From 367f5d379ca91ef55f496614945fd929d7e09b70 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 25 Mar 2014 09:08:16 +0100 Subject: [PATCH] Issue #21058: Fix a leak of file descriptor in tempfile.NamedTemporaryFile(), close the file descriptor if os.fdopen() fails --- Lib/tempfile.py | 8 ++++++-- Lib/test/test_tempfile.py | 18 ++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 7154d2c6b5..94ad0b7ec7 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -460,8 +460,12 @@ def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="", flags |= _os.O_TEMPORARY (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) - file = _os.fdopen(fd, mode, bufsize) - return _TemporaryFileWrapper(file, name, delete) + try: + file = _os.fdopen(fd, mode, bufsize) + return _TemporaryFileWrapper(file, name, delete) + except Exception: + _os.close(fd) + raise if _os.name != 'posix' or _os.sys.platform == 'cygwin': # On non-POSIX and Cygwin systems, assume that we cannot unlink a file diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 40f70c0b30..465bcdac0c 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -771,6 +771,24 @@ class test_NamedTemporaryFile(TC): pass self.assertRaises(ValueError, use_closed) + def test_no_leak_fd(self): + # Issue #21058: don't leak file descriptor when fdopen() fails + old_close = os.close + old_fdopen = os.fdopen + closed = [] + def close(fd): + closed.append(fd) + def fdopen(*args): + raise ValueError() + os.close = close + os.fdopen = fdopen + try: + self.assertRaises(ValueError, tempfile.NamedTemporaryFile) + self.assertEqual(len(closed), 1) + finally: + os.close = old_close + os.fdopen = old_fdopen + # How to test the mode and bufsize parameters? test_classes.append(test_NamedTemporaryFile) diff --git a/Misc/NEWS b/Misc/NEWS index e2c757c162..0f455557c2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Core and Builtins Library ------- +- Issue #21058: Fix a leak of file descriptor in tempfile.NamedTemporaryFile(), + close the file descriptor if os.fdopen() fails + - Issue #20283: RE pattern methods now accept the string keyword parameters as documented. The pattern and source keyword parameters are left as deprecated aliases. -- 2.50.1