diff --git a/django/utils/archive.py b/django/utils/archive.py
index 13f8afa..f8032d8 100644
|
a
|
b
|
|
| 27 | 27 | import zipfile |
| 28 | 28 | |
| 29 | 29 | from django.utils import six |
| | 30 | from django.utils._os import safe_join |
| 30 | 31 | |
| 31 | 32 | |
| 32 | 33 | class ArchiveException(Exception): |
| … |
… |
def extract(self, to_path):
|
| 146 | 147 | name = member.name |
| 147 | 148 | if leading: |
| 148 | 149 | name = self.split_leading_dir(name)[1] |
| 149 | | filename = os.path.join(to_path, name) |
| | 150 | filename = safe_join(to_path, name) |
| 150 | 151 | if member.isdir(): |
| 151 | 152 | if filename and not os.path.exists(filename): |
| 152 | 153 | os.makedirs(filename) |
| … |
… |
def extract(self, to_path):
|
| 187 | 188 | data = self._archive.read(name) |
| 188 | 189 | if leading: |
| 189 | 190 | name = self.split_leading_dir(name)[1] |
| 190 | | filename = os.path.join(to_path, name) |
| | 191 | if not name: |
| | 192 | continue |
| | 193 | filename = safe_join(to_path, name) |
| 191 | 194 | dirname = os.path.dirname(filename) |
| 192 | 195 | if dirname and not os.path.exists(dirname): |
| 193 | 196 | os.makedirs(dirname) |
| 194 | | if filename.endswith(('/', '\\')): |
| | 197 | if name.endswith(('/', '\\')): |
| 195 | 198 | # A directory |
| 196 | 199 | if not os.path.exists(filename): |
| 197 | 200 | os.makedirs(filename) |
diff --git a/tests/utils_tests/archives/absolute.tar b/tests/utils_tests/archives/absolute.tar
new file mode 100644
index 0000000..4522447
Binary files /dev/null and b/tests/utils_tests/archives/absolute.tar differ
diff --git a/tests/utils_tests/archives/dotdot.tar b/tests/utils_tests/archives/dotdot.tar
new file mode 100644
index 0000000..30cf436
Binary files /dev/null and b/tests/utils_tests/archives/dotdot.tar differ
diff --git a/tests/utils_tests/test_archive.py b/tests/utils_tests/test_archive.py
index d1dc5f2..929d22a 100644
|
a
|
b
|
|
| 3 | 3 | import tempfile |
| 4 | 4 | import unittest |
| 5 | 5 | |
| | 6 | from django.core.exceptions import SuspiciousFileOperation |
| 6 | 7 | from django.utils._os import upath |
| 7 | 8 | from django.utils.archive import Archive, extract |
| 8 | 9 | |
| … |
… |
def check_files(self, tmpdir):
|
| 60 | 61 | self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'foo', 'bar', '2'))) |
| 61 | 62 | |
| 62 | 63 | |
| | 64 | class TestSafeUnarchival(unittest.TestCase): |
| | 65 | |
| | 66 | def setUp(self): |
| | 67 | """ |
| | 68 | Create temporary directory for testing extraction. |
| | 69 | """ |
| | 70 | self.old_cwd = os.getcwd() |
| | 71 | self.tmpdir = tempfile.mkdtemp() |
| | 72 | self.addCleanup(shutil.rmtree, self.tmpdir) |
| | 73 | # Always start off in TEST_DIR. |
| | 74 | os.chdir(TEST_DIR) |
| | 75 | |
| | 76 | def test_absolute_path(self): |
| | 77 | path = os.path.join(TEST_DIR, 'absolute.tar') |
| | 78 | with self.assertRaises(SuspiciousFileOperation): |
| | 79 | extract(path) |
| | 80 | |
| | 81 | def test_no_dotdot_in_path(self): |
| | 82 | path = os.path.join(TEST_DIR, 'dotdot.tar') |
| | 83 | with self.assertRaises(SuspiciousFileOperation): |
| | 84 | extract(path) |
| | 85 | |
| | 86 | |
| 63 | 87 | class TestZip(ArchiveTester, unittest.TestCase): |
| 64 | 88 | archive = 'foobar.zip' |
| 65 | 89 | |