From a4b2381b20edfc8be76df63ef06c0f15959ad7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gust=C3=A4bel?= Date: Sat, 23 Dec 2006 17:57:23 +0000 Subject: Patch #1262036: Prevent TarFiles from being added to themselves under certain conditions. Will backport to 2.5. --- Lib/tarfile.py | 33 ++++++--------------------------- Lib/test/test_tarfile.py | 14 ++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 46031e1..658f214 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1052,7 +1052,7 @@ class TarFile(object): can be determined, `mode' is overridden by `fileobj's mode. `fileobj' is not closed, when TarFile is closed. """ - self.name = name + self.name = os.path.abspath(name) if len(mode) > 1 or mode not in "raw": raise ValueError("mode must be 'r', 'a' or 'w'") @@ -1064,7 +1064,7 @@ class TarFile(object): self._extfileobj = False else: if self.name is None and hasattr(fileobj, "name"): - self.name = fileobj.name + self.name = os.path.abspath(fileobj.name) if hasattr(fileobj, "mode"): self.mode = fileobj.mode self._extfileobj = True @@ -1200,24 +1200,12 @@ class TarFile(object): except (ImportError, AttributeError): raise CompressionError("gzip module is not available") - pre, ext = os.path.splitext(name) - pre = os.path.basename(pre) - if ext == ".tgz": - ext = ".tar" - if ext == ".gz": - ext = "" - tarname = pre + ext - if fileobj is None: fileobj = file(name, mode + "b") - if mode != "r": - name = tarname - try: - t = cls.taropen(tarname, mode, - gzip.GzipFile(name, mode, compresslevel, fileobj) - ) + t = cls.taropen(name, mode, + gzip.GzipFile(name, mode, compresslevel, fileobj)) except IOError: raise ReadError("not a gzip file") t._extfileobj = False @@ -1236,21 +1224,13 @@ class TarFile(object): except ImportError: raise CompressionError("bz2 module is not available") - pre, ext = os.path.splitext(name) - pre = os.path.basename(pre) - if ext == ".tbz2": - ext = ".tar" - if ext == ".bz2": - ext = "" - tarname = pre + ext - if fileobj is not None: fileobj = _BZ2Proxy(fileobj, mode) else: fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) try: - t = cls.taropen(tarname, mode, fileobj) + t = cls.taropen(name, mode, fileobj) except IOError: raise ReadError("not a bzip2 file") t._extfileobj = False @@ -1455,8 +1435,7 @@ class TarFile(object): arcname = name # Skip if somebody tries to archive the archive... - if self.name is not None \ - and os.path.abspath(name) == os.path.abspath(self.name): + if self.name is not None and os.path.abspath(name) == self.name: self._dbg(2, "tarfile: Skipped %r" % name) return diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 867eca4..a76ceb1 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -290,6 +290,20 @@ class WriteTest(BaseTest): else: self.dst.addfile(tarinfo, f) + def test_add_self(self): + dstname = os.path.abspath(self.dstname) + + self.assertEqual(self.dst.name, dstname, "archive name must be absolute") + + self.dst.add(dstname) + self.assertEqual(self.dst.getnames(), [], "added the archive to itself") + + cwd = os.getcwd() + os.chdir(dirname()) + self.dst.add(dstname) + os.chdir(cwd) + self.assertEqual(self.dst.getnames(), [], "added the archive to itself") + class Write100Test(BaseTest): # The name field in a tar header stores strings of at most 100 chars. diff --git a/Misc/NEWS b/Misc/NEWS index ae4d0d0..92f81eb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -103,6 +103,9 @@ Core and builtins Library ------- +- Patch #1262036: Prevent TarFiles from being added to themselves under + certain conditions. + - Patch #1230446: tarfile.py: fix ExFileObject so that read() and tell() work correctly together with readline(). -- cgit v0.12