tarfile: don't interpret GNU-style atime as ustar-style path prefix
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 35.9k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
Bug report
Bug description:
The GNU and ustar tar format families have slightly overlapping header definitions: ustar says that bytes 345:500 are used for the "path prefix" i.e. for paths longer than the 100 char limit in the path field, while old-style GNU ("oldgnu") says that 345:356 are used for storing an atime attribute for the member.
Consequently, the two overlap (partially), and a tar parser should check the header's magic to determine how to interpret that byte range.
At the moment, CPython does not use the header's magic, and instead unconditionally interprets that range as a ustar-style prefix:
https://github.com/python/cpython/blob/b11e749f7590e9a0907db908fa3e7e76c772c28f/Lib/tarfile.py#L1354
and then unconditionally uses that prefix as long as the member type (not the header type) isn't a special GNU member type:
The end result of this is that tarfile can extract a file with a surprising name, whereas other parsers extract with the correct (non-ustar-prefixed) name.
MRE:
import io
import tarfile
member = tarfile.TarInfo("victim")
header = bytearray(member.tobuf(format=tarfile.GNU_FORMAT))
# Old-GNU atime field: valid octal timestamp 1.
header[345:357] = b"00000000001\0"
# Recalculate checksum.
header[148:156] = b" " * 8
header[148:156] = f"{sum(header):06o}\0 ".encode("ascii")
archive = bytes(header) + b"\0" * 1024
with tarfile.open(fileobj=io.BytesIO(archive), mode="r:") as tf:
print(tf.getnames())
On a main build as of b11e749f7590e9a0907db908fa3e7e76c772c28f, this produces:
['00000000001/victim']
whereas the output should be ['victim'], since the format is GNU_FORMAT instead of a ustar-family format.
I think the fix for this is to tweak the obj.name assignment to only use prefix when the magic bytes match POSIX_MAGIC, i.e. not GNU_MAGIC or any legacy (v7, pre-ustar) magic.
CPython versions tested on:
CPython main branch
Operating systems tested on:
No response
Linked PRs
- gh-155706
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- 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.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu trong Lib/tarfile.py, tại phần phân tích tiền tố và phép gán obj.name quanh các dòng được tham chiếu, sau đó tái hiện vấn đề bằng MRE được cung cấp. Hoàn tất khi kho lưu trữ GNU-format trả về ['victim'] thay vì ['00000000001/victim']; hãy kiểm tra PR được liên kết gh-155706 trước khi bắt đầu.
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
- tooling
- Loại issue
- Lỗi
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 35/100