From a6f3d454388d2788dab71c5795d41e2843934225 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Tue, 25 Jun 2024 13:19:05 +1000 Subject: [PATCH] *: switch to golang.org/x/sys/unix Go modules mean adding dependencies is less painful than it was when we started this project, and we will need some syscalls from unix for implementing a safe MkdirAll. Signed-off-by: Aleksa Sarai --- go.mod | 2 ++ go.sum | 2 ++ join.go | 7 ++++--- join_test.go | 23 ++++++++++++----------- 4 files changed, 20 insertions(+), 14 deletions(-) create mode 100644 go.sum diff --git a/go.mod b/go.mod index 0607c1f..e13c3d3 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/cyphar/filepath-securejoin go 1.13 + +require golang.org/x/sys v0.21.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ac7fb31 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/join.go b/join.go index 324ab1b..59c8533 100644 --- a/join.go +++ b/join.go @@ -15,7 +15,8 @@ import ( "os" "path/filepath" "strings" - "syscall" + + "golang.org/x/sys/unix" ) const maxSymlinkLimit = 255 @@ -26,7 +27,7 @@ const maxSymlinkLimit = 255 func IsNotExist(err error) bool { // Check that it's not actually an ENOTDIR, which in some cases is a more // convoluted case of ENOENT (usually involving weird paths). - return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT) + return errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.ENOTDIR) || errors.Is(err, unix.ENOENT) } // SecureJoinVFS joins the two given path components (similar to Join) except @@ -97,7 +98,7 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) { // to the yet-unparsed path. linksWalked++ if linksWalked > maxSymlinkLimit { - return "", &os.PathError{Op: "SecureJoin", Path: root + string(filepath.Separator) + unsafePath, Err: syscall.ELOOP} + return "", &os.PathError{Op: "SecureJoin", Path: root + string(filepath.Separator) + unsafePath, Err: unix.ELOOP} } dest, err := vfs.Readlink(fullPath) diff --git a/join_test.go b/join_test.go index ef081d6..28597c5 100644 --- a/join_test.go +++ b/join_test.go @@ -10,8 +10,9 @@ import ( "os" "path/filepath" "runtime" - "syscall" "testing" + + "golang.org/x/sys/unix" ) // TODO: These tests won't work on plan9 because it doesn't have symlinks, and @@ -197,7 +198,7 @@ func TestSymlinkLoop(t *testing.T) { {dir, "/self/././.."}, } { got, err := SecureJoin(test.root, test.unsafe) - if !errors.Is(err, syscall.ELOOP) { + if !errors.Is(err, unix.ELOOP) { t.Errorf("securejoin(%q, %q): expected ELOOP, got %q & %v", test.root, test.unsafe, got, err) continue } @@ -241,15 +242,15 @@ func TestIsNotExist(t *testing.T) { err error expected bool }{ - {&os.PathError{Op: "test1", Err: syscall.ENOENT}, true}, - {&os.LinkError{Op: "test1", Err: syscall.ENOENT}, true}, - {&os.SyscallError{Syscall: "test1", Err: syscall.ENOENT}, true}, - {&os.PathError{Op: "test2", Err: syscall.ENOTDIR}, true}, - {&os.LinkError{Op: "test2", Err: syscall.ENOTDIR}, true}, - {&os.SyscallError{Syscall: "test2", Err: syscall.ENOTDIR}, true}, - {&os.PathError{Op: "test3", Err: syscall.EACCES}, false}, - {&os.LinkError{Op: "test3", Err: syscall.EACCES}, false}, - {&os.SyscallError{Syscall: "test3", Err: syscall.EACCES}, false}, + {&os.PathError{Op: "test1", Err: unix.ENOENT}, true}, + {&os.LinkError{Op: "test1", Err: unix.ENOENT}, true}, + {&os.SyscallError{Syscall: "test1", Err: unix.ENOENT}, true}, + {&os.PathError{Op: "test2", Err: unix.ENOTDIR}, true}, + {&os.LinkError{Op: "test2", Err: unix.ENOTDIR}, true}, + {&os.SyscallError{Syscall: "test2", Err: unix.ENOTDIR}, true}, + {&os.PathError{Op: "test3", Err: unix.EACCES}, false}, + {&os.LinkError{Op: "test3", Err: unix.EACCES}, false}, + {&os.SyscallError{Syscall: "test3", Err: unix.EACCES}, false}, {errors.New("not a proper error"), false}, } { got := IsNotExist(test.err)