Bug report
Bug description:
When a ZIP entry has general purpose bit 11 set (the name and comment are UTF-8), zipfile decodes the member name with .decode('utf-8') without guarding the decode. A member name that is flagged as UTF-8 but holds bytes that are not valid UTF-8 makes the operation raise UnicodeDecodeError instead of zipfile.BadZipFile.
A corrupt archive should surface as BadZipFile, the module's own error type, so that callers that already handle BadZipFile do not also have to catch UnicodeDecodeError. The sibling extra-field decoder _decodeExtra already wraps its own failures in BadZipFile.
Reproduction:
import io, struct, zipfile
name = b'\xff\xfe' # flagged UTF-8 but not valid UTF-8
flag = 0x800 # general purpose bit 11
lfh = struct.pack(zipfile.structFileHeader, zipfile.stringFileHeader,
20, 0, flag, 0, 0, 0, 0, 0, 0, len(name), 0) + name
cd = struct.pack(zipfile.structCentralDir, zipfile.stringCentralDir,
20, 0, 20, 0, flag, 0, 0, 0, 0, 0, 0, len(name), 0, 0, 0, 0, 0, 0) + name
eocd = struct.pack(zipfile.structEndArchive, zipfile.stringEndArchive,
0, 0, 1, 1, len(cd), len(lfh), 0)
zipfile.ZipFile(io.BytesIO(lfh + cd + eocd))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
The local file header path has the same gap: if the central directory name is valid UTF-8 but the local header name is not, ZipFile.open() / .read() raises UnicodeDecodeError.
Fix: wrap the two UTF-8 filename decodes (_RealGetContents for the central directory and open() for the local file header) so a UnicodeDecodeError is re-raised as BadZipFile, mirroring _decodeExtra.
CPython versions tested on:
3.13, 3.14
Operating systems tested on:
macOS
Linked PRs
Bug report
Bug description:
When a ZIP entry has general purpose bit 11 set (the name and comment are UTF-8),
zipfiledecodes the member name with.decode('utf-8')without guarding the decode. A member name that is flagged as UTF-8 but holds bytes that are not valid UTF-8 makes the operation raiseUnicodeDecodeErrorinstead ofzipfile.BadZipFile.A corrupt archive should surface as
BadZipFile, the module's own error type, so that callers that already handleBadZipFiledo not also have to catchUnicodeDecodeError. The sibling extra-field decoder_decodeExtraalready wraps its own failures inBadZipFile.Reproduction:
The local file header path has the same gap: if the central directory name is valid UTF-8 but the local header name is not,
ZipFile.open()/.read()raisesUnicodeDecodeError.Fix: wrap the two UTF-8 filename decodes (
_RealGetContentsfor the central directory andopen()for the local file header) so aUnicodeDecodeErroris re-raised asBadZipFile, mirroring_decodeExtra.CPython versions tested on:
3.13, 3.14
Operating systems tested on:
macOS
Linked PRs