Skip to content

test(ls): regression test for -aRv recursing into ./.. (#13501)#13515

Open
Gooh456 wants to merge 1 commit into
uutils:mainfrom
Gooh456:test-ls-recursive-version-sort-13501
Open

test(ls): regression test for -aRv recursing into ./.. (#13501)#13515
Gooh456 wants to merge 1 commit into
uutils:mainfrom
Gooh456:test-ls-recursive-version-sort-13501

Conversation

@Gooh456

@Gooh456 Gooh456 commented Jul 22, 2026

Copy link
Copy Markdown

What this is

Test-only PR, no behavior change. Adds coverage for the bug in #13501 (ls -aRv recurses into the listed ./.. entries and walks all the way up to the filesystem root).

What I found

I went in expecting to write an actual fix, but the bug is already gone on main - just never closed out. Details:

  • Reproduced it for real against an actual 0.8.0 build (the version the reporter was on): ls -aRv on a small a/b/c tree walked straight past the fixture dir and started listing my actual home directory tree, exactly matching the "recurses up to filesystem root" behavior described in the issue.
  • Root cause in 0.8.0: ./.. get pushed into the entries buffer first, then the whole buffer gets sorted, then recursion does .skip(trim) assuming ./.. are still the first trim (2) entries after sorting. That assumption only holds for the default name sort (where ./.. happen to sort first anyway) - version sort (-v) doesn't keep them there, so the skip lands on the wrong entries and ./.. get treated as regular subdirectories to recurse into.
  • Built the same repro against current main - doesn't happen anymore. Traced it via git blame to refactor uu_ls so that crate users can call the ls without having to print everything to stdout #9851 (April 2026, an unrelated refactor of ls's directory traversal into an explicit stack for library-embedding purposes). That refactor replaced the position-based skip with an actual is_dot_dir flag checked per-entry at recursion time, which is correct regardless of sort order. Landed 12 days after the 0.8.0 release the issue was filed against, so the reporter's build predates the fix.

So there's nothing to fix in ls.rs itself. What was missing is test coverage for this exact case - I checked and no existing test exercises -a + -R + -v together, so this could regress again silently. This PR adds that one test.

Testing

  • Rebuilt ls from a real 0.8.0 checkout (via git worktree) and reproduced the bug for real (recursed all the way into my Windows home directory).
  • Confirmed the new test fails against that old logic and passes against current main.
  • Ran the full ls test module (cargo test --release --test tests -p coreutils --features ls test_ls::) before and after: same 28 pre-existing failures both times (all A required privilege is not held by the client - my Windows account can't create symlinks without dev mode/admin, unrelated to this change), no new failures, my new test passes.
  • rustfmt --check on the touched file: no diff introduced by my change (the file has some pre-existing formatting drift elsewhere from a rustfmt version mismatch, not touched here).

Disclosure: I used an AI coding assistant (Claude) to help investigate and write this, but did the actual verification (building 0.8.0 from source, reproducing the crash for real, bisecting to #9851, running the test suite) myself/directly, not just theorizing from reading the code.

ls -aRv used to recurse into the listed "." and ".." entries themselves,
walking all the way up past the filesystem root, when combined with -a
(show dot entries) and version-sort. Root cause: the old recursion code
pushed "."/".." at a fixed prefix of the entry vector and then skipped
that fixed prefix count after sorting - which only worked because the
default name sort happens to keep them first. Version sort (-v) doesn't,
so the skip landed on the wrong entries and "."/".." got treated as
regular subdirectories to recurse into.

This was already fixed on main as a side effect of the unrelated
"enter_directory" traversal refactor in uutils#9851, which replaced the
position-based skip with an explicit is_dot_dir flag on each entry
that's checked at recursion time regardless of sort order (landed
2026-04-17, 12 days after the 0.8.0 release the issue was filed
against - the reporter just hadn't picked up a newer build yet).
Verified directly: reproduced the walk-up-to-root behavior with a real
0.8.0 build, confirmed it's gone on current main, and confirmed via
git blame + testing the actual pre-refactor code that the position-
based skip is the real cause.

No behavior change here, just adds coverage so this can't silently
regress: the case is not covered by any existing test.
@Gooh456
Gooh456 force-pushed the test-ls-recursive-version-sort-13501 branch from 2f727ec to 8fa9d17 Compare July 23, 2026 11:02
@codspeed-hq

codspeed-hq Bot commented Jul 23, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 3.55%

⚡ 1 improved benchmark
✅ 338 untouched benchmarks
⏩ 46 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation ls_recursive_balanced_tree[(6, 4, 15)] 51.2 ms 49.4 ms +3.55%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing Gooh456:test-ls-recursive-version-sort-13501 (8fa9d17) with main (651466e)

Open in CodSpeed

Footnotes

  1. 46 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

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.

1 participant