]> Cypherpunks repositories - gostls13.git/commitdiff
os: prevent infinite symlink loop of Stat on Windows
authorHiroshi Ioka <hirochachacha@gmail.com>
Thu, 18 Aug 2016 07:10:28 +0000 (16:10 +0900)
committerAlex Brainman <alex.brainman@gmail.com>
Fri, 26 Aug 2016 05:58:01 +0000 (05:58 +0000)
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>
src/os/os_test.go
src/os/stat_windows.go

index 0c4042a4bf3b8ff04c462ee7629388823c0cab9c..fb392b52cda309ca7792ad77de108f75e3b317cd 100644 (file)
@@ -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)
+       }
+}
index 3c433b1579b75cca02dd720ee14a2638ddb4c2f0..c14abc7c4138af0cb720906303758baa68cc578a 100644 (file)
@@ -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.