Skip to content

gh-151862: Fix NULL deref on non-str AttributeError when unpickling#151863

Open
tonghuaroot wants to merge 2 commits into
python:mainfrom
tonghuaroot:fix-crossinterp-asutf8-nullderef
Open

gh-151862: Fix NULL deref on non-str AttributeError when unpickling#151863
tonghuaroot wants to merge 2 commits into
python:mainfrom
tonghuaroot:fix-crossinterp-asutf8-nullderef

Conversation

@tonghuaroot

@tonghuaroot tonghuaroot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Python/crossinterp.c's check_missing___main___attr() passed the result of PyUnicode_AsUTF8() straight to strncmp() without a NULL check. msgobj is args[0] of an AttributeError raised on the receive side of the cross-interpreter pickle fallback (a concurrent.interpreters queue or channel). When args[0] is not a str (AttributeError(42), AttributeError(b'x'), AttributeError(None)) or is a str with lone surrogates (AttributeError('\ud800')), PyUnicode_AsUTF8() returns NULL and strncmp(NULL, ...) crashes the interpreter.

This adds a NULL guard matching the checked sibling helper _copy_string_obj_raw(). Because PyUnicode_AsUTF8 sets an exception on failure and the function asserts !PyErr_Occurred() on entry, the guard clears it, Py_DECREF(msgobj) (mirroring the success-path decref), and returns 0 (not a missing-__main__ attribute), so the failure degrades to the normal NotShareableError.

A regression test is added in Lib/test/test_interpreters/test_queues.py covering all four args[0] shapes (42, b'x', None, '\ud800' — the surrogate case is a distinct branch: args[0] is unicode but fails UTF-8 encoding), plus a positive control with normal str args (including the genuine missing-__main__-attribute message shape) to lock in the non-NULL strncmp() path. Without the fix the test crashes; with it the queue raises NotShareableError.

This fixes the check_missing___main___attr() crash reached through the queue/channel receive path. A separate crash on the Interpreter.call() result-preserve path is reported independently.

…ling

An object crossing interpreters via a queue or channel is unpickled on
the receive side.  When that unpickling raised an ``AttributeError``
whose first argument was not a UTF-8-encodable string,
``PyUnicode_AsUTF8()`` returned ``NULL`` and the subsequent
``strncmp(NULL, ...)`` in ``check_missing___main___attr()`` dereferenced
it, crashing the interpreter.  Guard against the ``NULL`` result and
treat it as not a missing-``__main__``-attribute error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant