Skip to content

fix: --stats printed the u128 sentinel as the smallest file size - #372

Open
VXNCXNX wants to merge 1 commit into
Byron:mainfrom
VXNCXNX:fix/smallest-file-sentinel-leak
Open

fix: --stats printed the u128 sentinel as the smallest file size#372
VXNCXNX wants to merge 1 commit into
Byron:mainfrom
VXNCXNX:fix/smallest-file-sentinel-leak

Conversation

@VXNCXNX

@VXNCXNX VXNCXNX commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

--stats on a path it cannot read prints the internal sentinel as the smallest file size.

$ dua aggregate --stats /tmp/nope
      0   B /tmp/nope  <1 IO Error>

before: Statistics { entries_traversed: 1, smallest_file_in_bytes: 340282366920938463463374607431768211455, largest_file_in_bytes: 0 }
after:  Statistics { entries_traversed: 1, smallest_file_in_bytes: 0, largest_file_in_bytes: 0 }

That number is u128::MAX, the starting value used so the first real file wins the minimum.

Cause

The reset was guarded by the wrong condition:

if stats.entries_traversed == 0 {
    stats.smallest_file_in_bytes = 0;
}

An entry whose metadata cannot be read still increments entries_traversed, but never contributes a size. So the counter says "we saw something" while the minimum was never set, and the sentinel survives into the output.

The fix

Check the sentinel itself rather than inferring it from the counter:

if stats.smallest_file_in_bytes == u128::MAX {

That is true exactly when no size was ever observed, which is the condition the reset actually wants. It also still covers the original empty-traversal case, so nothing is lost.

Verification

unreadable_roots_do_not_leak_the_smallest_file_sentinel in src/aggregate.rs, #[cfg(unix)] since it needs a path that fails to stat.

Reverting only the condition fails it:

assertion `left == right` failed: no file size was ever observed, so the sentinel must not be reported as a size
  left: 340282366920938463463374607431768211455
 right: 0

cargo test is 27 + 73 passed, cargo clippy --all-targets is clean, and tests/stateless-journey.sh exits 0 with no snapshot changes needed, since the existing stats snapshots all traverse real files.

Tested on Linux. Nothing platform-specific was touched.

Disclosure: written with AI assistance (Claude Code). I built binaries before and after and produced the output above by running them, and ran the mutation check and the journey suite myself.

The sentinel reset was guarded by entries_traversed == 0, but an entry
whose metadata cannot be read still counts as traversed while never
contributing a size. Reset when the sentinel is still in place instead.
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