From 2f8e2491453a5d0e0a90cb11059fc32a2163ec0f Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Tue, 26 May 2026 16:12:25 +0200 Subject: [PATCH 1/2] tempfile: Raise a ``ValueError`` if the ``prefix`` or ``suffix`` contains a directory component. gh-79459 --- Lib/tempfile.py | 4 ++++ Lib/test/test_tempfile.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 6dac9ab3c41717..0cfac56ceb8845 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -117,11 +117,15 @@ def _sanitize_params(prefix, suffix, dir): output_type = _infer_return_type(prefix, suffix, dir) if suffix is None: suffix = output_type() + if _os.path.dirname(suffix): + raise ValueError("'prefix' or 'suffix' can't contain a directory component") if prefix is None: if output_type is str: prefix = template else: prefix = _os.fsencode(template) + if _os.path.dirname(prefix): + raise ValueError("'prefix' or 'suffix' can't contain a directory component") if dir is None: if output_type is str: dir = gettempdir() diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 0e00ff1d0cc366..eed3ad10fa19cd 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -2054,5 +2054,30 @@ def test_delete_false(self): self.assertTrue(os.path.exists(working_dir)) shutil.rmtree(working_dir) + +class TestPrefixAndSuffix(BaseTestCase): + def test_value_error_if_prefix_or_suffix_contains_directory(self): + MESSAGE = "'prefix' or 'suffix' can't contain a directory component" + + if os.altsep is None: + data = ( + ((os.sep), None), + (os.fsencode(os.sep), tempfile.gettempdirb()), + ) + else: + data = ( + ((os.altsep), None), + (os.fsencode(os.altsep), tempfile.gettempdirb()), + ) + + for value, directory in data: + with self.subTest((value, directory)): + with self.assertRaisesRegex(ValueError, MESSAGE): + tempfile.mkstemp(dir=directory, prefix=value) + with self.assertRaisesRegex(ValueError, MESSAGE): + os.rmdir(tempfile.mkdtemp(dir=directory, prefix=value)) + with self.assertRaisesRegex(ValueError, MESSAGE): + tempfile.NamedTemporaryFile(dir=directory, prefix=value, delete=True) + if __name__ == "__main__": unittest.main() From 08a6afbd7ecea586d09b5febc44a89640284becd Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Tue, 26 May 2026 23:55:17 +0200 Subject: [PATCH 2/2] Use code-review suggestions. Co-authored-by: Victor Stinner --- Lib/tempfile.py | 4 +-- Lib/test/test_tempfile.py | 55 ++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 0cfac56ceb8845..f0329ed841bb1c 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -118,14 +118,14 @@ def _sanitize_params(prefix, suffix, dir): if suffix is None: suffix = output_type() if _os.path.dirname(suffix): - raise ValueError("'prefix' or 'suffix' can't contain a directory component") + raise ValueError("'suffix' can't contain a directory component") if prefix is None: if output_type is str: prefix = template else: prefix = _os.fsencode(template) if _os.path.dirname(prefix): - raise ValueError("'prefix' or 'suffix' can't contain a directory component") + raise ValueError("'prefix' can't contain a directory component") if dir is None: if output_type is str: dir = gettempdir() diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index eed3ad10fa19cd..d56c44c02ab001 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -2056,28 +2056,47 @@ def test_delete_false(self): class TestPrefixAndSuffix(BaseTestCase): - def test_value_error_if_prefix_or_suffix_contains_directory(self): - MESSAGE = "'prefix' or 'suffix' can't contain a directory component" - - if os.altsep is None: - data = ( - ((os.sep), None), - (os.fsencode(os.sep), tempfile.gettempdirb()), - ) - else: - data = ( - ((os.altsep), None), - (os.fsencode(os.altsep), tempfile.gettempdirb()), - ) + DATA = ( + f"dir{os.sep}name", + f"{os.sep}abs_name", + os.fsencode(f"dir{os.sep}name"), + os.fsencode(f"{os.sep}abs_name"), + ) + if os.altsep is not None: + DATA += ( + f"dir{os.altsep}name", + f"{os.altsep}abs_name", + os.fsencode(f"dir{os.altsep}name"), + os.fsencode(f"{os.altsep}abs_name"), + ) + + def test_prefix_error(self): + MESSAGE = "'prefix' can't contain a directory component" + + for value in self.DATA: + with self.subTest((value)): + with self.assertRaisesRegex(ValueError, MESSAGE): + tempfile.mkstemp(prefix=value) + with self.assertRaisesRegex(ValueError, MESSAGE): + os.rmdir(tempfile.mkdtemp(prefix=value)) + with self.assertRaisesRegex(ValueError, MESSAGE): + tempfile.TemporaryFile(prefix=value) + with self.assertRaisesRegex(ValueError, MESSAGE): + tempfile.NamedTemporaryFile(prefix=value) - for value, directory in data: - with self.subTest((value, directory)): + def test_suffix_error(self): + MESSAGE = "'suffix' can't contain a directory component" + + for value in self.DATA: + with self.subTest((value)): + with self.assertRaisesRegex(ValueError, MESSAGE): + tempfile.mkstemp(suffix=value) with self.assertRaisesRegex(ValueError, MESSAGE): - tempfile.mkstemp(dir=directory, prefix=value) + os.rmdir(tempfile.mkdtemp(suffix=value)) with self.assertRaisesRegex(ValueError, MESSAGE): - os.rmdir(tempfile.mkdtemp(dir=directory, prefix=value)) + tempfile.TemporaryFile(suffix=value) with self.assertRaisesRegex(ValueError, MESSAGE): - tempfile.NamedTemporaryFile(dir=directory, prefix=value, delete=True) + tempfile.NamedTemporaryFile(suffix=value) if __name__ == "__main__": unittest.main()