Skip to content

Commit

Permalink
ignore invalid symlinks already in ListRecursive
Browse files Browse the repository at this point in the history
  • Loading branch information
Equanox committed Jan 20, 2023
1 parent 0f7992c commit 2b83060
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 141 deletions.
1 change: 1 addition & 0 deletions bob.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ build:
cmd: go mod tidy

lint:
input: "*"
cmd: CGO_ENABLED=0 golangci-lint run --timeout=10m0s

test:
Expand Down
33 changes: 16 additions & 17 deletions bobtask/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/benchkram/bob/bob/global"
"github.com/benchkram/bob/pkg/filepathutil"
"github.com/benchkram/bob/pkg/usererror"
"github.com/benchkram/errz"
)

Expand Down Expand Up @@ -41,13 +42,19 @@ func (t *Task) FilterInputs(wd string) (err error) {

// filteredInputs returns inputs filtered by ignores and file targets.
// Calls sanitize on the result.
func (t *Task) FilteredInputs(wd string) ([]string, error) {
func (t *Task) FilteredInputs(projectRoot string) (_ []string, err error) {

inputDirty := split(fmt.Sprintf("%s\n%s", t.InputDirty, defaultIgnores))
inputDirtyRooted := inputDirty
if t.dir != "." {
inputDirtyRooted = make([]string, len(inputDirty))
for i, input := range inputDirty {

err = t.sanitizeInput(input)
if err != nil {
return nil, usererror.Wrap(err)
}

// keep ignored in inputDirty
if strings.HasPrefix(input, "!") {
inputDirtyRooted[i] = "!" + filepath.Join(t.dir, strings.TrimPrefix(input, "!"))
Expand All @@ -64,7 +71,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
// Ignore starts with !
if strings.HasPrefix(input, "!") {
input = strings.TrimPrefix(input, "!")
list, err := filepathutil.ListRecursive(input)
list, err := filepathutil.ListRecursive(input, projectRoot)
if err != nil {
return nil, fmt.Errorf("failed to list input: %w", err)
}
Expand All @@ -73,7 +80,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
continue
}

list, err := filepathutil.ListRecursive(input)
list, err := filepathutil.ListRecursive(input, projectRoot)
if err != nil {
return nil, fmt.Errorf("failed to list input: %w", err)
}
Expand All @@ -84,7 +91,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
// Ignore file & dir targets stored in the same directory
if t.target != nil {
for _, path := range rooted(t.target.FilesystemEntriesRawPlain(), t.dir) {
info, err := os.Stat(path)
info, err := os.Lstat(path)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
continue
Expand All @@ -93,7 +100,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
}

if info.IsDir() {
list, err := filepathutil.ListRecursive(path)
list, err := filepathutil.ListRecursive(path, projectRoot)
if err != nil {
return nil, fmt.Errorf("failed to list input: %w", err)
}
Expand All @@ -107,7 +114,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
// Ignore additional items found during aggregation.
// Usually the targets of child tasks which are already rooted.
for _, path := range t.InputAdditionalIgnores {
info, err := os.Stat(path)
info, err := os.Lstat(path)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
continue
Expand All @@ -116,7 +123,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
}

if info.IsDir() {
list, err := filepathutil.ListRecursive(path)
list, err := filepathutil.ListRecursive(path, projectRoot)
if err != nil {
return nil, fmt.Errorf("failed to list input: %w", err)
}
Expand Down Expand Up @@ -145,15 +152,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
}
}

sanitizedInputs, err := t.sanitizeInputs(
filteredInputs,
optimisationOptions{},
)
if err != nil {
return nil, fmt.Errorf("failed to sanitize inputs: %w", err)
}

sort.Strings(sanitizedInputs)
sort.Strings(filteredInputs)

// fmt.Println(t.name)
// fmt.Println("Inputs:", inputs)
Expand All @@ -162,7 +161,7 @@ func (t *Task) FilteredInputs(wd string) ([]string, error) {
// fmt.Println("Sanitized:", sanitizedInputs)
// fmt.Println("Sorted:", sortedInputs)

return sanitizedInputs, nil
return filteredInputs, nil
}

func rooted(ss []string, prefix string) []string {
Expand Down
115 changes: 7 additions & 108 deletions bobtask/sanitize.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,118 +5,21 @@ import (
"strings"
)

type optimisationOptions struct {
// wd is the current working directory
// to avoid calls to os.Getwd.
wd string
}

// GOON TODO: FIXME: Think about resolve...

// sanitizeInputs assures that inputs are only cosidered when they are inside the project dir.
// Needs to be called with the current working directory set to the tasks working directory.
func (t *Task) sanitizeInputs(inputs []string, opts optimisationOptions) ([]string, error) {

// projectRoot, err := resolve(".", optimisationOptions{})
// if err != nil {
// return nil, fmt.Errorf("failed to resolve project root %q: %w", t.dir, err)
// }

// sanitized := make([]string, 0, len(inputs))
// resolved := make(map[string]struct{})
for _, f := range inputs {
//println("org: " + f)

if strings.Contains(f, "../") {
return nil, fmt.Errorf("'../' not allowed in file path %q", f)
}
func (t *Task) sanitizeInput(f string) error {

if strings.HasPrefix(f, "/") {
return nil, fmt.Errorf("'/' not allowed, use only inputs relative to the project root %q", f)
}

// resolvedPath, err := resolve(f, opts)
// if err != nil {
// if errors.Is(err, os.ErrNotExist) {
// log.Printf("failed to resolve %q: %v, ignoring\n", f, err)
// continue
// }
// return nil, fmt.Errorf("failed to resolve %q: %w", f, err)
// }

// if _, ok := resolved[resolvedPath]; !ok {
// if isOutsideOfProject(projectRoot, resolvedPath) {
// return nil, fmt.Errorf("file %q is outside of project [pr: %s]", resolvedPath, projectRoot)
// }

// resolved[resolvedPath] = struct{}{}
// sanitized = append(sanitized, resolvedPath)
if strings.Contains(f, "../") {
return fmt.Errorf("'../' not allowed in file path %q", f)
}

// println("res: " + resolvedPath)
// }
if strings.HasPrefix(f, "/") {
return fmt.Errorf("'/' not allowed, use only inputs relative to the project root %q", f)
}

return inputs, nil
return nil
}

// type absolutePathOrError struct {
// abs string
// err error
// }

// // absPathMap caches already resolved absolute paths.
// var absPathMap = sync.Map{}

// // resolve is a very basic implementation only preventing the inclusion of files outside of the project.
// // It is very likely still possible to include other files with malicious intention.
// func resolve(path string, opts optimisationOptions) (_ string, err error) {

// // var abs string
// // if filepath.IsAbs(path) {
// // abs = filepath.Clean(path)
// // } else {
// // if opts.wd != "" {
// // // use given wd to avoid calling os.Getwd() for each path.
// // abs = filepath.Join(opts.wd, path)
// // } else {
// // abs, err = filepath.Abs(path)
// // if err != nil {
// // return "", err
// // }
// // }

// // }

// // if aoe, ok := absPathMap.Load(abs); ok {
// // aoe := aoe.(absolutePathOrError)
// // return aoe.abs, aoe.err
// // }

// lstat, err := os.Lstat(path)
// if err != nil {
// return "", fmt.Errorf("lstat failed %q: %w", path, err)
// }

// // follow symlinks
// if lstat.Mode()&os.ModeSymlink != 0 {
// sym, err := filepath.EvalSymlinks(path)
// if err != nil {
// a := absolutePathOrError{"", fmt.Errorf("failed to follow symlink of %q: %w", path, err)}
// //absPathMap.Store(abs, a)
// return a.abs, a.err
// }

// // if isOutsideOfProject(opts.wd, sym) {
// // return nil, fmt.Errorf("file %q is outside of project [pr: %s]", resolvedPath, projectRoot)
// // }
// //absPathMap.Store(abs, absolutePathOrError{abs: sym, err: nil})
// return sym, nil
// }

// //absPathMap.Store(abs, absolutePathOrError{abs: abs, err: nil})
// return path, nil
// }

// sanitizeRebuild used to transform from dirty member to internal member
func (t *Task) sanitizeRebuild(s string) RebuildType {
switch strings.ToLower(s) {
Expand All @@ -128,7 +31,3 @@ func (t *Task) sanitizeRebuild(s string) RebuildType {
return RebuildOnChange
}
}

func isOutsideOfProject(root, f string) bool {
return !strings.HasPrefix(f, root)
}
Loading

0 comments on commit 2b83060

Please sign in to comment.