Skip to content

tar held to the system tar over a rich tree, its extraction fuzzed with hostile archives - #35

Merged
closer-claudio merged 1 commit into
mainfrom
claudio/20261019-tests-compress
Oct 21, 2026
Merged

closer-claudio merged 1 commit into
mainfrom
claudio/20261019-tests-compress

Conversation

@closer-claudio

@closer-claudio closer-claudio commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

🎯 Why: tar had no check against the system tar, so an archive this tar writes that the system cannot read, or the reverse, would go unnoticed; and extraction had no fuzz target against hostile archives.
🛠️ What: internal/tarcmd/contract_interop_test.go (archives written here extracted by the host's bsdtar, gtar or tar, found on the host's own PATH with the hermetic entries removed, and the reverse, compared file by file over long and non-ASCII names, spaces, empty files, modes, symlinks, hard links, empty directories and mtimes; -z, -J and --zstd by magic and round trip), internal/tarcmd/fuzz_test.go (FuzzExtract with .. components, absolute paths, links out of the tree and PAX long names: extraction stays inside the target and returns without panic).
🧪 How:

  1. tar held to the system tar over a rich tree, its extraction fuzzed with hostile archives. V: go test ./... green; three minutes of fuzzing clean with the minimizer off (the target creates directories, which stalls the engine's minimizer, so -fuzzminimizetime=0, as the file says); command mutation sample 29 of 43 killed, the survivors option parsing and mode-bit edges in tarcmd, zip and unzip. No defect found.
    📝 Notes: -J and --zstd skip where the host has no xz or zstd outside the hermetic root; the system tar runs with COPYFILE_DISABLE=1 and a UTF-8 locale so AppleDouble entries and octal-escaped listings stay out of the comparison.

…th hostile archives

The README's word for the commands, "the grammar, output and exit
statuses of the tool it stands in for", held for tar against the tar on
PATH (bsdtar on macOS, GNU tar on Linux) over a tree with the shapes a
format has to carry: a path over 100 bytes and one over 255, a
non-ASCII name of characters no filesystem renormalizes, a name with
spaces, an empty file, an executable, a private file, a symlink, a hard
link, an empty directory, a 100 kB file, a fixed mtime on everything. An
archive this tar creates extracts under the system tar to the same tree
(kinds, permission bits, contents, link targets, mtimes) and the system
tar's under this tar, and both list the same names; the same both ways
for -z, -J and --zstd, this tar opening the system tar's compressed
archives by magic alone (TestContractInteropRichTree,
TestContractInteropCompressed; the system tar runs under
COPYFILE_DISABLE and a UTF-8 locale, or macOS adds AppleDouble entries
and escapes non-ASCII names in its listing).

FuzzExtract feeds `tar -xf - -C dest` archive bytes grown from six seeds
(a plain file, a symlink out of the tree and a file through it, a `..`
name, an absolute name, a hard link out of the tree, a PAX long name) and
holds that nothing lands beside or above the destination, nothing
panics, and the exit status is 0 or 2. Three minutes with the minimizer
off (which stalls on a target that makes directories): no failure.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: closer-claudio <[email protected]>
@closer-claudio

Copy link
Copy Markdown
Contributor Author

Reviewed at 652dbec

@closer-claudio
closer-claudio merged commit 8a38af3 into main Oct 21, 2026
12 checks passed
@closer-claudio
closer-claudio deleted the claudio/20261019-tests-compress branch October 21, 2026 00:10
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