diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 69283f67487b18..9d8ebb9e39c905 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1593,6 +1593,13 @@ New deprecations (Contributed by Sergey B Kirpichev and Serhiy Storchaka in :gh:`143715`.) +* :mod:`tempfile`: + + * The ``prefix`` and ``suffix`` parameters of the tempfile functions, + :func:`tempfile.mkdtemp`, :func:`tempfile.mkstemp` and + :func:`tempfile.NamedTemporaryFile`, will be sanitized to use only the + basename of the provided values if they contain a directory separator. + * ``__version__`` * The ``__version__``, ``version`` and ``VERSION`` attributes have been diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 6dac9ab3c41717..3b3717843f2338 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() + elif _os.path.dirname(suffix): + suffix = _os.path.basename(suffix) if prefix is None: if output_type is str: prefix = template else: prefix = _os.fsencode(template) + elif _os.path.dirname(prefix): + prefix = _os.path.basename(prefix) 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 b2b5390af33b00..f322cae934222f 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -644,8 +644,10 @@ def do_create(self, dir=None, pre=None, suf=None): dir = tempfile.gettempdirb() if pre is None: pre = output_type() + pre = os.path.basename(pre) if suf is None: suf = output_type() + suf = os.path.basename(suf) (fd, name) = tempfile.mkstemp(dir=dir, prefix=pre, suffix=suf) (ndir, nbase) = os.path.split(name) adir = os.path.abspath(dir) @@ -666,6 +668,8 @@ def test_basic(self): self.do_create(pre="a", suf="b") self.do_create(pre="aa", suf=".txt") self.do_create(dir=".") + self.do_create(pre=f"{os.sep}myhome") + self.do_create(suf=f"{os.sep}home") def test_basic_with_bytes_names(self): # mkstemp can create files when given name parts all @@ -676,6 +680,8 @@ def test_basic_with_bytes_names(self): self.do_create(dir=d, suf=b"b") self.do_create(dir=d, pre=b"a", suf=b"b") self.do_create(dir=d, pre=b"aa", suf=b".txt") + self.do_create(dir=d, pre=os.fsencode(f"{os.sep}home")) + self.do_create(dir=d, suf=os.fsencode(f"{os.sep}home")) self.do_create(dir=b".") with self.assertRaises(TypeError): self.do_create(dir=".", pre=b"aa", suf=b".txt") @@ -743,6 +749,8 @@ def do_create(self, dir=None, pre=None, suf=None): pre = output_type() if suf is None: suf = output_type() + pre = os.path.basename(pre) + suf = os.path.basename(suf) name = tempfile.mkdtemp(dir=dir, prefix=pre, suffix=suf) try: @@ -759,6 +767,8 @@ def test_basic(self): os.rmdir(self.do_create(suf="b")) os.rmdir(self.do_create(pre="a", suf="b")) os.rmdir(self.do_create(pre="aa", suf=".txt")) + os.rmdir(self.do_create(pre=f"{os.sep}home")) + os.rmdir(self.do_create(suf=f"{os.sep}home")) def test_basic_with_bytes_names(self): # mkdtemp can create directories when given all binary parts @@ -768,6 +778,8 @@ def test_basic_with_bytes_names(self): os.rmdir(self.do_create(dir=d, suf=b"b")) os.rmdir(self.do_create(dir=d, pre=b"a", suf=b"b")) os.rmdir(self.do_create(dir=d, pre=b"aa", suf=b".txt")) + os.rmdir(self.do_create(dir=d, pre=os.fsencode(f"{os.sep}home"))) + os.rmdir(self.do_create(dir=d, suf=os.fsencode(f"{os.sep}home"))) with self.assertRaises(TypeError): os.rmdir(self.do_create(dir=d, pre="aa", suf=b".txt")) with self.assertRaises(TypeError): @@ -962,9 +974,19 @@ def test_many(self): class TestNamedTemporaryFile(BaseTestCase): """Test NamedTemporaryFile().""" - def do_create(self, dir=None, pre="", suf="", delete=True): + def do_create(self, dir=None, pre=None, suf=None, delete=True): + output_type = tempfile._infer_return_type(dir, pre, suf) if dir is None: - dir = tempfile.gettempdir() + if output_type is str: + dir = tempfile.gettempdir() + else: + dir = tempfile.gettempdirb() + if pre is None: + pre = output_type() + if suf is None: + suf = output_type() + pre = os.path.basename(pre) + suf = os.path.basename(suf) file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf, delete=delete) @@ -979,6 +1001,10 @@ def test_basic(self): self.do_create(suf="b") self.do_create(pre="a", suf="b") self.do_create(pre="aa", suf=".txt") + self.do_create(pre=f"{os.sep}home") + self.do_create(pre=os.fsencode(f"{os.sep}home")) + self.do_create(suf=f"{os.sep}home") + self.do_create(suf=os.fsencode(f"{os.sep}home")) def test_method_lookup(self): # Issue #18879: Looking up a temporary file method should keep it diff --git a/Misc/NEWS.d/next/Library/2026-01-16-09-57-17.gh-issue-79459.x1acn-.rst b/Misc/NEWS.d/next/Library/2026-01-16-09-57-17.gh-issue-79459.x1acn-.rst new file mode 100644 index 00000000000000..06ae5cf4f16213 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-16-09-57-17.gh-issue-79459.x1acn-.rst @@ -0,0 +1,2 @@ +Sanitize the ``prefix`` and ``suffix`` arguments to the functions: :func:`tempfile.mkdtemp`, :func:`tempfile.mkstemp` and :func:`tempfile.NamedTemporaryFile`. +If the value of ``prefix`` or ``suffix`` contain a directory separator then the basename of the value is used.