Skip to content

Commit

Permalink
Handle arbitrarily long symlink target in expandSymlinks() (#23650)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alex65536 authored May 27, 2024
1 parent ce85b81 commit 3bda5fc
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions lib/std/private/ossymlinks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 3bda5fc

Please sign in to comment.