Skip to content

gh-161060: Fix pyexpat crash when the default handler is cleared - #161061

Merged
gpshead merged 3 commits into
python:mainfrom
gpshead:scanfix-pyexpat-0sjb3wwc
Nov 12, 2026
Merged

gpshead merged 3 commits into
python:mainfrom
gpshead:scanfix-pyexpat-0sjb3wwc

Conversation

@gpshead

@gpshead gpshead commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Expat calls the default handler once per 1024-byte piece of a token that needs encoding conversion and re-reads the handler pointer between pieces, so pyexpat must not set it to NULL from inside a callback. When handlers are cleared after an error, or DefaultHandler/DefaultHandlerExpand is set to None from inside a callback, install the existing no-op handler instead, as has been done for the character data handler since gh-42389. The Python-level handlers are still cleared, so no Python code runs after an error, and the handler setters are called in the same order, so the internal-entity expansion setting ends up as before.

Fixes #161060

ANT-2026-0SJB3WWC

Expat calls the default handler once per 1024-byte piece of a token that
needs encoding conversion.  Install a no-op instead of NULL when the
handler is cleared after an error or unset from within a callback, as is
already done for the character data handler.
@gpshead
gpshead marked this pull request as ready for review November 1, 2026 06:00
The handler setter only installs the no-op handler in place of NULL while
in_callback is set, but the trampolines reset it before releasing the
handler's result.  A destructor run at that point could still set the
default handler to None, removing it while Expat was passing a long token
to it in pieces.

Also test unsetting DefaultHandlerExpand from within a callback, and
reword the NEWS entry and a comment.
@gpshead
gpshead enabled auto-merge (squash) November 12, 2026 00:09
@gpshead
gpshead merged commit eb21dea into python:main Nov 12, 2026
57 checks passed
@miss-islington-app

Copy link
Copy Markdown

Thanks @gpshead for the PR 🌮🎉.. I'm working now to backport this PR to: 3.14, 3.15.
🐍🍒⛏🤖

@miss-islington-app

Copy link
Copy Markdown

Sorry, @gpshead, I could not cleanly backport this to 3.14 due to a conflict.

Please backport manually with cherry_picker, see the devguide for more information.

cherry_picker eb21dea301df801352ac6b4b21117fe6ef5cae4e 3.14

@bedevere-app

bedevere-app Bot commented Nov 12, 2026

Copy link
Copy Markdown

GH-161842 is a backport of this pull request to the 3.15 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 bugs and security fixes label Nov 12, 2026
gpshead added a commit that referenced this pull request Nov 12, 2026
…ed (GH-161061) (#161842)

gh-161060: Fix pyexpat crash when the default handler is cleared (GH-161061)

Expat calls the default handler once per 1024-byte piece of a token that
needs encoding conversion.  Install a no-op instead of NULL when the
handler is cleared after an error or unset from within a callback, as is
already done for the character data handler.

ANT-2026-0SJB3WWC
(cherry picked from commit eb21dea)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
@bedevere-app

bedevere-app Bot commented Nov 12, 2026

Copy link
Copy Markdown

GH-161846 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Nov 12, 2026
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.

xml.parsers.expat crashes when DefaultHandler raises on a long non-UTF-8 token

1 participant