]> Cypherpunks repositories - gostls13.git/commitdiff
os: permit RemoveAll with paths that end in ".."
authorIan Lance Taylor <iant@golang.org>
Tue, 20 Nov 2018 18:15:14 +0000 (10:15 -0800)
committerIan Lance Taylor <iant@golang.org>
Tue, 20 Nov 2018 19:33:17 +0000 (19:33 +0000)
Prohibiting RemoveAll with paths that end in ".." was added with
CL 137442 in this release cycle, but it worked before and it should
continue to work.

Also run TestRemoveAllDot on all systems; the test is not specific to
the use of unlinkat and friends.

Change-Id: I277784c8915cd748fec318d2936062440d5d1fde
Reviewed-on: https://go-review.googlesource.com/c/150497
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
src/os/removeall_at.go
src/os/removeall_test.go

index 5aa1b46117158c6575c8514a2437301b99876eea..5eea770a3e715759db6f0304b0b181b384b79ebf 100644 (file)
@@ -19,7 +19,8 @@ func RemoveAll(path string) error {
                return nil
        }
 
-       // Not allowed in unix
+       // The rmdir system call does not permit removing ".",
+       // so we don't permit it either.
        if endsWithDot(path) {
                return syscall.EINVAL
        }
@@ -130,16 +131,13 @@ func openFdAt(fd int, path string) (*File, error) {
        return NewFile(uintptr(fd), path), nil
 }
 
+// endsWithDot returns whether the final component of path is ".".
 func endsWithDot(path string) bool {
-       if path == "." || path == ".." {
+       if path == "." {
                return true
        }
-       if len(path) >= 2 && path[len(path)-2:] == "/." {
+       if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
                return true
        }
-       if len(path) >= 3 && path[len(path)-3:] == "/.." {
-               return true
-       }
-
        return false
 }
index fd3b8d22f980de8bce5092af42ad9e793f1f2166..1c9f16322547ae19389a852521fc702e09dbd019 100644 (file)
@@ -215,13 +215,6 @@ func TestRemoveAllLongPath(t *testing.T) {
 }
 
 func TestRemoveAllDot(t *testing.T) {
-       switch runtime.GOOS {
-       case "aix", "darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
-               break
-       default:
-               t.Skip("skipping for not implemented platforms")
-       }
-
        prevDir, err := Getwd()
        if err != nil {
                t.Fatalf("Could not get wd: %s", err)
@@ -242,13 +235,32 @@ func TestRemoveAllDot(t *testing.T) {
                t.Errorf("RemoveAll succeed to remove .")
        }
 
-       err = RemoveAll("..")
-       if err == nil {
-               t.Errorf("RemoveAll succeed to remove ..")
-       }
-
        err = Chdir(prevDir)
        if err != nil {
                t.Fatalf("Could not chdir %s: %s", prevDir, err)
        }
 }
+
+func TestRemoveAllDotDot(t *testing.T) {
+       t.Parallel()
+
+       tempDir, err := ioutil.TempDir("", "TestRemoveAllDotDot-")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer RemoveAll(tempDir)
+
+       subdir := filepath.Join(tempDir, "x")
+       subsubdir := filepath.Join(subdir, "y")
+       if err := MkdirAll(subsubdir, 0777); err != nil {
+               t.Fatal(err)
+       }
+       if err := RemoveAll(filepath.Join(subsubdir, "..")); err != nil {
+               t.Error(err)
+       }
+       for _, dir := range []string{subsubdir, subdir} {
+               if _, err := Stat(dir); err == nil {
+                       t.Errorf("%s: exists after RemoveAll", dir)
+               }
+       }
+}