A deliberately constructed tar archive exposes an ambiguity in how tools interpret the size of a hard-linked file. A single GNU tar command archives a file twice, then transforms the second entry’s name to the UTF-8 name “café,” making it a hard link with a pax header. That header assigns the link a size of 512 bytes - the exact length of a tar header. The key question is whether those bytes belong to the hard link’s contents or should be ignored, as many tools do. Depending on that choice, the bytes can instead be read as the header for the following empty file, producing sharply different extraction results.
GNU tar, BusyBox, Python, Go, and Perl ignore the hard-link size and extract the expected files and link. BSD tar writes the next header into the original file. Several other tools skip those bytes, losing the empty file; Java Commons Compress creates an extra file containing the header, while PHP creates a separate empty link and Ruby omits it. R misapplies the size to the empty file, and Haskell corrupts the UTF-8 filename. .NET, Julia, and uv’s tar-codec reject the archive. The example belongs to a collection of 134 adversarial tar files, with a test suite and comparison table documenting how different implementations handle them.
Summary generated by AI from the linked article. hn.today is not affiliated with Hacker News or Y Combinator.