139 lines
2.8 KiB
Go
139 lines
2.8 KiB
Go
package safepath
|
||||
|
|
|
|||
|
|
import (
|
|||
|
|
"errors"
|
|||
|
|
"path/filepath"
|
|||
|
|
"testing"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
func TestValidateRelative(t *testing.T) {
|
|||
|
|
valid := []string{
|
|||
|
|
"JsonParser.exe",
|
|||
|
|
"bin/JsonParser.exe",
|
|||
|
|
"工具/解析器.exe",
|
|||
|
|
".config/settings.json",
|
|||
|
|
"name..txt",
|
|||
|
|
"folder with spaces/read me.txt",
|
|||
|
|
}
|
|||
|
|
for _, value := range valid {
|
|||
|
|
t.Run("valid_"+value, func(t *testing.T) {
|
|||
|
|
if err := ValidateRelative(value); err != nil {
|
|||
|
|
t.Fatalf("ValidateRelative(%q) error = %v", value, err)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
invalid := []string{
|
|||
|
|
"",
|
|||
|
|
".",
|
|||
|
|
"..",
|
|||
|
|
"../escape.exe",
|
|||
|
|
"a/../escape.exe",
|
|||
|
|
"./App.exe",
|
|||
|
|
"a//App.exe",
|
|||
|
|
"a/",
|
|||
|
|
"/App.exe",
|
|||
|
|
"//server/share/App.exe",
|
|||
|
|
`C:/App.exe`,
|
|||
|
|
`C:App.exe`,
|
|||
|
|
`bin\App.exe`,
|
|||
|
|
"bad\x00name.exe",
|
|||
|
|
"bad\nname.exe",
|
|||
|
|
"bad<name.exe",
|
|||
|
|
"bad>name.exe",
|
|||
|
|
`bad"name.exe`,
|
|||
|
|
"bad|name.exe",
|
|||
|
|
"bad?name.exe",
|
|||
|
|
"bad*name.exe",
|
|||
|
|
"folder./App.exe",
|
|||
|
|
"folder /App.exe",
|
|||
|
|
" App.exe",
|
|||
|
|
"folder/ App.exe",
|
|||
|
|
"App.exe.",
|
|||
|
|
"App.exe ",
|
|||
|
|
"CON",
|
|||
|
|
"con.txt",
|
|||
|
|
"PRN.json",
|
|||
|
|
"AUX",
|
|||
|
|
"NUL.bin",
|
|||
|
|
"NUL .bin",
|
|||
|
|
"COM1",
|
|||
|
|
"com9.log",
|
|||
|
|
"LPT1",
|
|||
|
|
"lpt9.txt",
|
|||
|
|
"COM¹",
|
|||
|
|
"LPT³.log",
|
|||
|
|
"CLOCK$",
|
|||
|
|
"CONIN$",
|
|||
|
|
"CONOUT$",
|
|||
|
|
}
|
|||
|
|
for _, value := range invalid {
|
|||
|
|
t.Run("invalid_"+value, func(t *testing.T) {
|
|||
|
|
err := ValidateRelative(value)
|
|||
|
|
if !errors.Is(err, ErrInvalidRelativePath) {
|
|||
|
|
t.Fatalf(
|
|||
|
|
"ValidateRelative(%q) error = %v, want %v",
|
|||
|
|
value,
|
|||
|
|
err,
|
|||
|
|
ErrInvalidRelativePath,
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func TestValidateWorkingDirectory(t *testing.T) {
|
|||
|
|
for _, value := range []string{".", "bin", "资源/运行目录"} {
|
|||
|
|
if err := ValidateWorkingDirectory(value); err != nil {
|
|||
|
|
t.Fatalf("ValidateWorkingDirectory(%q) error = %v", value, err)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
for _, value := range []string{"", "..", "bin.", "NUL"} {
|
|||
|
|
if err := ValidateWorkingDirectory(value); !errors.Is(err, ErrInvalidRelativePath) {
|
|||
|
|
t.Fatalf(
|
|||
|
|
"ValidateWorkingDirectory(%q) error = %v, want %v",
|
|||
|
|
value,
|
|||
|
|
err,
|
|||
|
|
ErrInvalidRelativePath,
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func TestCollisionKeyUsesUnicodeSimpleFold(t *testing.T) {
|
|||
|
|
tests := [][2]string{
|
|||
|
|
{"App.EXE", "app.exe"},
|
|||
|
|
{"K.exe", "K.exe"},
|
|||
|
|
{"Σ.txt", "ς.txt"},
|
|||
|
|
}
|
|||
|
|
for _, values := range tests {
|
|||
|
|
if CollisionKey(values[0]) != CollisionKey(values[1]) {
|
|||
|
|
t.Fatalf(
|
|||
|
|
"CollisionKey(%q) != CollisionKey(%q)",
|
|||
|
|
values[0],
|
|||
|
|
values[1],
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func TestJoinUnder(t *testing.T) {
|
|||
|
|
root := filepath.Join(t.TempDir(), "staging")
|
|||
|
|
target, err := JoinUnder(root, "bin/App.exe")
|
|||
|
|
if err != nil {
|
|||
|
|
t.Fatalf("JoinUnder() error = %v", err)
|
|||
|
|
}
|
|||
|
|
want := filepath.Join(root, "bin", "App.exe")
|
|||
|
|
if target != want {
|
|||
|
|
t.Fatalf("JoinUnder() = %q, want %q", target, want)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for _, value := range []string{"../escape.exe", ".. /escape.exe", "/escape.exe"} {
|
|||
|
|
_, err := JoinUnder(root, value)
|
|||
|
|
if !errors.Is(err, ErrInvalidRelativePath) &&
|
|||
|
|
!errors.Is(err, ErrOutsideRoot) {
|
|||
|
|
t.Fatalf("JoinUnder(%q) error = %v", value, err)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|