-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-89373: _Py_Dealloc() checks tp_dealloc exception #32357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
See https://bugs.python.org/issue45210#msg416849 for a manual test on this PR. |
@serhiy-storchaka @methane @pablogsal: is it this change acceptable for a debug build? The intent is to detect bugs in C extensions. It's similar to _Py_CheckFunctionResult() and _Py_CheckSlotResult(). For example, if a deallocator function clears the current exception, it can be very problematic for code like:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
old_exc_type
is a borrowed reference. If the exception type is deallocated, comparing a pointer is an UB.- What if the deallocator raised an exception with the same popular type?
- What if the exception was not normalized and the deallocator normalized it? Normalization of OSError changes the type.
Well, I made the assumption that a tp_dealloc function is not going to allocate new types which would get he same memory address. Are you suggesting to store a strong reference to the exception type? I tried to minimize _Py_Dealloc() overhead, since it's called often. I tried to avoid INCREF/DECREF on the type, but IMO the error message would be useless if we cannot dump the freed object and we cannot at least mention the type name.
If the old and new exception types are the same, the test doesn't notice that tp_dealloc raised a new exception. Do you mean that I should store the pointer to the exception instance ("exc value") and compare it to the new value as well?
The deallocator must not normalize the current exception: it must not change the current exception. IMO the test must fail in this case. Either it doesn't touch exceptions at all, or it must save and restore the current exception. See GH #28358 and https://bugs.python.org/issue45210. |
If tp_dealloc deallocates the old exception type, allocates a new new exception type which gets the same address and tp_dealloc raises a new exception (bug!) with the new type: my test fails to detect the bug. Well. It's unfortunate. But at least, the test cannot crash Python (fatal error) with a false positive: it cannot fail even if the code is correct. If you prefer, I can told strong references to the old exception type and to the old exception value. |
Practically, it perhaps does not cause problems on common platforms. Not sure about WebAssembly. And UB is UB -- the result is unpredictable, it can be not only crash. |
|
🤖 New build scheduled with the buildbot fleet by @gpshead for commit 3c57ddbd91ebdadc472749e97d9411269ac6d102 🤖 If you want to schedule another build, you need to add the ":hammer: test-with-buildbots" label again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm generally in favor of these kinds of checks in debug builds. They help ferret out issues in our code. If possible for this check, consider keying off of #ifndef NDEBUG
rather than #ifdef Py_DEBUG
. More builds use NDEBUG than full --with-pydebug
.
If Python is built in debug mode, _Py_Dealloc() now ensures that the tp_dealloc function leaves the current exception unchanged.
Updates:
I'm not comfortable with replacing Py_DEBUG with NDEBUG. I would prefer to have a guidelines saying what's acceptable or not acceptable for Py_DEBUG, NDEBUG and release builds. There is also the Python Development Mode which can be turned on "at runtime" (on the command line). My worry here is that the two Py_INCREF() might have subtle behavior changes. For me, NDEBUG is specific to assertions, but here is no call to Since Python 3.8, debug and release builds are ABI compatible. Where is the line between checking parameters at runtime and performance? Last time I proposed to drop these checks at runtime, the idea was rejected. The main reason is that popular CIs only provide release builds of Python, not debug builds. |
If Python is built in debug mode, _Py_Dealloc() now ensures that the
tp_dealloc function leaves the current exception unchanged.
https://bugs.python.org/issue45210