261025.1 · 26ff936df038b6a62ec42cf18db27b2ea2bb8ec3
Check walker ancestor symlinks against the current root only
- A symlink in one root was skipped when its target was an ancestor of
another root, hiding files reachable only through it
- Fix and tests by @mabunemeh
Close #4944
reading declarations
Changes to src/reader_test.go. All files
@@ -1,6 +1,10 @@ package fzf import (+ "os"+ "path/filepath"+ "slices"+ "sync" "testing" "time" @@ -66,3 +70,70 @@ func TestReadFromCommand(t *testing.T) { t.Error("EvtReadFin should be set") } }++func walkFiles(t *testing.T, roots ...string) []string {+ t.Helper()+ var mu sync.Mutex+ files := []string{}+ reader := NewReader(func(data []byte) bool {+ mu.Lock()+ defer mu.Unlock()+ files = append(files, filepath.FromSlash(string(data)))+ return true+ }, util.NewEventBox(), nil, false, false)+ if !reader.readFiles(roots, walkerOpts{file: true, follow: true}, nil) {+ t.Fatal("file walk failed")+ }+ slices.Sort(files)+ return files+}++func TestReadFilesSymlinkAcrossRoots(t *testing.T) {+ base := t.TempDir()+ app := filepath.Join(base, "app")+ shared := filepath.Join(base, "shared")+ frontend := filepath.Join(shared, "frontend")+ os.MkdirAll(app, 0755)+ os.MkdirAll(frontend, 0755)+ os.WriteFile(filepath.Join(shared, "docs.txt"), nil, 0644)+ os.WriteFile(filepath.Join(frontend, "index.js"), nil, 0644)+ if err := os.Symlink(filepath.Join("..", "shared"), filepath.Join(app, "shared")); err != nil {+ t.Skipf("cannot create symlink: %v", err)+ }++ viaApp := []string{+ filepath.Join(app, "shared", "docs.txt"),+ filepath.Join(app, "shared", "frontend", "index.js"),+ }+ both := append(slices.Clone(viaApp), filepath.Join(frontend, "index.js"))+ slices.Sort(both)+ for _, tc := range []struct {+ roots []string+ want []string+ }{+ {[]string{app}, viaApp},+ {[]string{app, frontend}, both},+ {[]string{frontend, app}, both},+ } {+ if files := walkFiles(t, tc.roots...); !slices.Equal(files, tc.want) {+ t.Errorf("roots = %v, files = %v, want %v", tc.roots, files, tc.want)+ }+ }+}++func TestReadFilesSkipsAncestorSymlinks(t *testing.T) {+ base := t.TempDir()+ project := filepath.Join(base, "project")+ os.Mkdir(project, 0755)+ file := filepath.Join(project, "file.txt")+ os.WriteFile(file, nil, 0644)+ os.WriteFile(filepath.Join(base, "outside.txt"), nil, 0644)+ for name, target := range map[string]string{"parent": "..", "self": "."} {+ if err := os.Symlink(target, filepath.Join(project, name)); err != nil {+ t.Skipf("cannot create symlink: %v", err)+ }+ }+ if files := walkFiles(t, project); !slices.Equal(files, []string{file}) {+ t.Errorf("files = %v, want [%s]", files, file)+ }+}