テクノロジー · 実用ガイド

zipfile.Path.is_symlink()が常にFalse?実行版と格納された種類を確認

20件の実測で、Python 3.12の仮実装、ZIPのUnix種別情報、CRC整合性、標準展開器が実際に作るオブジェクトを分ける。

3.12のaliasについて存在・ファイル・リンクの述語とUnix種類ビットを示すオリジナル解説イラスト。
オリジナル解説イラスト:実測3.12.14ではFalseと格納されたリンク種別が両立する。 Watch at Ease

CPython 3.12.14では、Unixシンボリックリンクとして記録した合成ZIPのメンバーが存在し、zipfile.Path.is_file()もTrueだったのに、is_symlink()はFalseになった。格納されたモードを見るとリンクを識別できた。Falseだけでは通常ファイルのみのアーカイブだと証明できない。

アーカイブを変更する前に、実行版と採用されたメタデータ規則を確認する。Linux上で751バイト、7メンバーの合成ZIPを使い20件のアサーションを実行した。CRC合格、展開成功、格納された種類の確認はそれぞれ別の結果だった。

1. メソッドの有無ではなく実装を試す

sys.versionを表示し、対象が展開後のファイルを指すpathlib.Pathではなくzipfile.Pathであることを確認する。実際の3.12.14でzipfile.Path.is_symlinkのソースを調べると、単にFalseを返す実装だった。呼び出し可能なので、属性の存在確認だけでは制限を検出できない。

Pythonの版別リファレンスは3.13での変更を記録し、それ以前は無条件にFalseだったと説明する。文書は読んだが3.13は実行していない。既知で無害なリンク種別の例を実環境で試し、最新の文書やメソッド名だけから挙動を推測しない。

2. 明示した規則に従ってメンバーを調べる

開いたアーカイブのinfolist()を走査し、各ZipInfoを保持する。filename、create_system、info.external_attr >>16というモード式を記録する。今回のUnixホスト規則ではcreate_system==3を条件にして、stat.S_ISLNK、stat.S_ISREG、stat.S_ISDIRで種類を判定する。確認するのは記録済みの種類ビットで、現在のファイルシステムではない。

PKWAREは外部属性の意味をホスト依存としている。限定した分類器では非Unixホストと判別できる種類のないモードをunknownにする。unknownは通常ファイルでも問題なしでもない。他の生成ソフトやホスト規則は別途検証し、無理に否定結果へ置き換えない。

3. 名前、リンク先文字列、種類ビットを分ける

例のaliasとdanglingは両方ともリンク種別だった。danglingの指す先が存在しなくても同じだ。読み取ると格納されたtarget.txtとabsent.txtという文字列が返った。ordinary.linkという名前の通常メンバーは明示したUnix種類ビットで通常ファイルとなり、拡張子はリンクの証拠ではなかった。

folder/にはディレクトリ形式の名前とディレクトリモードの両方があった。ZipInfo.is_dirは名前の末尾スラッシュを使い、すべてのUnix種類ビットを調べる処理ではない。権限だけのメンバーには判別できる種類がなくunknownのままだった。権限ビットだけで通常ファイルとは判断できない。

4. 展開後の結果を別に測る

testzip()は例全体にNoneを返し、対象メンバーはそのCRCとヘッダー検査を通過した。それでもリンクのメタデータは残った。整合性検査はメンバーがリンクかどうか、別の展開器が何を復元するかを答えていない。

標準のZipFile.extractで無害なaliasだけを新しい一時ディレクトリへ展開した。この3.12.14/Linux実行では、target.txtという文字列を含む通常ファイルができ、OSのシンボリックリンクはできなかった。外部展開器は試していない。他のソフトへ一般化したり、期待する真偽値に合わせてメタデータを書き換えたりしない。

5. 予定する受け渡しに合う完了条件を決める

20件の検証はメソッドの有無、exists/is_file/is_symlink、7メンバーの種類、切れたリンク先と拡張子の対照、unknown、CRC合格、格納文字列、存在しないメンバー、展開後の種類と正確な内容を確認した。報告には実行版、述語のソース、スクリプトとアーカイブのハッシュを残した。

自分の処理でも未変更アーカイブと小さな既知例を保持する。メンバー一覧を照合し、規則が対応する形式だけを分類してunknownは方針に従い調査または拒否する。そのうえで実際に使う展開器の生成物の種類と内容を確認する。これはメンバーの種類診断であり、信頼できないアーカイブの完全な展開検証や他環境への互換保証ではない。

7メンバーの種類、unknown、CRC、展開結果を分けるオリジナル解説イラスト。
オリジナル解説イラスト:種類、整合性、展開は別の結果。unknownは通常ファイルを意味しない。 Watch at Ease