`zipfile` may write inappropriate extra fields to Local File Entries
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:
Currently, ZipInfo.extra reads data from the Central Directory (CD), but writes to both the Local File Entry (LFE) and the Central Directory.
However, certain extra fields are layout-dependent or exclusive to the CD. Direct synchronization may cause corrupted or unreadable metadata.
1. Duplicated Zip64 Extra Fields (0x0001)
If ZipInfo.extra already contains a Zip64 extra field manually injected or copied from an existing archive, the LFE will contain duplicated Zip64 extra fields when written.
Since how to handle duplicated fields is undefined, ZIP tools may fail to read the correct zip64 data or treat the ZIP archive as corrupted due to inconsistency across LFE and CD.
For example:
import io
import struct
import zipfile
fh = io.BytesIO()
with zipfile.ZipFile(fh, 'w') as zh:
zinfo = zipfile.ZipInfo('strfile')
zinfo.extra = (
b'\x01\x00\x10\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00'
)
with zh.open(zinfo, 'w', force_zip64=True) as zi:
pass
fh.seek(zinfo.header_offset)
entry = fh.read(zh.start_dir - zinfo.header_offset - zinfo.compress_size)
header = struct.unpack_from(zipfile.structFileHeader, entry)
extra = entry[-header[zipfile._FH_EXTRA_FIELD_LENGTH]:]
print(extra)
The result is double b'\x01\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', while only one should exist.
2. Appended Zip64 Field Can Be Masked and Inaccessible
When ZipInfo.extra contains a misaligned or trailing field that ends abruptly, the appended Zip64 extra field is written immediately after it.
For example:
import io
import struct
import zipfile
fh = io.BytesIO()
with zipfile.ZipFile(fh, 'w') as zh:
zinfo = zipfile.ZipInfo('strfile')
zinfo.extra = b'\x02\x00\x00\x01\x00\x00'
with zh.open(zinfo, 'w', force_zip64=True) as zi:
pass
fh.seek(zinfo.header_offset)
entry = fh.read(zh.start_dir - zinfo.header_offset - zinfo.compress_size)
header = struct.unpack_from(zipfile.structFileHeader, entry)
extra = entry[-header[zipfile._FH_EXTRA_FIELD_LENGTH]:]
print(extra)
The result is b'\x02\x00\x00\x01\x00\x00\x01\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', which will be intepreted as having a field with ID \x0002 and length 256 (\x00\x01). The zip64 field will be treated as part of that field and is not readable.
It would be better to prepend (rather than append) the zip64 field, as how it is handled in central directory. Although this still gets invalid extra data, it will be easier to analysis and recover since the zip64 extra field is readable.
3. Redundant Info-ZIP Unicode Comment Fields (0x6375)
The Info-ZIP Unicode Comment field (0x6375) is strictly meant to map archive comments, which only exist in the CD.
Writing 0x6375 to the LFE is a violation of common layout expectations and bloats the local file header with dead data.
For example:
import io
import struct
import zipfile
fh = io.BytesIO()
with zipfile.ZipFile(fh, 'w') as zh:
zinfo = zipfile.ZipInfo('strfile')
zinfo.comment = b'1'
zinfo.extra = struct.pack(
'<HHBL5s', 0x6375, 11, 1, zipfile.crc32(b'1'), '1\u4e00'.encode('utf-8'))
with zh.open(zinfo, 'w') as zi:
pass
fh.seek(zinfo.header_offset)
entry = fh.read(zh.start_dir - zinfo.header_offset - zinfo.compress_size)
header = struct.unpack_from(zipfile.structFileHeader, entry)
extra = entry[-header[zipfile._FH_EXTRA_FIELD_LENGTH]:]
print(extra)
The result is the unicode comment field, while it should be empty.
Proposed Solution
Before writing to LFE, zipfile should strip or sanitize layout-incompatible fields from ZipInfo.extra.
If automatic fields (like Zip64) must be injected, they should be prepended rather than appended to prevent trailing parsing errors.
CPython versions tested on:
3.14, 3.16
Operating systems tested on:
No response
Linked PRs
- gh-153704
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 từ đường dẫn zipfile.ZipFile.open và cách xử lý ZipInfo.extra, bao gồm force_zip64 và việc xây dựng header cục bộ so với header trung tâm. So sánh các ví dụ được báo cáo với các mục tệp cục bộ được tạo; hoàn thành có nghĩa là các trường không tương thích với bố cục không được ghi vào đó và dữ liệu Zip64 được tự động thêm vào vẫn có thể phân tích được.
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ó
- 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
- 25/100