From f5a91add482a94d622edc572233092ee44f5b1df Mon Sep 17 00:00:00 2001 From: Igor Bolshakov Date: Mon, 29 Mar 2021 00:23:30 +0300 Subject: [PATCH 1/3] Fix MemoryError on zip.read in shutil._unpack_zipfile for large files --- Lib/shutil.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index e29fe4d83e9277..21a7f2d9ef5de0 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1161,20 +1161,16 @@ def _unpack_zipfile(filename, extract_dir): if name.startswith('/') or '..' in name: continue - target = os.path.join(extract_dir, *name.split('/')) - if not target: + targetpath = os.path.join(extract_dir, *name.split('/')) + if not targetpath: continue - _ensure_directory(target) + _ensure_directory(targetpath) if not name.endswith('/'): # file - data = zip.read(info.filename) - f = open(target, 'wb') - try: - f.write(data) - finally: - f.close() - del data + with zip.open(name, 'r') as source, \ + open(targetpath, "wb") as target: + copyfileobj(source, target) finally: zip.close() From 9ff999e0211a28dc59e2201ddf0903c73d8cf65b Mon Sep 17 00:00:00 2001 From: Igor Bolshakov Date: Tue, 30 Mar 2021 07:14:43 +0300 Subject: [PATCH 2/3] changes description in Misc/NEWS.d --- .../next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst diff --git a/Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst b/Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst new file mode 100644 index 00000000000000..a2ea4a4800a738 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst @@ -0,0 +1,2 @@ +Fix :exc:`MemoryError` in :func:`shutil.unpack_archive` which fails inside +:func:`shutil._unpack_zipfile` on large files. Patch by Igor Bolshakov. From e422cc5f016c080404af41680e6de0583ba834d4 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Mon, 17 May 2021 01:04:58 -0700 Subject: [PATCH 3/3] keep the quote style consistent. --- Lib/shutil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 21a7f2d9ef5de0..33f2ca94bf4bca 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1169,7 +1169,7 @@ def _unpack_zipfile(filename, extract_dir): if not name.endswith('/'): # file with zip.open(name, 'r') as source, \ - open(targetpath, "wb") as target: + open(targetpath, 'wb') as target: copyfileobj(source, target) finally: zip.close()