python / python/cpython

tarfile silently stops/skips on bad member header (e.g. checksum mismatch)

Đang mở
#120,740 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

type-bug
Ngôn ngữ chính
Python
Star
77.2k
Fork
36k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

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

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Tái hiện hành vi bằng ví dụ BytesIO được cung cấp, sau đó bắt đầu từ TarFile.getmembers(), extractfile() và extractall(), các điểm vào được nêu trong báo cáo. Theo dõi cách một header của member không hợp lệ được xử lý và cách các header tiếp theo được tiếp cận. Được xem là hoàn tất khi header sai được báo cáo như yêu cầu, trong khi các member hợp lệ tiếp theo vẫn có thể được xử lý, và hành vi bị ảnh hưởng được bao phủ bởi các bài kiểm thử.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
backend
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
48/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.