最も難しいtarball?
The Hardest Tarball? (stoppels.ch)
要約
この記事は、様々なアーカイブツールで抽出動作が大きく異なる、奇妙なtarアーカイブを探求しています。単一の`tar`コマンドで作成されたこのアーカイブは、ハードリンクとPAXヘッダーを悪用して曖昧さを生み出し、GNU tar、bsdtar、7-Zipなどのツールで多様な解釈を引き起こし、tarアーカイブ処理の複雑さと不整合性を浮き彫りにしています。
全文翻訳
最も難しいtarball?
2026年11月7日
これは奇妙なものです。単一のGNU tar呼び出しで構築でき、使用するツールによって8通りの異なる方法で抽出されるアーカイブです。
$ printf hello > file
$ touch empty
$ tar --format=pax --pax-option='delete=?time,size:=512' \
--transform='s,^\./file$,café,' \
-cf hardest.tar file ./file empty
これは、file、./file、emptyの3つのファイルから、fileが繰り返されることでGNU tarが2番目のファイルをハードリンクとして保存し、emptyは空であるというシーケンスでアーカイブhardest.tarを作成します。2番目のエントリのユニークなパスを利用して、ハードリンクはcaféにリネームされます。これにより、tarはファイル名をUTF-8で保存するためにpaxヘッダーを作成します。paxヘッダーにsize=512レコードを追加すると、ハードリンクからのデフォルトのsize=0が上書きされます。値512は偶然ではありません。これはtarヘッダーの正確なサイズです。
視覚的には、このアーカイブはハードリンクにサイズを持たせることができるかどうかによって、2つの基本的な解釈に基づいた構造を持っています。
[画像: The structure of hardest.tar, with two basic interpretations based on whether a hard link can have a size or not.]
さて、POSIXは、ハードリンクのデータブロックはpaxアーカイブに「含めることができる」と述べていますが、その意味合いは完全には明らかではありません。したがって、ハードリンクの後の512バイトは、アーカイブしたemptyのヘッダーではなく、そのデータなのでしょうか?ハードリンクがその前のfileとは異なる内容を持つことができるのでしょうか?
抽出
このアーカイブは、よく知られたtarユーティリティやライブラリで抽出する際に、私がこれまでに遭遇した中で最も豊かで驚くべき結果をもたらします。以下の結果は、執筆時点ですべてのパッケージの最新リリースを使用して生成されました。
GNU tar, BusyBox, Python, Go and Perl
このグループは原則として合理的です。ハードリンクのサイズを無視し、file、そのハードリンクcafé、およびemptyを抽出します。
bsdtar
これはmacOSのシステムtarユーティリティであり、ハードリンクのサイズという概念に関してPOSIXの精神に近く、512バイトをハードリンクに書き込みます。最終結果として、fileにはemptyのtarヘッダーが含まれることになります。
7-Zip, node-tar, tar-fs, and Rust's tar & astral-tokio-tar
このグループはbsdtarと同様に512バイトをハードリンクのデータと見なしますが、それをハードリンクに書き込みません。代わりに、データの先へスキップし、emptyなしでfileとcaféだけが残ります。
Java's Commons Compress
ここで想像力が必要になります。なぜならcaféにはデータが含まれているため、emptyのヘッダーをデータとして含む別のファイルが作成され、fileは元の内容を保持するからです。
PHP's PharData
caféを別の空ファイルにし、emptyも抽出します。なぜだめなのでしょうか?
RubyGems
caféはまったく抽出されませんが、その代わりにfileとemptyの隣にPaxHeadersという空のディレクトリを作成します。
R
Rはまったく異なるアプローチを取ります。512バイトのヌルバイトを含むemptyを抽出します。誤ってハードリンクではなくemptyにサイズを適用しており、その512バイトはアーカイブ終了マーカーからのものです。
ボーナス: Haskell
Haskellのtarは、文字列デコードの問題がなければGNU tarとまったく同じですが、その問題により、ファイルcaféはディスク上でcaféになります(2026年現在、これはブラウザのレンダリングの問題ではありません)。
.NET, Julia and uv's tar-codec
これらの実装はtarballを拒否します。技術的にはPOSIX準拠ではありませんが、これが最善の対応だと考えます。
さらに詳しく
このtarballは、私がテストスイートhaampie/tar-minefieldで収集・分類している134個のトリッキーなtarballの1つです。このウェブサイトhttps://stoppels.ch/tarには、実装がこれらのケースにどのように対応するかを示す大きなテーブルと、各テストケースの詳細情報が掲載されています。この投稿のtarballのバリアントはテストケースとして含まれています。
これについて議論したい場合は、firstname[at]lastname.chまでメールを送信してください。