GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-152682: Fix NULL dereference on OOM in symtable_visit_type_param_bound_or_default by petrvaganoff · Pull Request #152684 · python/cpython Conversation
|
| code = textwrap.dedent("""\ | ||
| import _testcapi | ||
| _testcapi.set_nomemory(0) | ||
| compile("class A[__classdict__]: pass", "<string>", "exec") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Can we catch the MemoryError here? And just assert that script works correctly with assert_python_ok?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done, updated the test to catch MemoryError and use assert_python_ok. Imports fixed.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…aram_bound_or_default In symtable_visit_type_param_bound_or_default(), when a reserved name (e.g. __classdict__) is used as a type parameter, PyUnicode_FromFormat() is called to build the SyntaxError message. If the allocation fails and returns NULL, the subsequent PyErr_SetObject() and Py_DECREF() calls would dereference NULL, causing a segfault. Fix by returning 0 immediately when PyUnicode_FromFormat() returns NULL. This propagates the MemoryError set by PyUnicode_FromFormat(). The bug was introduced in pythongh-128632 (commit 891c61c).
There was an error while loading. Please reload this page.
|
Thanks @petrvaganoff for the PR, and @sobolevn for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14, 3.15. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
GH-152695 is a backport of this pull request to the 3.15 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
GH-152696 is a backport of this pull request to the 3.14 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
GH-152697 is a backport of this pull request to the 3.13 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Congrats on your first CPython contribution! 🎉 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| """, "<testcase>", mode="exec") | ||
|
|
||
| @support.nomemtest | ||
| def test_disallowed_type_param_names_oom(self): |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This test passes for me on main.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, I also couldn't reproduce it reliably. After investigating, it seems _testcapi.set_nomemory(0) replaces the global CPython allocator with a stub, and there are many allocations happening between the set_nomemory(0) call and PyUnicode_FromFormat inside compile(), so OOM typically hits one of them first. I verified this with a coverage build - the relevant lines are never reached.
I also tried manually injecting an OOM condition in the C code - without the fix it does produce SIGSEGV, confirming the bug is real.
In principle, we could add a fault injection hook in the debug build and expose it via _testinternalcapi. But I think the simpler option is to drop the OOM test entirely - the fix is a straightforward NULL check, and the existing test_disallowed_type_param_names() already covers the code path. What do you think?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The test isn't doing anything, please remove it. In general we just don't test these cases.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
See please, - #152770
Sorry, something went wrong.
There was an error while loading. Please reload this page.
* main: (266 commits) pythongh-151626: Fix tests that fail when PYTHONPYCACHEPREFIX is set (pythonGH-151952) pythongh-152728: IDLE - move 3 toplevel fix_xyz functions to idlelb.util (python#152729) pythongh-152711: Add pythoninfo-build command to Platforms/Android (python#152713) pythongh-152715: Add pythoninfo-build command to Platforms/Apple (python#152716) pythongh-152433: Windows: enable mmapmodule for UWP (python#152473) pythongh-152433: Windows: use GetFileSizeEx instead of GetFileSize for memory mapped files (python#152383) pythonGH-81881: Raise `SpecialFileError` for sockets and devices in `shutil.copyfile` (python#142693) pythongh-152502: Detect the curses mouse interface and is_* methods portably (pythonGH-152705) pythongh-145857: Replace `DELETE_GLOBAL` with `PUSH_NULL; STORE_GLOBAL` (pythonGH-146314) pythongh-145854: Replace `DELETE_NAME` with `PUSH_NULL; STORE_NAME` (pythonGH-146006) pythongh-152680: Detect container/VM in test.pythoninfo (python#152668) pythongh-152682: Fix NULL dereference on OOM in `symtable_visit_type_param_bound_or_default` (python#152684) pythongh-151881: Skip tk_inactive negativity check on Windows (pythonGH-152683) pythongh-152546: Refactor `mappingproxy.__new__` to use `PyDictProxy_New` (python#152547) pythongh-151126: Fix a possible crash during the startup with no memory under `Py_STACKREF_DEBUG` (python#152478) pythongh-152635: Raise MemoryError when the lock allocation fails in `_interpchannels.create()` (python#152642) pythongh-151029: Fix `test_remote_exec_deleted_static_executable` on static installed builds (pythonGH-152653) pythongh-121249: Deprecate using F/D type codes in the struct module (python#152309) pythongh-152192: Fix JUMP_BACKWARD passing a truncated oparg to the jit tracer (pythonGH-152382) Don't require the `_test{internal}capi` modules in `test_monitoring.py` (python#152311) ...
…_param_bound_or_default` (GH-152684) (#152696) In `symtable_visit_type_param_bound_or_default()`, when a reserved name (e.g. `__classdict__`) is used as a type parameter, `PyUnicode_FromFormat()` is called to build the SyntaxError message. If the allocation fails and returns NULL, the subsequent `PyErr_SetObject()` and `Py_DECREF()` calls would dereference NULL, causing a segfault. Fix by returning 0 immediately when `PyUnicode_FromFormat()` returns NULL. This propagates the MemoryError set by `PyUnicode_FromFormat()`. The bug was introduced in gh-128632 (commit 891c61c). (cherry picked from commit 10ed03e) Co-authored-by: Petr Vaganov <[email protected]> * Remove test --------- Co-authored-by: Petr Vaganov <[email protected]> Co-authored-by: Stan Ulbrych <[email protected]>
…_param_bound_or_default` (GH-152684) (#152697) In `symtable_visit_type_param_bound_or_default()`, when a reserved name (e.g. `__classdict__`) is used as a type parameter, `PyUnicode_FromFormat()` is called to build the SyntaxError message. If the allocation fails and returns NULL, the subsequent `PyErr_SetObject()` and `Py_DECREF()` calls would dereference NULL, causing a segfault. Fix by returning 0 immediately when `PyUnicode_FromFormat()` returns NULL. This propagates the MemoryError set by `PyUnicode_FromFormat()`. The bug was introduced in gh-128632 (commit 891c61c). (cherry picked from commit 10ed03e) Co-authored-by: Petr Vaganov <[email protected]> * Remove test --------- Co-authored-by: Petr Vaganov <[email protected]> Co-authored-by: Stan Ulbrych <[email protected]>
…_param_bound_or_default` (GH-152684) (#152695) In `symtable_visit_type_param_bound_or_default()`, when a reserved name (e.g. `__classdict__`) is used as a type parameter, `PyUnicode_FromFormat()` is called to build the SyntaxError message. If the allocation fails and returns NULL, the subsequent `PyErr_SetObject()` and `Py_DECREF()` calls would dereference NULL, causing a segfault. Fix by returning 0 immediately when `PyUnicode_FromFormat()` returns NULL. This propagates the MemoryError set by `PyUnicode_FromFormat()`. The bug was introduced in gh-128632 (commit 891c61c). (cherry picked from commit 10ed03e) Co-authored-by: Petr Vaganov <[email protected]> * Remove test --------- Co-authored-by: Petr Vaganov <[email protected]> Co-authored-by: Stan Ulbrych <[email protected]>
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.