pytilpack.zipfile¶
pytilpack.zipfile
¶
ZIP関連のユーティリティ集。
decode_zipinfo_filename(info, *, fallback_encodings=('cp932', 'cp437'))
¶
ZipInfoのファイル名を生バイト列基準で復号する。
info.filenameはzipfile._sanitize_filenameでプラットフォーム依存の
加工(Windowsなら\\を/に置換)を経た文字列であり、CP932の
2バイト目に0x5Cを含む文字(ソ・ポ・表など)を含むエントリでは
info.filename.encode("cp437").decode("cp932")の往復復元に失敗する。
そのため、生バイト列に近いinfo.orig_filenameを起点に復号する。
bit 11(Unicode flag)がセットされている場合はzipfileがUTF-8でorig_filenameを
構築済みなのでそのまま採用する。未セットの場合はorig_filenameをCP437で
エンコードして原バイト列を復元し、fallback_encodingsの先頭からstrictで
復号を試み、全て失敗した場合はCP437既定のorig_filenameをそのまま返す。
復号後はNUL文字以降を切り詰める。zipfile._sanitize_filenameがもともと
行うNUL切り詰め処理のうち、orig_filename起点では適用されない部分を
最低限再現するもの。Windowsの\\→/置換は0x5C問題の原因のため再現しない。
Zip Slip相当の検証は本関数では行わない。
呼び出し側でis_safe_relative_pathなどにより別途検証すること。
引数:
| 名前 | タイプ | デスクリプション | デフォルト |
|---|---|---|---|
info
|
ZipInfo
|
対象のZIPエントリ情報。 |
必須 |
fallback_encodings
|
Sequence[str]
|
bit 11未設定時に試行する復号エンコーディングの優先順。 |
('cp932', 'cp437')
|
戻り値:
| タイプ | デスクリプション |
|---|---|
str
|
復号済みのエントリ名。 |
ソースコード位置: pytilpack/zipfile.py
is_safe_relative_path(name)
¶
ZIPエントリ名が展開先配下にとどまる安全な相対パスかを判定する。
Zip Slip攻撃の防止を主目的とし、加えてSJIS復号崩れによる バックスラッシュ混入も併せて遮るため、以下を全て満たすことを要求する。
- 空文字でない
- バックスラッシュを含まない(CP932 2バイト目の
0x5C混入の保険) - 先頭が
/でない /区切りの各要素が""(連続//由来)でも..でもなく、:を含まないPureWindowsPathでdriveまたはrootを持たない (C:foo・\\srv\share等の拒否)
NUL文字の混入チェックはdecode_zipinfo_filename側で
切り詰めにより吸収するため本関数では扱わない。
引数:
| 名前 | タイプ | デスクリプション | デフォルト |
|---|---|---|---|
name
|
str
|
ZIPエントリ名相当の文字列。末尾 |
必須 |
戻り値:
| タイプ | デスクリプション |
|---|---|
bool
|
安全な相対パスであれば |