tarfile silently stops/skips on bad member header (e.g. checksum mismatch)
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 36k
- PR マージ指標
- PR 指標を取得中
説明
Bug report
Bug description:
When reading a tar archive that includes a file with a bad header (such as a checksum mismatch), getmembers simply stops listing the members at that file, without reporting an error, and ignoring the files that come after it (Edit: unless ignore_zeros=True is set).
I would expect instead that getmembers lists all members, and extractfile raises a TarError when trying to extract a file with an invalid header (such as a bad chksum or typeflag).
import os
import contextlib
import subprocess
from io import BytesIO
from tarfile import TarFile, TarInfo
from tempfile import TemporaryDirectory
# generate a tar file in memory
bio = BytesIO()
with TarFile(mode="w", fileobj=bio, errorlevel=2) as tf:
ti = TarInfo()
ti.size = 3
for name, data in (("foo", b"123"), ("bar", b"456"), ("quz", b"789")):
ti.name = name
tf.addfile(ti, BytesIO(data))
# break the checksum of the second file 'bar'
assert b"\x00006425\x00" in bio.getvalue()
broken = bio.getvalue().replace(b"\x00006425\x00", b"\x00106425\x00")
# try to read the tar file
with TarFile(fileobj=BytesIO(broken), errorlevel=2) as tf:
for ti in tf.getmembers():
print(repr(ti.name))
with tf.extractfile(ti) as fh:
print(repr(fh.read()))
# => only "foo" is extracted
with TemporaryDirectory() as td:
with contextlib.chdir(td):
with TarFile(fileobj=BytesIO(broken), errorlevel=2) as tf:
tf.extractall()
print(os.listdir())
# => again only "foo" is extracted
os.unlink("foo")
with TarFile(fileobj=BytesIO(broken), errorlevel=2) as tf:
tf.extractall(filter="data")
print(os.listdir())
# => filter doesn't change anything
with open("test.tar", "wb") as fh:
fh.write(broken)
subprocess.run(["tar", "tvf", "test.tar"], check=False)
# => GNU tar 1.34 correctly identifies error and continues processing
Output:
'foo'
b'123'
['foo']
['foo']
-rw-r--r-- 0/0 3 1970-01-01 00:00 foo
tar: Skipping to next header
-rw-r--r-- 0/0 3 1970-01-01 00:00 quz
tar: Exiting with failure status due to previous errors
CPython versions tested on:
3.12, 3.13
Operating systems tested on:
Linux, Windows
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
提供された BytesIO の例でその動作を再現し、その後、レポートで挙げられているエントリーポイントである TarFile.getmembers()、extractfile()、extractall() から調査を始めます。無効なメンバーヘッダーがどのように処理され、後続のヘッダーにどのように到達するかを追跡します。完了とみなされるのは、要求どおりに不正なヘッダーが報告され、後続の有効なメンバーを引き続き処理でき、対象の動作がテストでカバーされている状態です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- backend
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 48/100