Skip to content

memfs: Reject ReadDir calls on regular files - #247

Merged
pjbgf merged 1 commit into
go-git:mainfrom
Aryangupta-05:fix/memfs-readdir-file-error
Oct 16, 2026
Merged

pjbgf merged 1 commit into
go-git:mainfrom
Aryangupta-05:fix/memfs-readdir-file-error

Conversation

@Aryangupta-05

Copy link
Copy Markdown
Contributor

memfs.ReadDir currently returns an empty result and no error for a regular file. Callers cannot distinguish that invalid directory path from an empty directory, unlike the OS-backed filesystem and the documented billy.Dir contract.

Return a *os.PathError wrapping syscall.ENOTDIR after resolving symlinks. The shared directory-conformance test compares the same call through memfs and osfs. A memfs regression also checks that a link to a file is rejected while a link to a directory remains readable.

Minimal reproduction:

fs := memfs.New()
f, err := fs.Create("file")
if err != nil {
    panic(err)
}
if err := f.Close(); err != nil {
    panic(err)
}
entries, err := fs.ReadDir("file")
fmt.Printf("entries=%v error=%v\n", entries, err)

Before: empty entries, nil error. After: nil entries and a non-nil path error. The OS-backed regression passed before the change; the memfs and symlink-to-file regressions failed before and pass after.

Validation on Windows / Go 1.26.8:

  • go test ./memfs -count=1
  • go test ./test -run '^TestDir_' -count=1
  • go vet ./memfs ./test, gofmt and git diff --check
  • Pinned golangci-lint 2.14.0: no newly introduced issues with --new-from-rev=eae82c9f2d37fb502d080eef0ab6bc1655501985.

Full-suite limitations were checked against a separate clean snapshot of the same upstream revision: both runs hit existing Windows symlink-privilege failures and the 45-second bound in the large TempFileMany stress test. Full lint reports unrelated findings in unchanged files on both snapshots; full vet flags the existing osfs.WriteTo signature. A full-suite pass or race-test pass is not claimed; the local C compiler could not start.

AI assistance: OpenAI Codex (GPT-6) assisted with investigation, implementation, regression tests, validation and this description. The commit includes an Assisted-by trailer and DCO sign-off.

Returning an empty directory listing for a regular file hides invalid
paths from callers and differs from the OS-backed filesystem. Check the
target mode after resolving symlinks and return a PathError wrapping
ENOTDIR.

Add a shared filesystem regression and memfs coverage for symlinks to
files and directories.

Assisted-by: OpenAI Codex (GPT-6)
Signed-off-by: Aryan <aryangupta050903@gmail.com>

@pjbgf pjbgf left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Aryangupta-05 thank you for working on this. 🙇

@pjbgf
pjbgf merged commit fd38f5a into go-git:main Oct 16, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants