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
gh-98724: Fix Py_CLEAR() macro side effects #99100
Conversation
223d605
to
fb9aafa
Compare
|
I looked at the x86-64 machine code of test_py_clear() built by gcc -O3. I don't see any |
|
I completed test_py_clear() to test calling Py_CLEAR() with a side effect: test based on #98724 (comment) idea. |
|
I have some suggestion for the test: It should crash with the old |
It does crash with the old Py_CLEAR() macro: |
|
cc @serhiy-storchaka: there is now a unit test which shows that the old macro had a bug. |
|
Py_SETREF? |
I don't understand your comment. This PR fix a bug in Py_CLEAR(). Can you please elaborate? |
|
Py_SETREF and Py_XSETREF are similar to Py_CLEAR. If change the latter, why not change the formers? |
|
I think all macros should be changed so they only reference their arguments once. This avoids the whole issue with side effects applied multiple times. |
That's one of the purpose of PEP 670. It's just that @erlend-aasland and me missed these macros (Py_CLEAR, Py_SETREF, Py_XSETREF). |
You're right. I completed my PR to fix also Py_SETREF() and Py_XSETREF() macros. Py_SETREF() and Py_XSETREF() macros require an additional I added unit tests. |
|
I would document it as a change in 3.12. And older versions need documenting that the first argument can be evaluated more than once. |
Ok, I documented the Py_CLEAR() change with a "versionchanged". But Py_SETREF() and Py_XSETREF() are not documented. Maybe it's no purpose, so I didn't modify their (non existing) documentation. |
|
I would consider adding a What's New item. |
d004dfe
to
260083b
Compare
Ok, I added a What's New in Python 3.12 entry. I copied the same text everywhere. Would you mind to review the update documentation text? |
The Py_CLEAR(), Py_SETREF() and Py_XSETREF() macros now only evaluate their argument once. If the argument has side effects, these side effects are no longer duplicated. Add test_py_clear() and test_py_setref() unit tests to _testcapi.
|
Doc/c-api/refcounting.rst contains two times an error: If the argument has side effects, there are no longer duplicated. Further down it is correct with these are no longer duplicated. |
Ah, I hesitated between both :-) I changed for "these are". |
Unfortunately, anything that's included by Python.h is de facto part of the public C API, documented or not. |
|
GH-99288 is a backport of this pull request to the 3.11 branch. |
|
I created a 3.11 backport without documentation changes: #99288 |
The Py_CLEAR(), Py_SETREF() and Py_XSETREF() macros now only evaluate their argument once. If an argument has side effects, these side effects are no longer duplicated. Add test_py_clear() and test_py_setref() unit tests to _testcapi. (cherry picked from commit c03e05c)
But that will invalidate the |
The Py_CLEAR(), Py_SETREF() and Py_XSETREF() macros now only evaluate their argument once. If an argument has side effects, these side effects are no longer duplicated. Add test_py_clear() and test_py_setref() unit tests to _testcapi. (cherry picked from commit c03e05c)
…ythonGH-99288) The Py_CLEAR(), Py_SETREF() and Py_XSETREF() macros now only evaluate their argument once. If an argument has side effects, these side effects are no longer duplicated. Add test_py_clear() and test_py_setref() unit tests to _testcapi. (cherry picked from commit 1082890) Co-authored-by: Victor Stinner <vstinner@python.org> (cherry picked from commit c03e05c)
I fixed the bug silently, but I cannot document that it's the default behavior in Python 3.11.0 since the fix will only be done in later 3.11.x bugfix versions. |
|
Hum. I read again the discussion and now I'm confused. @serhiy-storchaka @erlend-aasland: Should I backport the fix to 3.10 and 3.11 or not? I just backported the change to 3.11 as: 1082890 I created backport to 3.10 but then I closed it before it got merged: #99292 My idea is to fix the bug in Python 3.10 and 3.11 with a changelog entry, but don't document the behavior in the C API documentation with versionchanged. Is it a bad thing to fix this bug in 3.10 and 3.11? People who need to use Py_CLEAR(), Py_SETREF() or Py_XSETREF() with side effects on old Python versions can redefine the macros with a flavor which has the bugfix, no? |
|
I created python/pythoncapi-compat#50 to fix the two macros in the pythoncapi-compat project. |
|
I proposed to add them to the stable API. But there were objections. https://mail.python.org/archives/list/python-dev@python.org/thread/HGBT2Y4VAZOOU5XI2RPSURDGFBMRJKPO/ If you want to reconsider this, please open a new discussion. |
|
By the way, Python 3.12 contains an important change related to memory allocation of objects tracked by the GC:
See #97922 for details. The change was done in _PyObject_GC_New() and _PyObject_GC_NewVar(), not on Py_DECREF(). See also issue #89060 and @nascheme's PR #27738 "WIP: Integrate trashcan into _Py_Dealloc". But again, this WIP change is only for objects tracked by the GC. |
|
See also issue #99300: "Replace Py_INCREF()/Py_XINCREF() usage with Py_NewRef()/Py_XNewRef()", but it's not directly related :-) |
Is adding Py_SETREF() to the limited C API (stable ABI) related to deciding if the Py_CLEAR() and Py_SETREF() bugfix should be backported to Python 3.11? I'm not sure that I get it. Functions excluded from the limited C API are also documented. Well, I'm open to add Py_SETREF() to the limited C API, but I suggest to discuss it separately. |
|
I am in favor of adding these functions to the limited C API, but since this idea was rejected once, you cannot do this without a broader discussion. How do you document that they are not a part of the limited C API? |
|
Adding these functions to the Limited API should be discussed in a separate issue. It is out of scope for gh-98724, and this PR is definitely not the correct place to discuss it. Regarding the backports, which should be discussed here (or on the linked issue): if we are not to update the docs in the backports, I don't think the backports should be made. It is unfortunate if the docs are inaccurate because of the backports. |
What if I put a "versionchanged" with Python 3.11.x and Python 3.10.x bugfix versions, rather than "3.11" and "3.10"? |
I'm not sure how to handle that correctly in Sphinx. In order to be accurate, the |
|
I just feel uncomfortable that these macros were documented without discussion. What is they official status? |
I don't understand your point about the fact that functions which are excluded from the limited C API should not be documented. Most of the C API is excluded from the limited C API and it is documented. For example, https://docs.python.org/dev/c-api/frame.html documents many PyFrame functions, PyFrame_GetBack() is documented and excluded from the limited C API. Only some functions have the "Part of the Stable ABI" label (see this Frame C API doc). By the way, many C API macros are documented.
Py_CLEAR(), Py_SETREF(), Py_XSETREF() are part of the public C API, are tested and documented in Python 3.12. How is it an issue? Sorry, I still don't get your point. |
That's problematic in practice if 3.10 or 3.11 get a special release just for a single security fix, not based on the current 3.10 and 3.11 branch. Well, I don't recall that it ever happened. But I would prefer to not attempt to which today what will be the 3.x.y release in 3.10, 3.11 and main branches which will include the change. I prefer to only put 3.10.x in 3.10 doc, 3.11.x in the 3.11 doc, and 3.12 in the main branch. We did that multiple times in the past for security fixes. See also:
I'm not suggesting to document Py_SETREF() change as a "notable change". I would prefer to not even document it in 3.10 and 3.11 branches. I don't get why you guys consider that Py_SETREF() is special enough to require that the bugfix is documented. But I'm fine with document it if you prefer. |
The Py_CLEAR(), Py_SETREF() and Py_XSETREF() macros now only evaluate
their argument once. If the argument has side effects, these side
effects are no longer duplicated.
Add test_py_clear() and test_py_setref() unit tests to _testcapi.