aboutsummaryrefslogtreecommitdiff
path: root/src/os
diff options
context:
space:
mode:
authorHiroshi Ioka <hirochachacha@gmail.com>2016-08-18 16:10:28 +0900
committerAlex Brainman <alex.brainman@gmail.com>2016-08-26 05:58:01 +0000
commit2eb46e8c57c4dab0197ca82d9899fa1356500fc0 (patch)
treed6b677fc60ae8235121b6b3c2e09fee1ee2c2160 /src/os
parent5a6f973565ccb54c77e03cbb4844fd0ea392d3fe (diff)
downloadgo-2eb46e8c57c4dab0197ca82d9899fa1356500fc0.tar.xz
os: prevent infinite symlink loop of Stat on Windows
The Windows version of Stat calls Readlink iteratively until reaching a non-symlink file. If the given file is a circular symlink, It never stops. This CL defines the maximum number of symlink loop count. If the loop count will exceed that number, Stat will return error. Fixes #16538 Change-Id: Ia9f3f2259a8d32801461c5041cc24a34f9f81009 Reviewed-on: https://go-review.googlesource.com/27580 TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Diffstat (limited to 'src/os')
-rw-r--r--src/os/os_test.go23
-rw-r--r--src/os/stat_windows.go3
2 files changed, 25 insertions, 1 deletions
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 0c4042a4bf..fb392b52cd 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -1812,3 +1812,26 @@ func TestRemoveAllRace(t *testing.T) {
close(hold) // let workers race to remove root
wg.Wait()
}
+
+func TestStatSymlinkLoop(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ defer chtmpdir(t)()
+
+ err := Symlink("x", "y")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer Remove("y")
+
+ err = Symlink("y", "x")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer Remove("x")
+
+ _, err = Stat("x")
+ if perr, ok := err.(*PathError); !ok || perr.Err != syscall.ELOOP {
+ t.Errorf("expected *PathError with ELOOP, got %T: %v\n", err, err)
+ }
+}
diff --git a/src/os/stat_windows.go b/src/os/stat_windows.go
index 3c433b1579..c14abc7c41 100644
--- a/src/os/stat_windows.go
+++ b/src/os/stat_windows.go
@@ -61,7 +61,7 @@ func (file *File) Stat() (FileInfo, error) {
func Stat(name string) (FileInfo, error) {
var fi FileInfo
var err error
- for {
+ for i := 0; i < 255; i++ {
fi, err = Lstat(name)
if err != nil {
return fi, err
@@ -74,6 +74,7 @@ func Stat(name string) (FileInfo, error) {
return fi, err
}
}
+ return nil, &PathError{"Stat", name, syscall.ELOOP}
}
// Lstat returns the FileInfo structure describing the named file.