mirror of
https://github.com/python/cpython.git
synced 2024-11-21 12:59:38 +01:00
Avoid race conditions in the creation of directories during concurrent extraction in tarfile and zipfile. Co-authored-by: Samantha Hughes <shughes-uk@users.noreply.github.com> Co-authored-by: Peder Bergebakken Sundt <pbsds@hotmail.com>
This commit is contained in:
parent
bf75f1b147
commit
5d2794a16b
@ -2411,7 +2411,7 @@ class TarFile(object):
|
||||
if upperdirs and not os.path.exists(upperdirs):
|
||||
# Create directories that are not part of the archive with
|
||||
# default permissions.
|
||||
os.makedirs(upperdirs)
|
||||
os.makedirs(upperdirs, exist_ok=True)
|
||||
|
||||
if tarinfo.islnk() or tarinfo.issym():
|
||||
self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
|
||||
|
@ -3,6 +3,7 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from test.support import swap_attr
|
||||
from test.support import os_helper
|
||||
|
||||
class OverwriteTests:
|
||||
@ -153,3 +154,24 @@ class OverwriteTests:
|
||||
self.extractall(ar)
|
||||
self.assertTrue(os.path.islink(target))
|
||||
self.assertFalse(os.path.exists(target2))
|
||||
|
||||
def test_concurrent_extract_dir(self):
|
||||
target = os.path.join(self.testdir, 'test')
|
||||
def concurrent_mkdir(*args, **kwargs):
|
||||
orig_mkdir(*args, **kwargs)
|
||||
orig_mkdir(*args, **kwargs)
|
||||
with swap_attr(os, 'mkdir', concurrent_mkdir) as orig_mkdir:
|
||||
with self.open(self.ar_with_dir) as ar:
|
||||
self.extractall(ar)
|
||||
self.assertTrue(os.path.isdir(target))
|
||||
|
||||
def test_concurrent_extract_implicit_dir(self):
|
||||
target = os.path.join(self.testdir, 'test')
|
||||
def concurrent_mkdir(*args, **kwargs):
|
||||
orig_mkdir(*args, **kwargs)
|
||||
orig_mkdir(*args, **kwargs)
|
||||
with swap_attr(os, 'mkdir', concurrent_mkdir) as orig_mkdir:
|
||||
with self.open(self.ar_with_implicit_dir) as ar:
|
||||
self.extractall(ar)
|
||||
self.assertTrue(os.path.isdir(target))
|
||||
self.assertTrue(os.path.isfile(os.path.join(target, 'file')))
|
||||
|
@ -1802,11 +1802,15 @@ class ZipFile:
|
||||
# Create all upper directories if necessary.
|
||||
upperdirs = os.path.dirname(targetpath)
|
||||
if upperdirs and not os.path.exists(upperdirs):
|
||||
os.makedirs(upperdirs)
|
||||
os.makedirs(upperdirs, exist_ok=True)
|
||||
|
||||
if member.is_dir():
|
||||
if not os.path.isdir(targetpath):
|
||||
os.mkdir(targetpath)
|
||||
try:
|
||||
os.mkdir(targetpath)
|
||||
except FileExistsError:
|
||||
if not os.path.isdir(targetpath):
|
||||
raise
|
||||
return targetpath
|
||||
|
||||
with self.open(member, pwd=pwd) as source, \
|
||||
|
@ -0,0 +1,2 @@
|
||||
Avoid race conditions in the creation of directories during concurrent
|
||||
extraction in :mod:`tarfile` and :mod:`zipfile`.
|
Loading…
Reference in New Issue
Block a user