Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8ed20bc

Browse files
[3.12]gh-114959: tarfile: do not ignore errors when extract a directory on top of a file (GH-114960) (GH-114963)
Also, add tests common to tarfile and zipfile.(cherry picked from commit96bce03)Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parentc86a9e6 commit8ed20bc

File tree

5 files changed

+220
-1
lines changed

5 files changed

+220
-1
lines changed

‎Lib/tarfile.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2449,7 +2449,8 @@ def makedir(self, tarinfo, targetpath):
24492449
# later in _extract_member().
24502450
os.mkdir(targetpath,0o700)
24512451
exceptFileExistsError:
2452-
pass
2452+
ifnotos.path.isdir(targetpath):
2453+
raise
24532454

24542455
defmakefile(self,tarinfo,targetpath):
24552456
"""Make a file called targetpath.

‎Lib/test/archiver_tests.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
"""Tests common to tarfile and zipfile."""
2+
3+
importos
4+
importsys
5+
6+
fromtest.supportimportos_helper
7+
8+
classOverwriteTests:
9+
10+
defsetUp(self):
11+
os.makedirs(self.testdir)
12+
self.addCleanup(os_helper.rmtree,self.testdir)
13+
14+
defcreate_file(self,path,content=b''):
15+
withopen(path,'wb')asf:
16+
f.write(content)
17+
18+
defopen(self,path):
19+
raiseNotImplementedError
20+
21+
defextractall(self,ar):
22+
raiseNotImplementedError
23+
24+
25+
deftest_overwrite_file_as_file(self):
26+
target=os.path.join(self.testdir,'test')
27+
self.create_file(target,b'content')
28+
withself.open(self.ar_with_file)asar:
29+
self.extractall(ar)
30+
self.assertTrue(os.path.isfile(target))
31+
withopen(target,'rb')asf:
32+
self.assertEqual(f.read(),b'newcontent')
33+
34+
deftest_overwrite_dir_as_dir(self):
35+
target=os.path.join(self.testdir,'test')
36+
os.mkdir(target)
37+
withself.open(self.ar_with_dir)asar:
38+
self.extractall(ar)
39+
self.assertTrue(os.path.isdir(target))
40+
41+
deftest_overwrite_dir_as_implicit_dir(self):
42+
target=os.path.join(self.testdir,'test')
43+
os.mkdir(target)
44+
withself.open(self.ar_with_implicit_dir)asar:
45+
self.extractall(ar)
46+
self.assertTrue(os.path.isdir(target))
47+
self.assertTrue(os.path.isfile(os.path.join(target,'file')))
48+
withopen(os.path.join(target,'file'),'rb')asf:
49+
self.assertEqual(f.read(),b'newcontent')
50+
51+
deftest_overwrite_dir_as_file(self):
52+
target=os.path.join(self.testdir,'test')
53+
os.mkdir(target)
54+
withself.open(self.ar_with_file)asar:
55+
withself.assertRaises(PermissionErrorifsys.platform=='win32'
56+
elseIsADirectoryError):
57+
self.extractall(ar)
58+
self.assertTrue(os.path.isdir(target))
59+
60+
deftest_overwrite_file_as_dir(self):
61+
target=os.path.join(self.testdir,'test')
62+
self.create_file(target,b'content')
63+
withself.open(self.ar_with_dir)asar:
64+
withself.assertRaises(FileExistsError):
65+
self.extractall(ar)
66+
self.assertTrue(os.path.isfile(target))
67+
withopen(target,'rb')asf:
68+
self.assertEqual(f.read(),b'content')
69+
70+
deftest_overwrite_file_as_implicit_dir(self):
71+
target=os.path.join(self.testdir,'test')
72+
self.create_file(target,b'content')
73+
withself.open(self.ar_with_implicit_dir)asar:
74+
withself.assertRaises(FileNotFoundErrorifsys.platform=='win32'
75+
elseNotADirectoryError):
76+
self.extractall(ar)
77+
self.assertTrue(os.path.isfile(target))
78+
withopen(target,'rb')asf:
79+
self.assertEqual(f.read(),b'content')
80+
81+
@os_helper.skip_unless_symlink
82+
deftest_overwrite_file_symlink_as_file(self):
83+
# XXX: It is potential security vulnerability.
84+
target=os.path.join(self.testdir,'test')
85+
target2=os.path.join(self.testdir,'test2')
86+
self.create_file(target2,b'content')
87+
os.symlink('test2',target)
88+
withself.open(self.ar_with_file)asar:
89+
self.extractall(ar)
90+
self.assertTrue(os.path.islink(target))
91+
self.assertTrue(os.path.isfile(target2))
92+
withopen(target2,'rb')asf:
93+
self.assertEqual(f.read(),b'newcontent')
94+
95+
@os_helper.skip_unless_symlink
96+
deftest_overwrite_broken_file_symlink_as_file(self):
97+
# XXX: It is potential security vulnerability.
98+
target=os.path.join(self.testdir,'test')
99+
target2=os.path.join(self.testdir,'test2')
100+
os.symlink('test2',target)
101+
withself.open(self.ar_with_file)asar:
102+
self.extractall(ar)
103+
self.assertTrue(os.path.islink(target))
104+
self.assertTrue(os.path.isfile(target2))
105+
withopen(target2,'rb')asf:
106+
self.assertEqual(f.read(),b'newcontent')
107+
108+
@os_helper.skip_unless_symlink
109+
deftest_overwrite_dir_symlink_as_dir(self):
110+
# XXX: It is potential security vulnerability.
111+
target=os.path.join(self.testdir,'test')
112+
target2=os.path.join(self.testdir,'test2')
113+
os.mkdir(target2)
114+
os.symlink('test2',target,target_is_directory=True)
115+
withself.open(self.ar_with_dir)asar:
116+
self.extractall(ar)
117+
self.assertTrue(os.path.islink(target))
118+
self.assertTrue(os.path.isdir(target2))
119+
120+
@os_helper.skip_unless_symlink
121+
deftest_overwrite_dir_symlink_as_implicit_dir(self):
122+
# XXX: It is potential security vulnerability.
123+
target=os.path.join(self.testdir,'test')
124+
target2=os.path.join(self.testdir,'test2')
125+
os.mkdir(target2)
126+
os.symlink('test2',target,target_is_directory=True)
127+
withself.open(self.ar_with_implicit_dir)asar:
128+
self.extractall(ar)
129+
self.assertTrue(os.path.islink(target))
130+
self.assertTrue(os.path.isdir(target2))
131+
self.assertTrue(os.path.isfile(os.path.join(target2,'file')))
132+
withopen(os.path.join(target2,'file'),'rb')asf:
133+
self.assertEqual(f.read(),b'newcontent')
134+
135+
@os_helper.skip_unless_symlink
136+
deftest_overwrite_broken_dir_symlink_as_dir(self):
137+
target=os.path.join(self.testdir,'test')
138+
target2=os.path.join(self.testdir,'test2')
139+
os.symlink('test2',target,target_is_directory=True)
140+
withself.open(self.ar_with_dir)asar:
141+
withself.assertRaises(FileExistsError):
142+
self.extractall(ar)
143+
self.assertTrue(os.path.islink(target))
144+
self.assertFalse(os.path.exists(target2))
145+
146+
@os_helper.skip_unless_symlink
147+
deftest_overwrite_broken_dir_symlink_as_implicit_dir(self):
148+
target=os.path.join(self.testdir,'test')
149+
target2=os.path.join(self.testdir,'test2')
150+
os.symlink('test2',target,target_is_directory=True)
151+
withself.open(self.ar_with_implicit_dir)asar:
152+
withself.assertRaises(FileExistsError):
153+
self.extractall(ar)
154+
self.assertTrue(os.path.islink(target))
155+
self.assertFalse(os.path.exists(target2))

‎Lib/test/test_tarfile.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
importunittest.mock
1616
importtarfile
1717

18+
fromtestimportarchiver_tests
1819
fromtestimportsupport
1920
fromtest.supportimportos_helper
2021
fromtest.supportimportscript_helper
@@ -4089,6 +4090,38 @@ def valueerror_filter(tarinfo, path):
40894090
self.expect_exception(TypeError)# errorlevel is not int
40904091

40914092

4093+
classOverwriteTests(archiver_tests.OverwriteTests,unittest.TestCase):
4094+
testdir=os.path.join(TEMPDIR,"testoverwrite")
4095+
4096+
@classmethod
4097+
defsetUpClass(cls):
4098+
p=cls.ar_with_file=os.path.join(TEMPDIR,'tar-with-file.tar')
4099+
cls.addClassCleanup(os_helper.unlink,p)
4100+
withtarfile.open(p,'w')astar:
4101+
t=tarfile.TarInfo('test')
4102+
t.size=10
4103+
tar.addfile(t,io.BytesIO(b'newcontent'))
4104+
4105+
p=cls.ar_with_dir=os.path.join(TEMPDIR,'tar-with-dir.tar')
4106+
cls.addClassCleanup(os_helper.unlink,p)
4107+
withtarfile.open(p,'w')astar:
4108+
tar.addfile(tar.gettarinfo(os.curdir,'test'))
4109+
4110+
p=os.path.join(TEMPDIR,'tar-with-implicit-dir.tar')
4111+
cls.ar_with_implicit_dir=p
4112+
cls.addClassCleanup(os_helper.unlink,p)
4113+
withtarfile.open(p,'w')astar:
4114+
t=tarfile.TarInfo('test/file')
4115+
t.size=10
4116+
tar.addfile(t,io.BytesIO(b'newcontent'))
4117+
4118+
defopen(self,path):
4119+
returntarfile.open(path,'r')
4120+
4121+
defextractall(self,ar):
4122+
ar.extractall(self.testdir,filter='fully_trusted')
4123+
4124+
40924125
defsetUpModule():
40934126
os_helper.unlink(TEMPDIR)
40944127
os.makedirs(TEMPDIR)

‎Lib/test/test_zipfile/test_core.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
fromtempfileimportTemporaryFile
1919
fromrandomimportrandint,random,randbytes
2020

21+
fromtestimportarchiver_tests
2122
fromtest.supportimportscript_helper
2223
fromtest.supportimport (
2324
findfile,requires_zlib,requires_bz2,requires_lzma,
@@ -1687,6 +1688,33 @@ def _test_extract_hackers_arcnames(self, hacknames):
16871688
unlink(TESTFN2)
16881689

16891690

1691+
classOverwriteTests(archiver_tests.OverwriteTests,unittest.TestCase):
1692+
testdir=TESTFN
1693+
1694+
@classmethod
1695+
defsetUpClass(cls):
1696+
p=cls.ar_with_file=TESTFN+'-with-file.zip'
1697+
cls.addClassCleanup(unlink,p)
1698+
withzipfile.ZipFile(p,'w')aszipfp:
1699+
zipfp.writestr('test',b'newcontent')
1700+
1701+
p=cls.ar_with_dir=TESTFN+'-with-dir.zip'
1702+
cls.addClassCleanup(unlink,p)
1703+
withzipfile.ZipFile(p,'w')aszipfp:
1704+
zipfp.mkdir('test')
1705+
1706+
p=cls.ar_with_implicit_dir=TESTFN+'-with-implicit-dir.zip'
1707+
cls.addClassCleanup(unlink,p)
1708+
withzipfile.ZipFile(p,'w')aszipfp:
1709+
zipfp.writestr('test/file',b'newcontent')
1710+
1711+
defopen(self,path):
1712+
returnzipfile.ZipFile(path,'r')
1713+
1714+
defextractall(self,ar):
1715+
ar.extractall(self.testdir)
1716+
1717+
16901718
classOtherTests(unittest.TestCase):
16911719
deftest_open_via_zip_info(self):
16921720
# Create the ZIP archive
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:mod:`tarfile` no longer ignores errors when trying to extract a directory on
2+
top of a file.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp