diff options
| author | Hiroshi Ioka <hirochachacha@gmail.com> | 2016-10-16 13:25:53 +0900 |
|---|---|---|
| committer | Alex Brainman <alex.brainman@gmail.com> | 2016-10-19 01:25:18 +0000 |
| commit | e65bce7144dbced232df8842ef6825d7e45f094e (patch) | |
| tree | 7f51f524a9607280447df66b708a1325f260ee1e /src/syscall/syscall_windows.go | |
| parent | ebf827ded7d6997747c96ae8f0f4871c15090d49 (diff) | |
| download | go-e65bce7144dbced232df8842ef6825d7e45f094e.tar.xz | |
os, syscall: fix incorrect offset calculation in Readlink on windows
Current implementation of syscall.Readlink mistakenly calculates
the end offset of the PrintName field.
Also, there are some cases that the PrintName field is empty.
Instead, the CL uses SubstituteName with correct calculation.
Fixes #15978
Fixes #16145
Change-Id: If3257137141129ac1c552d003726d5b9c08bb754
Reviewed-on: https://go-review.googlesource.com/31118
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/syscall/syscall_windows.go')
| -rw-r--r-- | src/syscall/syscall_windows.go | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index e13d6e2dd5..f4f8f3ad09 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -1024,11 +1024,31 @@ func Readlink(path string, buf []byte) (n int, err error) { case IO_REPARSE_TAG_SYMLINK: data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) - s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2]) + s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2]) + if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 { + if len(s) >= 4 && s[:4] == `\??\` { + s = s[4:] + switch { + case len(s) >= 2 && s[1] == ':': // \??\C:\foo\bar + // do nothing + case len(s) >= 4 && s[:4] == `UNC\`: // \??\UNC\foo\bar + s = `\\` + s[4:] + default: + // unexpected; do nothing + } + } else { + // unexpected; do nothing + } + } case _IO_REPARSE_TAG_MOUNT_POINT: data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer)) p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0])) - s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2]) + s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2]) + if len(s) >= 4 && s[:4] == `\??\` { // \??\C:\foo\bar + s = s[4:] + } else { + // unexpected; do nothing + } default: // the path is not a symlink or junction but another type of reparse // point |
