summaryrefslogtreecommitdiffstats
path: root/Doc/c-api
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-12-07 14:22:38 (GMT)
committerGitHub <noreply@github.com>2022-12-07 14:22:38 (GMT)
commitb11a384dc7471ffc16de4b86e8f5fdeef151f348 (patch)
treec2fc15ebb4de11991f9f1799fa2588a484003073 /Doc/c-api
parent7031275776f43c76231318c2158a7a2753bc1fba (diff)
downloadcpython-b11a384dc7471ffc16de4b86e8f5fdeef151f348.zip
cpython-b11a384dc7471ffc16de4b86e8f5fdeef151f348.tar.gz
cpython-b11a384dc7471ffc16de4b86e8f5fdeef151f348.tar.bz2
gh-98724: Fix Py_CLEAR() macro side effects (#99100) (#100070)
The Py_CLEAR(), Py_SETREF() and Py_XSETREF() macros now only evaluate their arguments once. If an argument has side effects, these side effects are no longer duplicated. Use temporary variables to avoid duplicating side effects of macro arguments. If available, use _Py_TYPEOF() to avoid type punning. Otherwise, use memcpy() for the assignment to prevent a miscompilation with strict aliasing caused by type punning. Add _Py_TYPEOF() macro: __typeof__() on GCC and clang. Add test_py_clear() and test_py_setref() unit tests to _testcapi.
Diffstat (limited to 'Doc/c-api')
-rw-r--r--Doc/c-api/refcounting.rst46
1 files changed, 44 insertions, 2 deletions
diff --git a/Doc/c-api/refcounting.rst b/Doc/c-api/refcounting.rst
index cd1f2ef..d8e9c2d 100644
--- a/Doc/c-api/refcounting.rst
+++ b/Doc/c-api/refcounting.rst
@@ -7,8 +7,8 @@
Reference Counting
******************
-The macros in this section are used for managing reference counts of Python
-objects.
+The functions and macros in this section are used for managing reference counts
+of Python objects.
.. c:function:: Py_ssize_t Py_REFCNT(PyObject *o)
@@ -129,6 +129,11 @@ objects.
It is a good idea to use this macro whenever decrementing the reference
count of an object that might be traversed during garbage collection.
+ .. versionchanged:: 3.12
+ The macro argument is now only evaluated once. If the argument has side
+ effects, these are no longer duplicated.
+
+
.. c:function:: void Py_IncRef(PyObject *o)
Increment the reference count for object *o*. A function version of :c:func:`Py_XINCREF`.
@@ -139,3 +144,40 @@ objects.
Decrement the reference count for object *o*. A function version of :c:func:`Py_XDECREF`.
It can be used for runtime dynamic embedding of Python.
+
+
+.. c:macro:: Py_SETREF(dst, src)
+
+ Macro safely decrementing the `dst` reference count and setting `dst` to
+ `src`.
+
+ As in case of :c:func:`Py_CLEAR`, "the obvious" code can be deadly::
+
+ Py_DECREF(dst);
+ dst = src;
+
+ The safe way is::
+
+ Py_SETREF(dst, src);
+
+ That arranges to set `dst` to `src` _before_ decrementing reference count of
+ *dst* old value, so that any code triggered as a side-effect of `dst`
+ getting torn down no longer believes `dst` points to a valid object.
+
+ .. versionadded:: 3.6
+
+ .. versionchanged:: 3.12
+ The macro arguments are now only evaluated once. If an argument has side
+ effects, these are no longer duplicated.
+
+
+.. c:macro:: Py_XSETREF(dst, src)
+
+ Variant of :c:macro:`Py_SETREF` macro that uses :c:func:`Py_XDECREF` instead
+ of :c:func:`Py_DECREF`.
+
+ .. versionadded:: 3.6
+
+ .. versionchanged:: 3.12
+ The macro arguments are now only evaluated once. If an argument has side
+ effects, these are no longer duplicated.