Skip to content

Commit 1ba542d

Browse files
Add a test and rename the NEWS entry
The test builds a small archive with a pax size header for a GNU sparse 1.0 member, so that it does not need a file larger than 8 GiB. GNU tar, bsdtar and 7-Zip all read such an archive and find the member after the sparse file.
1 parent 553b694 commit 1ba542d

3 files changed

Lines changed: 37 additions & 2 deletions

File tree

Lib/test/test_tarfile.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,37 @@ def test_sparse_file_01(self):
13991399
def test_sparse_file_10(self):
14001400
self._test_sparse_file("gnu/sparse-1.0")
14011401

1402+
def test_sparse_file_10_pax_size(self):
1403+
# gh-83869: when the pax header replaces the size field, the offset
1404+
# of the next header must be computed from the size of the data in
1405+
# the archive, not from the apparent size of the sparse file.
1406+
data = b"payload!" * 4
1407+
realsize = 1 << 20
1408+
smap = b"1\n%d\n%d\n" % (realsize - len(data), len(data))
1409+
smap += b"\0" * (-len(smap) % tarfile.BLOCKSIZE)
1410+
1411+
sparse = tarfile.TarInfo("sparse")
1412+
sparse.size = len(smap) + len(data)
1413+
sparse.pax_headers = {
1414+
"GNU.sparse.major": "1",
1415+
"GNU.sparse.minor": "0",
1416+
"GNU.sparse.name": "sparse",
1417+
"GNU.sparse.realsize": str(realsize),
1418+
"size": str(sparse.size),
1419+
}
1420+
buf = sparse.tobuf(tarfile.PAX_FORMAT)
1421+
buf += smap + data + b"\0" * (-len(data) % tarfile.BLOCKSIZE)
1422+
1423+
last = tarfile.TarInfo("last")
1424+
last.size = len(data)
1425+
buf += last.tobuf(tarfile.PAX_FORMAT)
1426+
buf += data + b"\0" * (-len(data) % tarfile.BLOCKSIZE)
1427+
buf += b"\0" * (tarfile.BLOCKSIZE * 2)
1428+
1429+
with tarfile.open(fileobj=io.BytesIO(buf)) as tar:
1430+
self.assertEqual(tar.getnames(), ["sparse", "last"])
1431+
self.assertEqual(tar.extractfile("last").read(), data)
1432+
14021433
@staticmethod
14031434
def _fs_supports_holes():
14041435
# Return True if the platform knows the st_blocks stat attribute and

Misc/NEWS.d/next/Library/2020-02-19-16-35-52.bpo-39688.EPD_zn.rst

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Fix :mod:`tarfile` reading an archive with a GNU sparse 1.0 member whose
2+
size is set in the pax extended header.
3+
The offset of the next header was computed from the offset of the data,
4+
which is already past the sparse map, and from the size of the member,
5+
which can be the apparent size of the sparse file.
6+
All following members were unreachable.

0 commit comments

Comments
 (0)