Skip to content

Commit 681477d

Browse files
authored
gh-150077: Fix fileobj leak in tarfile.TarFile.zstopen on BaseException (GH-150080)
This is one of those times when a bare `except` is appropriate.
1 parent 93beea7 commit 681477d

3 files changed

Lines changed: 36 additions & 1 deletion

File tree

Lib/tarfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2129,7 +2129,7 @@ def zstopen(cls, name, mode="r", fileobj=None, level=None, options=None,
21292129
if mode == 'r':
21302130
raise ReadError("not a zstd file") from e
21312131
raise
2132-
except Exception:
2132+
except:
21332133
fileobj.close()
21342134
raise
21352135
t._extfileobj = False

Lib/test/test_tarfile.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,38 @@ class LzmaDetectReadTest(LzmaTest, DetectReadTest):
11411141
class ZstdDetectReadTest(ZstdTest, DetectReadTest):
11421142
pass
11431143

1144+
1145+
@support.requires_zstd()
1146+
class ZstdOpenTest(unittest.TestCase):
1147+
"""
1148+
See: https://github.com/python/cpython/issues/150077
1149+
"""
1150+
def test_zstopen_closes_fileobj_on_base_exception(self):
1151+
path = os_helper.TESTFN + ".tar.zst"
1152+
self.addCleanup(os_helper.unlink, path)
1153+
with tarfile.open(path, "w:zst"):
1154+
pass
1155+
1156+
opened = []
1157+
real_ZstdFile = zstd.ZstdFile
1158+
1159+
def tracking_ZstdFile(*args, **kwargs):
1160+
fileobj = real_ZstdFile(*args, **kwargs)
1161+
opened.append(fileobj)
1162+
return fileobj
1163+
1164+
with (
1165+
unittest.mock.patch("compression.zstd.ZstdFile", tracking_ZstdFile),
1166+
unittest.mock.patch.object(
1167+
tarfile.TarFile, "taropen", side_effect=KeyboardInterrupt),
1168+
self.assertRaises(KeyboardInterrupt),
1169+
):
1170+
tarfile.TarFile.zstopen(path)
1171+
1172+
self.assertEqual(len(opened), 1)
1173+
self.assertTrue(opened[0].closed)
1174+
1175+
11441176
class GzipBrokenHeaderCorrectException(GzipTest, unittest.TestCase):
11451177
"""
11461178
See: https://github.com/python/cpython/issues/107396
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix ``tarfile.TarFile.zstopen`` to close the underlying zstd file object
2+
when opening the tar archive is interrupted by a :exc:`BaseException`
3+
subclass such as :exc:`KeyboardInterrupt`.

0 commit comments

Comments
 (0)