bpo-36434: Properly handle writing errors in ZIP files. (GH-12559) (G… · python/cpython@4724ba9

@@ -1101,47 +1101,50 @@ def write(self, data):

11011101

def close(self):

11021102

if self.closed:

11031103

return

1104-

super().close()

1105-

# Flush any data from the compressor, and update header info

1106-

if self._compressor:

1107-

buf = self._compressor.flush()

1108-

self._compress_size += len(buf)

1109-

self._fileobj.write(buf)

1110-

self._zinfo.compress_size = self._compress_size

1111-

else:

1112-

self._zinfo.compress_size = self._file_size

1113-

self._zinfo.CRC = self._crc

1114-

self._zinfo.file_size = self._file_size

1115-1116-

# Write updated header info

1117-

if self._zinfo.flag_bits & 0x08:

1118-

# Write CRC and file sizes after the file data

1119-

fmt = '<LLQQ' if self._zip64 else '<LLLL'

1120-

self._fileobj.write(struct.pack(fmt, _DD_SIGNATURE, self._zinfo.CRC,

1121-

self._zinfo.compress_size, self._zinfo.file_size))

1122-

self._zipfile.start_dir = self._fileobj.tell()

1123-

else:

1124-

if not self._zip64:

1125-

if self._file_size > ZIP64_LIMIT:

1126-

raise RuntimeError('File size unexpectedly exceeded ZIP64 '

1127-

'limit')

1128-

if self._compress_size > ZIP64_LIMIT:

1129-

raise RuntimeError('Compressed size unexpectedly exceeded '

1130-

'ZIP64 limit')

1131-

# Seek backwards and write file header (which will now include

1132-

# correct CRC and file sizes)

1133-1134-

# Preserve current position in file

1135-

self._zipfile.start_dir = self._fileobj.tell()

1136-

self._fileobj.seek(self._zinfo.header_offset)

1137-

self._fileobj.write(self._zinfo.FileHeader(self._zip64))

1138-

self._fileobj.seek(self._zipfile.start_dir)

1139-1140-

self._zipfile._writing = False

1141-1142-

# Successfully written: Add file to our caches

1143-

self._zipfile.filelist.append(self._zinfo)

1144-

self._zipfile.NameToInfo[self._zinfo.filename] = self._zinfo

1104+

try:

1105+

super().close()

1106+

# Flush any data from the compressor, and update header info

1107+

if self._compressor:

1108+

buf = self._compressor.flush()

1109+

self._compress_size += len(buf)

1110+

self._fileobj.write(buf)

1111+

self._zinfo.compress_size = self._compress_size

1112+

else:

1113+

self._zinfo.compress_size = self._file_size

1114+

self._zinfo.CRC = self._crc

1115+

self._zinfo.file_size = self._file_size

1116+1117+

# Write updated header info

1118+

if self._zinfo.flag_bits & 0x08:

1119+

# Write CRC and file sizes after the file data

1120+

fmt = '<LLQQ' if self._zip64 else '<LLLL'

1121+

self._fileobj.write(struct.pack(fmt, _DD_SIGNATURE, self._zinfo.CRC,

1122+

self._zinfo.compress_size, self._zinfo.file_size))

1123+

self._zipfile.start_dir = self._fileobj.tell()

1124+

else:

1125+

if not self._zip64:

1126+

if self._file_size > ZIP64_LIMIT:

1127+

raise RuntimeError(

1128+

'File size unexpectedly exceeded ZIP64 limit')

1129+

if self._compress_size > ZIP64_LIMIT:

1130+

raise RuntimeError(

1131+

'Compressed size unexpectedly exceeded ZIP64 limit')

1132+

# Seek backwards and write file header (which will now include

1133+

# correct CRC and file sizes)

1134+1135+

# Preserve current position in file

1136+

self._zipfile.start_dir = self._fileobj.tell()

1137+

self._fileobj.seek(self._zinfo.header_offset)

1138+

self._fileobj.write(self._zinfo.FileHeader(self._zip64))

1139+

self._fileobj.seek(self._zipfile.start_dir)

1140+1141+

# Successfully written: Add file to our caches

1142+

self._zipfile.filelist.append(self._zinfo)

1143+

self._zipfile.NameToInfo[self._zinfo.filename] = self._zinfo

1144+

finally:

1145+

self._zipfile._writing = False

1146+1147+1145114811461149

class ZipFile:

11471150

""" Class with methods to open, read, write, close, list zip files.