Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e12aa62

Browse files
committed
Merge with 3.4: Issue #24259: tarfile now raises a ReadError if an archive is truncated inside a data segment.
2 parents 53ecc58 + 0357268 commit e12aa62

3 files changed

Lines changed: 41 additions & 7 deletions

File tree

Lib/tarfile.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def calc_chksums(buf):
225225
signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf))
226226
return unsigned_chksum, signed_chksum
227227

228-
def copyfileobj(src, dst, length=None):
228+
def copyfileobj(src, dst, length=None, exception=OSError):
229229
"""Copy length bytes from fileobj src to fileobj dst.
230230
If length is None, copy the entire content.
231231
"""
@@ -240,13 +240,13 @@ def copyfileobj(src, dst, length=None):
240240
for b in range(blocks):
241241
buf = src.read(BUFSIZE)
242242
if len(buf) < BUFSIZE:
243-
raise OSError("end of file reached")
243+
raise exception("unexpected end of data")
244244
dst.write(buf)
245245

246246
if remainder != 0:
247247
buf = src.read(remainder)
248248
if len(buf) < remainder:
249-
raise OSError("end of file reached")
249+
raise exception("unexpected end of data")
250250
dst.write(buf)
251251
return
252252

@@ -690,7 +690,10 @@ def read(self, size=None):
690690
length = min(size, stop - self.position)
691691
if data:
692692
self.fileobj.seek(offset + (self.position - start))
693-
buf += self.fileobj.read(length)
693+
b = self.fileobj.read(length)
694+
if len(b) != length:
695+
raise ReadError("unexpected end of data")
696+
buf += b
694697
else:
695698
buf += NUL * length
696699
size -= length
@@ -2150,9 +2153,9 @@ def makefile(self, tarinfo, targetpath):
21502153
if tarinfo.sparse is not None:
21512154
for offset, size in tarinfo.sparse:
21522155
target.seek(offset)
2153-
copyfileobj(source, target, size)
2156+
copyfileobj(source, target, size, ReadError)
21542157
else:
2155-
copyfileobj(source, target, tarinfo.size)
2158+
copyfileobj(source, target, tarinfo.size, ReadError)
21562159
target.seek(tarinfo.size)
21572160
target.truncate()
21582161

@@ -2267,8 +2270,13 @@ def next(self):
22672270
self.firstmember = None
22682271
return m
22692272

2273+
# Advance the file pointer.
2274+
if self.offset != self.fileobj.tell():
2275+
self.fileobj.seek(self.offset - 1)
2276+
if not self.fileobj.read(1):
2277+
raise ReadError("unexpected end of data")
2278+
22702279
# Read the next block.
2271-
self.fileobj.seek(self.offset)
22722280
tarinfo = None
22732281
while True:
22742282
try:

Lib/test/test_tarfile.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,29 @@ def test_ignore_zeros(self):
364364
finally:
365365
tar.close()
366366

367+
def test_premature_end_of_archive(self):
368+
for size in (512, 600, 1024, 1200):
369+
with tarfile.open(tmpname, "w:") as tar:
370+
t = tarfile.TarInfo("foo")
371+
t.size = 1024
372+
tar.addfile(t, io.BytesIO(b"a" * 1024))
373+
374+
with open(tmpname, "r+b") as fobj:
375+
fobj.truncate(size)
376+
377+
with tarfile.open(tmpname) as tar:
378+
with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"):
379+
for t in tar:
380+
pass
381+
382+
with tarfile.open(tmpname) as tar:
383+
t = tar.next()
384+
385+
with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"):
386+
tar.extract(t, TEMPDIR)
387+
388+
with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"):
389+
tar.extractfile(t).read()
367390

368391
class MiscReadTestBase(CommonReadTest):
369392
def requires_name_attribute(self):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ Core and Builtins
1717
Library
1818
-------
1919

20+
- Issue #24259: tarfile now raises a ReadError if an archive is truncated
21+
inside a data segment.
22+
2023

2124
What's New in Python 3.5.0 beta 3?
2225
==================================

0 commit comments

Comments
 (0)