https://github.com/python/cpython/commit/a4ab2c1c6907f404a7463efac2bea8b8a4639c42
commit: a4ab2c1c6907f404a7463efac2bea8b8a4639c42
branch: 3.13
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-08T15:17:38Z
summary:

[3.13] gh-121617: Fix Py_CLEAR() in C++: replace NULL with _Py_NULL (#157067) 
(#157189)

gh-121617: Fix Py_CLEAR() in C++: replace NULL with _Py_NULL (#157067)

* Enhance Py_CLEAR() test in test_cext and test_cppext.
  Check that Py_CLEAR(obj) sets obj to NULL.
* Add also tests on Py_SETREF() and Py_BEGIN_CRITICAL_SECTION().

(cherry picked from commit 36c7440c480da622735788af656c728af28cd9eb)

files:
M Include/object.h
M Lib/test/test_cext/extension.c
M Lib/test/test_cppext/extension.cpp

diff --git a/Include/object.h b/Include/object.h
index e59f78789844e7c..d59644032a1b709 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -1006,7 +1006,7 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject 
*op)
     do { \
         _Py_TYPEOF(op)* _tmp_op_ptr = &(op); \
         _Py_TYPEOF(op) _tmp_old_op = (*_tmp_op_ptr); \
-        if (_tmp_old_op != NULL) { \
+        if (_tmp_old_op != _Py_NULL) { \
             *_tmp_op_ptr = _Py_NULL; \
             Py_DECREF(_tmp_old_op); \
         } \
@@ -1016,7 +1016,7 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject 
*op)
     do { \
         PyObject **_tmp_op_ptr = _Py_CAST(PyObject**, &(op)); \
         PyObject *_tmp_old_op = (*_tmp_op_ptr); \
-        if (_tmp_old_op != NULL) { \
+        if (_tmp_old_op != _Py_NULL) { \
             PyObject *_null_ptr = _Py_NULL; \
             memcpy(_tmp_op_ptr, &_null_ptr, sizeof(PyObject*)); \
             Py_DECREF(_tmp_old_op); \
diff --git a/Lib/test/test_cext/extension.c b/Lib/test/test_cext/extension.c
index b76abe1d74c6285..5aab01890b07596 100644
--- a/Lib/test/test_cext/extension.c
+++ b/Lib/test/test_cext/extension.c
@@ -45,6 +45,8 @@ _testcext_exec(
 #endif
     )
 {
+    PyObject *obj;
+
 #ifdef __STDC_VERSION__
     if (PyModule_AddIntMacro(module, __STDC_VERSION__) < 0) {
         return -1;
@@ -55,6 +57,22 @@ _testcext_exec(
     Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
     assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0);
 
+    // Test Py_CLEAR(): use typeof()/__typeof__() if available, or memcpy()
+    obj = Py_None;
+    Py_CLEAR(obj);
+    assert(obj == NULL);
+
+#ifndef Py_LIMITED_API
+    // Test Py_SETREF(): use typeof()/__typeof__() if available, or memcpy()
+    obj = Py_None;
+    Py_SETREF(obj, NULL);
+    assert(obj == NULL);
+
+    // Test that Py_BEGIN_CRITICAL_SECTION is available
+    Py_BEGIN_CRITICAL_SECTION(module);
+    Py_END_CRITICAL_SECTION();
+#endif
+
     return 0;
 }
 
diff --git a/Lib/test/test_cppext/extension.cpp 
b/Lib/test/test_cppext/extension.cpp
index 500d5918145c00a..bc32c5dc822c0e4 100644
--- a/Lib/test/test_cppext/extension.cpp
+++ b/Lib/test/test_cppext/extension.cpp
@@ -238,6 +238,22 @@ _testcppext_exec(PyObject *module)
     Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
     assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0);
 
+    // Test Py_CLEAR(): use typeof()/__typeof__() if available, or memcpy()
+    PyObject *obj = Py_None;
+    Py_CLEAR(obj);
+    assert(obj == _Py_NULL);
+
+#ifndef Py_LIMITED_API
+    // Test Py_SETREF(): use typeof()/__typeof__() if available, or memcpy()
+    obj = Py_None;
+    Py_SETREF(obj, _Py_NULL);
+    assert(obj == _Py_NULL);
+
+    // Test that Py_BEGIN_CRITICAL_SECTION is available
+    Py_BEGIN_CRITICAL_SECTION(module);
+    Py_END_CRITICAL_SECTION();
+#endif
+
     return 0;
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to