Skip to content

3.10.22.x: gh-151497 tarfile pre-allocation; rename XML_SetHashSalt16Bytes - #122

Merged
icanhasmath merged 2 commits into
3.10.22.xfrom
3.10.22.x-review-followups
Oct 29, 2026
Merged

icanhasmath merged 2 commits into
3.10.22.xfrom
3.10.22.x-review-followups

Conversation

@icanhasmath

Copy link
Copy Markdown

Two follow-ups from the 3.7.17.8 review (#117) that also apply to this line. For the next 3.10.22.x release.

What's in it

  • tarfile: memory exhaustion via oversized extended-header (GNU long name / pax) size field python/cpython#151497: tarfile no longer pre-allocates the size an extended header claims. A GNU long name/link or pax header's size comes from the archive, and tarfile read it with one read(size), so a 512-byte file could make tarfile.open() allocate gigabytes before any extraction filter runs. The header is now read in 1 MiB chunks. Cherry-picked from upstream 3.13 (b83961a); upstream only backported it to 3.13 and 3.14. The test_tarfile conflict was context only.
  • pyexpatns.h renames XML_SetHashSalt16Bytes. Expat 2.9.0 added it and pyexpat and _elementtree call it, but it kept its unprefixed name, so it could clash with a system libexpat in the same process. The AllocTracker functions are already renamed on this line. Every XMLPARSEAPI function in the bundled expat.h is now renamed. Upstream main doesn't rename this one either.

Testing

  • tarfile: memory exhaustion via oversized extended-header (GNU long name / pax) size field python/cpython#151497: a 512-byte GNU long-name header that claims 3 GB, opened under a 1.5 GB address-space limit. Unfixed tarfile raises MemoryError trying to allocate the claimed size; with the fix it raises ReadError without the allocation. The three new ExtendedHeaderMemoryTest cases and the whole of test_tarfile pass.
  • pyexpatns.h: a Linux build of this branch has no unprefixed XML_ symbols in pyexpat, and PyExpat_XML_SetHashSalt16Bytes replaces XML_SetHashSalt16Bytes. test_pyexpat, test_xml_etree, test_xml_etree_c, test_sax, test_minidom, test_xml_dom_minicompat and test_tarfile pass.

miss-islington and others added 2 commits October 29, 2026 15:13
…rfile extended headers (pythonGH-151498) (pythonGH-151978)

tarfile reads a member's extended header (a GNU long name/link or a pax
header) with a single read sized by the header's size field:

    buf = tarfile.fileobj.read(self._block(self.size))

The size is taken from the archive and is not validated, so a ~512-byte
crafted file can claim several gigabytes (or, via base-256 encoding, far
more) and make read() pre-allocate that much memory -- on open/iterate,
before any extraction filter runs.

Read the extended-header data in bounded chunks instead, so an oversized
or truncated header can no longer force a huge allocation. The bytes
returned for valid archives are unchanged.
(cherry picked from commit da99711)

Co-authored-by: Shardul Deshpande <iamsharduld@users.noreply.github.com>

(cherry picked from commit b83961a)

3.10.22.x: the test_tarfile conflict was context only (test_extractfile_attrs, pythongh-74468, isn't on this line); only the ReadSizeRecorder and ExtendedHeaderMemoryTest classes are added.
pyexpatns.h prefixes the bundled Expat's exported symbols with PyExpat_ so
they cannot clash with a system libexpat loaded in the same process. Expat
2.9.0 added XML_SetHashSalt16Bytes, which pyexpat and _elementtree call,
but the header did not rename it (upstream main does not either). The
AllocTracker functions are already renamed on this line. Same change as
3.7.17.x 69ab1c8 (#117 review).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@icanhasmath icanhasmath mentioned this pull request Oct 29, 2026

@ezequielp-activestate ezequielp-activestate left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving.

  • The pythongh-151497 port matches upstream 3.13 (b83961ade8) line for line, apart from one blank line. Upstream has no follow-ups to it.
  • With this branch's Lib/test on a python:3.10 image, test_tarfile passes with this branch's tarfile.py and fails with the 3.10.22.x one.
  • The pyexpatns.h change adds XML_SetHashSalt16Bytes. Every XML_* function declared in the bundled expat.h now has a PyExpat_ rename.

@icanhasmath
icanhasmath merged commit 2a7f779 into 3.10.22.x Oct 29, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants