Skip to content

fix(tests): stop git corrupting the decmpfs fixtures on Windows checkout - #8

Closed
h4x0r wants to merge 2 commits into
mainfrom
fix/crlf-fixtures
Closed

fix(tests): stop git corrupting the decmpfs fixtures on Windows checkout#8
h4x0r wants to merge 2 commits into
mainfrom
fix/crlf-fixtures

Conversation

@h4x0r

@h4x0r h4x0r commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Seven decmpfs tests failed only on windows-latest. Decompression itself was
fine -- the output was the expected perl script -- so the corruption was in
the fixture bytes, not the decoder.

Cause: the repo had no .gitattributes, so git applied its text/binary
autodetection to byte-exact forensic evidence. core.autocrlf is true by
default on windows-latest, so every file git judged "text" had its LF bytes
rewritten to CRLF at checkout, and the tests then compared against corrupted
evidence.

Git scans only the first 8000 bytes for a NUL when making that call, so this
was not confined to the .expected files -- it also hit a compressed INPUT
whose first NUL falls past that window. Comparing a simulated windows-latest
checkout against the stored blobs shows 7 of 15 decmpfs fixtures altered:

lzvn.expected 80000 -> 87855 zlib.expected 150000 -> 164122
real_zlib_inline.expected 2000 -> 2218 zlib_inline.expected 3000 -> 3325
tahoe_type8.expected 1936 -> 1994 zlib_type3_stored.payload
tahoe_type9.expected 63 -> 71 3001 -> 3326

Marking the data trees -text fixes the class rather than the seven failing
tests, and covers fixtures added later. No test or source file is touched.

Verified against git's own mechanism rather than by waiting on CI, since the
mechanism is git's and not the OS's -- git -c core.autocrlf=true clone
reproduces the runner's checkout on any platform:

before 7 fixtures differ from their stored blobs; 19 passed, 7 failed
after 0 fixtures differ; 26 passed, 0 failed

The seven altered fixtures correspond one-to-one with the seven failing
tests. Both runs use --no-fail-fast: without it cargo abandons the remaining
targets after the first failure, and the broken tree reports 19 tests against
the fixed tree's 26, which would have compared two different test sets.

Corruption is detected by comparing each file against git cat-file blob,
NOT by counting CRLF sequences -- compressed data legitimately contains 0D 0A,
and a counting check falsely flagged lzvn.rsrc and real_zlib_rsrc.rsrc, which
are intact.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

h4x0r and others added 2 commits August 7, 2026 09:19
The shared workflow's `deny-config-repo` input defaulted to
SecurityRonin/fleet-config, so adopting it silently replaced this repo's
supply-chain policy with the shared one. That is a real change to what
`cargo deny` accepts, and no adoption PR disclosed it — nobody involved knew.

Measured across the fleet when it was found: 61 of 65 adopted repos had a
stricter local config. The shared one carries 21 advisory ignores against their
`ignore = []`, every one a bare RUSTSEC id with no reason and no removal
condition — which the fleet's own suppression rule forbids. Among them
RUSTSEC-2023-0071 (rsa, Marvin timing attack). Several repos also went from
`bans.multiple-versions = "deny"` to `"warn"` and gained nine allowed licences.

fleet-ci now defaults to the repository's own deny.toml; opting into the shared
config is explicit. This repin picks that up, restoring the policy this repo
actually wrote.

Reassuring rather than alarming: before this fix all 65 adopted repos were
re-checked against their OWN deny.toml and all 65 passed. The gate was weakened,
but nothing was hiding behind it. If this repin does turn a check red, that is a
true finding this repo's own policy always meant to catch — fix it rather than
re-pointing at the shared config.

Only the pinned SHA changes.
Seven decmpfs tests failed only on windows-latest. Decompression itself was
fine -- the output was the expected perl script -- so the corruption was in
the fixture bytes, not the decoder.

Cause: the repo had no .gitattributes, so git applied its text/binary
autodetection to byte-exact forensic evidence. core.autocrlf is true by
default on windows-latest, so every file git judged "text" had its LF bytes
rewritten to CRLF at checkout, and the tests then compared against corrupted
evidence.

Git scans only the first 8000 bytes for a NUL when making that call, so this
was not confined to the .expected files -- it also hit a compressed INPUT
whose first NUL falls past that window. Comparing a simulated windows-latest
checkout against the stored blobs shows 7 of 15 decmpfs fixtures altered:

  lzvn.expected              80000 -> 87855    zlib.expected  150000 -> 164122
  real_zlib_inline.expected   2000 ->  2218    zlib_inline.expected 3000 -> 3325
  tahoe_type8.expected        1936 ->  1994    zlib_type3_stored.payload
  tahoe_type9.expected          63 ->    71                         3001 -> 3326

Marking the data trees -text fixes the class rather than the seven failing
tests, and covers fixtures added later. No test or source file is touched.

Verified against git's own mechanism rather than by waiting on CI, since the
mechanism is git's and not the OS's -- `git -c core.autocrlf=true clone`
reproduces the runner's checkout on any platform:

  before   7 fixtures differ from their stored blobs; 19 passed, 7 failed
  after    0 fixtures differ;                         26 passed, 0 failed

The seven altered fixtures correspond one-to-one with the seven failing
tests. Both runs use --no-fail-fast: without it cargo abandons the remaining
targets after the first failure, and the broken tree reports 19 tests against
the fixed tree's 26, which would have compared two different test sets.

Corruption is detected by comparing each file against `git cat-file blob`,
NOT by counting CRLF sequences -- compressed data legitimately contains 0D 0A,
and a counting check falsely flagged lzvn.rsrc and real_zlib_rsrc.rsrc, which
are intact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@h4x0r

h4x0r commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Superseded: the fix is now a single commit on this PR's sibling branch ci/repin-deny-local (PR #7), whose windows-latest job is the one that was red. Opening it against main duplicated #7's repin commit, which would have been confusing to review.

@h4x0r h4x0r closed this Aug 8, 2026
@h4x0r
h4x0r deleted the fix/crlf-fixtures branch August 8, 2026 00:49
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