Skip to content

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

Open
tonghuaroot wants to merge 3 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 3 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.
Comment thread Python/crossinterp.c
}
}
const char *err = PyUnicode_AsUTF8(msgobj);
if (err == NULL) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe we should add another PyUnicode_Check before this call.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need the result check in any case, because PyUnicode_AsUTF8() can fail for other reasons -- embedded surrogates or failed memory allocation. If the errors were not silenced, PyUnicode_Check() would be more preferable, but in the current code it would not have advantage.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I proposed PyUnicode_Check not as opposite, but as an addition to current check.

@serhiy-storchaka serhiy-storchaka added needs backport to 3.15 pre-release feature fixes, bugs and security fixes needs backport to 3.14 bugs and security fixes labels Aug 16, 2026

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

./python -m test test_interpreters.test_queues runs now the whole test suite. This is a regression of this PR.

Comment thread Python/crossinterp.c
}
}
const char *err = PyUnicode_AsUTF8(msgobj);
if (err == NULL) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need the result check in any case, because PyUnicode_AsUTF8() can fail for other reasons -- embedded surrogates or failed memory allocation. If the errors were not silenced, PyUnicode_Check() would be more preferable, but in the current code it would not have advantage.

@bedevere-app

bedevere-app Bot commented Aug 16, 2026

Copy link
Copy Markdown

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

The positive-control arg crafted a "module '__main__' has no attribute" message, which the cross-interpreter path matched and re-executed __main__ (the test runner) in-process. Drop that case and build the module in memory instead of writing a file, so test_interpreters.test_queues runs in isolation again.
@tonghuaroot

Copy link
Copy Markdown
Contributor Author

Fixed in 7cadf94: the positive-control arg spelled a module '__main__' has no attribute ... message, which the cross-interpreter path matched and re-ran __main__ (the test runner) in-process. Dropped that case and build the module in memory instead of writing a file, so test_interpreters.test_queues runs in isolation again.

I have made the requested changes; please review again.

@bedevere-app

bedevere-app Bot commented Aug 16, 2026

Copy link
Copy Markdown

Thanks for making the requested changes!

@serhiy-storchaka: please review the changes made to this pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting change review needs backport to 3.14 bugs and security fixes needs backport to 3.15 pre-release feature fixes, bugs and security fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants