https://github.com/python/cpython/commit/89926c6364ab23dde6560f20175fc607f982fb6c
commit: 89926c6364ab23dde6560f20175fc607f982fb6c
branch: 3.14
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-08T15:14:23Z
summary:
[3.14] gh-121617: Fix Py_CLEAR() in C++: replace NULL with _Py_NULL (#157067)
(#157187)
* 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)
* Use also _Py_NULL in memcpy() implementation of Py_CLEAR()
files:
M Include/refcount.h
M Lib/test/test_cext/extension.c
M Lib/test/test_cppext/extension.cpp
diff --git a/Include/refcount.h b/Include/refcount.h
index 1ef6b2186bba039..03da93b53c2438c 100644
--- a/Include/refcount.h
+++ b/Include/refcount.h
@@ -478,7 +478,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); \
} \
@@ -488,7 +488,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 56f40b354c69135..e6dd47edd20bbe0 100644
--- a/Lib/test/test_cext/extension.c
+++ b/Lib/test/test_cext/extension.c
@@ -79,7 +79,7 @@ static PyMethodDef _testcext_methods[] = {
static int
_testcext_exec(PyObject *module)
{
- PyObject *result;
+ PyObject *result, *obj;
#ifdef __STDC_VERSION__
if (PyModule_AddIntMacro(module, __STDC_VERSION__) < 0) {
@@ -95,6 +95,22 @@ _testcext_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()
+ 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 4db63df94f52334..19984a3908ce6dd 100644
--- a/Lib/test/test_cppext/extension.cpp
+++ b/Lib/test/test_cppext/extension.cpp
@@ -294,6 +294,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]