From 3bda5fc840870f6589e4bdbcbbdc811bde599969 Mon Sep 17 00:00:00 2001 From: Alexander Kernozhitsky Date: Mon, 27 May 2024 11:01:13 +0200 Subject: [PATCH] Handle arbitrarily long symlink target in `expandSymlinks()` (#23650) For now, `expandSymlinks()` can handle only symlinks with lengths up to 1024. We can improve this logic and retry inside a loop with increasing lengths until we succeed. The same approach is used in [Go](https://github.com/golang/go/blob/377646589d5fb0224014683e0d1f1db35e60c3ac/src/os/file_unix.go#L446), [Rust](https://github.com/rust-lang/rust/blob/785eb65377e5d7f8d8e8b82ede044212bbd2d76e/library/std/src/sys/pal/unix/fs.rs#L1700) and [Nim's `getCurrentDir()`](https://github.com/nim-lang/Nim/blob/devel/lib/std/private/ospaths2.nim#L877), so maybe it's a good idea to use the same logic in `expandSymlinks()` also. --- lib/std/private/ossymlinks.nim | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/std/private/ossymlinks.nim b/lib/std/private/ossymlinks.nim index c0774b5735c1..c1760c42ec56 100644 --- a/lib/std/private/ossymlinks.nim +++ b/lib/std/private/ossymlinks.nim @@ -66,11 +66,13 @@ proc expandSymlink*(symlinkPath: string): string {.noWeirdTarget.} = when defined(windows) or defined(nintendoswitch): result = symlinkPath else: - result = newString(maxSymlinkLen) - var len = readlink(symlinkPath, result.cstring, maxSymlinkLen) - if len < 0: - raiseOSError(osLastError(), symlinkPath) - if len > maxSymlinkLen: - result = newString(len+1) - len = readlink(symlinkPath, result.cstring, len) - setLen(result, len) + var bufLen = 1024 + while true: + result = newString(bufLen) + let len = readlink(symlinkPath.cstring, result.cstring, bufLen) + if len < 0: + raiseOSError(osLastError(), symlinkPath) + if len < bufLen: + result.setLen(len) + break + bufLen = bufLen shl 1