diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2022-06-26 07:58:28 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-26 07:58:28 (GMT) |
commit | d4792ce916b94d090b6c7bce8b0f973e840c9e4e (patch) | |
tree | f9eec03deffc59d3d56e76b244f74706f0e8c8a5 /Lib/tempfile.py | |
parent | 536985814a7116f14c9bc90aa1b3e3d36d5b2367 (diff) | |
download | cpython-d4792ce916b94d090b6c7bce8b0f973e840c9e4e.zip cpython-d4792ce916b94d090b6c7bce8b0f973e840c9e4e.tar.gz cpython-d4792ce916b94d090b6c7bce8b0f973e840c9e4e.tar.bz2 |
gh-83499: Fix closing file descriptors in tempfile (GH-93874)
Diffstat (limited to 'Lib/tempfile.py')
-rw-r--r-- | Lib/tempfile.py | 79 |
1 files changed, 51 insertions, 28 deletions
diff --git a/Lib/tempfile.py b/Lib/tempfile.py index eb870c9..480c172 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -203,8 +203,7 @@ def _get_default_tempdir(): fd = _os.open(filename, _bin_openflags, 0o600) try: try: - with _io.open(fd, 'wb', closefd=False) as fp: - fp.write(b'blat') + _os.write(fd, b'blat') finally: _os.close(fd) finally: @@ -244,6 +243,7 @@ def _get_candidate_names(): def _mkstemp_inner(dir, pre, suf, flags, output_type): """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.""" + dir = _os.path.abspath(dir) names = _get_candidate_names() if output_type is bytes: names = map(_os.fsencode, names) @@ -264,7 +264,7 @@ def _mkstemp_inner(dir, pre, suf, flags, output_type): continue else: raise - return (fd, _os.path.abspath(file)) + return fd, file raise FileExistsError(_errno.EEXIST, "No usable temporary file name found") @@ -554,15 +554,26 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, if "b" not in mode: encoding = _io.text_encoding(encoding) - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) + name = None + def opener(*args): + nonlocal name + fd, name = _mkstemp_inner(dir, prefix, suffix, flags, output_type) + return fd try: - file = _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding, errors=errors) - - return _TemporaryFileWrapper(file, name, delete) - except BaseException: - _os.unlink(name) - _os.close(fd) + file = _io.open(dir, mode, buffering=buffering, + newline=newline, encoding=encoding, errors=errors, + opener=opener) + try: + raw = getattr(file, 'buffer', file) + raw = getattr(raw, 'raw', raw) + raw.name = name + return _TemporaryFileWrapper(file, name, delete) + except: + file.close() + raise + except: + if name is not None and not (_os.name == 'nt' and delete): + _os.unlink(name) raise if _os.name != 'posix' or _sys.platform == 'cygwin': @@ -601,9 +612,20 @@ else: flags = _bin_openflags if _O_TMPFILE_WORKS: - try: + fd = None + def opener(*args): + nonlocal fd flags2 = (flags | _os.O_TMPFILE) & ~_os.O_CREAT fd = _os.open(dir, flags2, 0o600) + return fd + try: + file = _io.open(dir, mode, buffering=buffering, + newline=newline, encoding=encoding, + errors=errors, opener=opener) + raw = getattr(file, 'buffer', file) + raw = getattr(raw, 'raw', raw) + raw.name = fd + return file except IsADirectoryError: # Linux kernel older than 3.11 ignores the O_TMPFILE flag: # O_TMPFILE is read as O_DIRECTORY. Trying to open a directory @@ -620,24 +642,25 @@ else: # fails with NotADirectoryError, because O_TMPFILE is read as # O_DIRECTORY. pass - else: - try: - return _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding, - errors=errors) - except: - _os.close(fd) - raise # Fallback to _mkstemp_inner(). - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) - try: - _os.unlink(name) - return _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding, errors=errors) - except: - _os.close(fd) - raise + fd = None + def opener(*args): + nonlocal fd + fd, name = _mkstemp_inner(dir, prefix, suffix, flags, output_type) + try: + _os.unlink(name) + except BaseException as e: + _os.close(fd) + raise + return fd + file = _io.open(dir, mode, buffering=buffering, + newline=newline, encoding=encoding, errors=errors, + opener=opener) + raw = getattr(file, 'buffer', file) + raw = getattr(raw, 'raw', raw) + raw.name = fd + return file class SpooledTemporaryFile(_io.IOBase): """Temporary file wrapper, specialized to switch from BytesIO |