summaryrefslogtreecommitdiffstats
path: root/Lib/tarfile.py
diff options
context:
space:
mode:
authorLars Gustäbel <lars@gustaebel.de>2015-07-06 07:27:24 (GMT)
committerLars Gustäbel <lars@gustaebel.de>2015-07-06 07:27:24 (GMT)
commit0357268d96d4ff3546cfd89f594a5630a3adf747 (patch)
treee4a4869b686c5d72e546c24cbee377b6fcfcb407 /Lib/tarfile.py
parent54630d999f640b3ea0b9da302a112a0ccd5bdd96 (diff)
downloadcpython-0357268d96d4ff3546cfd89f594a5630a3adf747.zip
cpython-0357268d96d4ff3546cfd89f594a5630a3adf747.tar.gz
cpython-0357268d96d4ff3546cfd89f594a5630a3adf747.tar.bz2
Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment.
Diffstat (limited to 'Lib/tarfile.py')
-rwxr-xr-xLib/tarfile.py22
1 files changed, 15 insertions, 7 deletions
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 6d8d36c..5f1a979 100755
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -225,7 +225,7 @@ def calc_chksums(buf):
signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf))
return unsigned_chksum, signed_chksum
-def copyfileobj(src, dst, length=None):
+def copyfileobj(src, dst, length=None, exception=OSError):
"""Copy length bytes from fileobj src to fileobj dst.
If length is None, copy the entire content.
"""
@@ -240,13 +240,13 @@ def copyfileobj(src, dst, length=None):
for b in range(blocks):
buf = src.read(BUFSIZE)
if len(buf) < BUFSIZE:
- raise OSError("end of file reached")
+ raise exception("unexpected end of data")
dst.write(buf)
if remainder != 0:
buf = src.read(remainder)
if len(buf) < remainder:
- raise OSError("end of file reached")
+ raise exception("unexpected end of data")
dst.write(buf)
return
@@ -690,7 +690,10 @@ class _FileInFile(object):
length = min(size, stop - self.position)
if data:
self.fileobj.seek(offset + (self.position - start))
- buf += self.fileobj.read(length)
+ b = self.fileobj.read(length)
+ if len(b) != length:
+ raise ReadError("unexpected end of data")
+ buf += b
else:
buf += NUL * length
size -= length
@@ -2132,9 +2135,9 @@ class TarFile(object):
if tarinfo.sparse is not None:
for offset, size in tarinfo.sparse:
target.seek(offset)
- copyfileobj(source, target, size)
+ copyfileobj(source, target, size, ReadError)
else:
- copyfileobj(source, target, tarinfo.size)
+ copyfileobj(source, target, tarinfo.size, ReadError)
target.seek(tarinfo.size)
target.truncate()
@@ -2244,8 +2247,13 @@ class TarFile(object):
self.firstmember = None
return m
+ # Advance the file pointer.
+ if self.offset != self.fileobj.tell():
+ self.fileobj.seek(self.offset - 1)
+ if not self.fileobj.read(1):
+ raise ReadError("unexpected end of data")
+
# Read the next block.
- self.fileobj.seek(self.offset)
tarinfo = None
while True:
try: