2026-04-10 03:25:23 -03:00
|
|
|
package internal
|
|
|
|
|
|
|
|
|
|
import (
|
2026-04-11 00:02:59 -03:00
|
|
|
"errors"
|
2026-04-10 03:25:23 -03:00
|
|
|
"path/filepath"
|
|
|
|
|
"testing"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestSafeJoinWithinRoot(t *testing.T) {
|
|
|
|
|
root := t.TempDir()
|
|
|
|
|
got, err := SafeJoin(root, "folder/file.txt")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("SafeJoin failed: %v", err)
|
|
|
|
|
}
|
|
|
|
|
want := filepath.Join(root, "folder", "file.txt")
|
|
|
|
|
if got != want {
|
|
|
|
|
t.Fatalf("SafeJoin mismatch got=%q want=%q", got, want)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSafeJoinRejectsEscape(t *testing.T) {
|
|
|
|
|
root := t.TempDir()
|
|
|
|
|
if _, err := SafeJoin(root, "../etc/passwd"); err == nil {
|
|
|
|
|
t.Fatalf("expected escape rejection")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSafeJoinAllowsRoot(t *testing.T) {
|
|
|
|
|
root := t.TempDir()
|
|
|
|
|
got, err := SafeJoin(root, "")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("SafeJoin root failed: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if got != root {
|
|
|
|
|
t.Fatalf("expected root path %q got %q", root, got)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-11 00:02:59 -03:00
|
|
|
|
|
|
|
|
func TestSafeJoinAbsError(t *testing.T) {
|
|
|
|
|
origAbs := absPath
|
|
|
|
|
defer func() { absPath = origAbs }()
|
|
|
|
|
|
|
|
|
|
absPath = func(string) (string, error) {
|
|
|
|
|
return "", errors.New("boom")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if _, err := SafeJoin(t.TempDir(), "child"); err == nil {
|
|
|
|
|
t.Fatalf("expected abs-path error")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSafeJoinRejectsSiblingPrefix(t *testing.T) {
|
|
|
|
|
origAbs := absPath
|
|
|
|
|
defer func() { absPath = origAbs }()
|
|
|
|
|
|
|
|
|
|
absPath = func(p string) (string, error) {
|
|
|
|
|
switch p {
|
|
|
|
|
case "/root":
|
|
|
|
|
return "/root", nil
|
|
|
|
|
case "/root/child":
|
|
|
|
|
return "/rootx/child", nil
|
|
|
|
|
default:
|
|
|
|
|
return p, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if _, err := SafeJoin("/root", "child"); err == nil {
|
|
|
|
|
t.Fatalf("expected sibling-prefix rejection")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSafeJoinRejectsRootAbsError(t *testing.T) {
|
|
|
|
|
origAbs := absPath
|
|
|
|
|
defer func() { absPath = origAbs }()
|
|
|
|
|
|
|
|
|
|
absPath = func(p string) (string, error) {
|
|
|
|
|
if p == "/root" {
|
|
|
|
|
return "", errors.New("root failed")
|
|
|
|
|
}
|
|
|
|
|
return p, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if _, err := SafeJoin("/root", "child"); err == nil {
|
|
|
|
|
t.Fatalf("expected root abs-path error")
|
|
|
|
|
}
|
|
|
|
|
}
|