gh-131492, gh-131461: handle exceptions in GzipFile constructor while owning resources (#131462)

Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Thomas Grainger 2025-03-20 17:06:21 +00:00 committed by GitHub
parent f53e7de6a8
commit ce79274e9f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 65 additions and 49 deletions

View file

@ -202,6 +202,8 @@ class GzipFile(_compression.BaseStream):
raise ValueError("Invalid mode: {!r}".format(mode))
if mode and 'b' not in mode:
mode += 'b'
try:
if fileobj is None:
fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
if filename is None:
@ -247,6 +249,11 @@ class GzipFile(_compression.BaseStream):
if self.mode == WRITE:
self._write_gzip_header(compresslevel)
except:
# Avoid a ResourceWarning if the write fails,
# eg read-only file or KeyboardInterrupt
self._close()
raise
@property
def mtime(self):
@ -387,9 +394,12 @@ class GzipFile(_compression.BaseStream):
elif self.mode == READ:
self._buffer.close()
finally:
self._close()
def _close(self):
self.fileobj = None
myfileobj = self.myfileobj
if myfileobj:
if myfileobj is not None:
self.myfileobj = None
myfileobj.close()

View file

@ -19,6 +19,7 @@ from test import archiver_tests
from test import support
from test.support import os_helper
from test.support import script_helper
from test.support import warnings_helper
# Check for our compression modules.
try:
@ -1638,8 +1639,11 @@ class WriteTest(WriteTestBase, unittest.TestCase):
raise exctype
f = BadFile()
with self.assertRaises(exctype):
tar = tarfile.open(tmpname, self.mode, fileobj=f,
with (
warnings_helper.check_no_resource_warning(self),
self.assertRaises(exctype),
):
tarfile.open(tmpname, self.mode, fileobj=f,
format=tarfile.PAX_FORMAT,
pax_headers={'non': 'empty'})
self.assertFalse(f.closed)

View file

@ -0,0 +1 @@
Fix :exc:`ResourceWarning` when constructing a :class:`gzip.GzipFile` in write mode with a broken file object.

View file

@ -0,0 +1 @@
Fix a resource leak when constructing a :class:`gzip.GzipFile` with a filename fails, for example when passing an invalid ``compresslevel``.