Avoid filepath.Abs
filepath.Abs is surprisingly expensive, it calls os.Getwd every time, which involves multiple syscalls, a lock, and and allocations. Use IsAbs and prefix matching instead. Test: paths_test.go Change-Id: Ia6cf34d6bef24c694702af1e7a6ff08ffd2d822b
This commit is contained in:
parent
590b1ae37c
commit
7b3dcc31eb
|
@ -503,16 +503,9 @@ func safePathForSource(ctx PathContext, pathComponents ...string) (SourcePath, e
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
abs, err := filepath.Abs(ret.String())
|
// absolute path already checked by validateSafePath
|
||||||
if err != nil {
|
if strings.HasPrefix(ret.String(), ctx.Config().buildDir) {
|
||||||
return ret, err
|
return ret, fmt.Errorf("source path %s is in output", ret.String())
|
||||||
}
|
|
||||||
buildroot, err := filepath.Abs(ctx.Config().buildDir)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(abs, buildroot) {
|
|
||||||
return ret, fmt.Errorf("source path %s is in output", abs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, err
|
return ret, err
|
||||||
|
@ -526,16 +519,9 @@ func pathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
abs, err := filepath.Abs(ret.String())
|
// absolute path already checked by validatePath
|
||||||
if err != nil {
|
if strings.HasPrefix(ret.String(), ctx.Config().buildDir) {
|
||||||
return ret, err
|
return ret, fmt.Errorf("source path %s is in output", ret.String())
|
||||||
}
|
|
||||||
buildroot, err := filepath.Abs(ctx.Config().buildDir)
|
|
||||||
if err != nil {
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(abs, buildroot) {
|
|
||||||
return ret, fmt.Errorf("source path %s is in output", abs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
|
@ -630,3 +630,64 @@ func TestMaybeRel(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPathForSource(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
buildDir string
|
||||||
|
src string
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normal",
|
||||||
|
buildDir: "out",
|
||||||
|
src: "a/b/c",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abs",
|
||||||
|
buildDir: "out",
|
||||||
|
src: "/a/b/c",
|
||||||
|
err: "is outside directory",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "in out dir",
|
||||||
|
buildDir: "out",
|
||||||
|
src: "out/a/b/c",
|
||||||
|
err: "is in output",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
funcs := []struct {
|
||||||
|
name string
|
||||||
|
f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
|
||||||
|
}{
|
||||||
|
{"pathForSource", pathForSource},
|
||||||
|
{"safePathForSource", safePathForSource},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range funcs {
|
||||||
|
t.Run(f.name, func(t *testing.T) {
|
||||||
|
for _, test := range testCases {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
testConfig := TestConfig(test.buildDir, nil)
|
||||||
|
ctx := &configErrorWrapper{config: testConfig}
|
||||||
|
_, err := f.f(ctx, test.src)
|
||||||
|
if len(ctx.errors) > 0 {
|
||||||
|
t.Fatalf("unexpected errors %v", ctx.errors)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
if test.err == "" {
|
||||||
|
t.Fatalf("unexpected error %q", err.Error())
|
||||||
|
} else if !strings.Contains(err.Error(), test.err) {
|
||||||
|
t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if test.err != "" {
|
||||||
|
t.Fatalf("missing error %q", test.err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue