gh-98724: Fix Py_CLEAR() macro side effects (#99100) (#99288) · python/cpython@1082890 (original) (raw)
`@@ -5684,6 +5684,91 @@ test_set_type_size(PyObject *self, PyObject *Py_UNUSED(ignored))
`
5684
5684
`}
`
5685
5685
``
5686
5686
``
``
5687
`+
// Test Py_CLEAR() macro
`
``
5688
`+
static PyObject*
`
``
5689
`+
test_py_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
`
``
5690
`+
{
`
``
5691
`+
// simple case with a variable
`
``
5692
`+
PyObject *obj = PyList_New(0);
`
``
5693
`+
if (obj == NULL) {
`
``
5694
`+
return NULL;
`
``
5695
`+
}
`
``
5696
`+
Py_CLEAR(obj);
`
``
5697
`+
assert(obj == NULL);
`
``
5698
+
``
5699
`+
// gh-98724: complex case, Py_CLEAR() argument has a side effect
`
``
5700
`+
PyObject* array[1];
`
``
5701
`+
array[0] = PyList_New(0);
`
``
5702
`+
if (array[0] == NULL) {
`
``
5703
`+
return NULL;
`
``
5704
`+
}
`
``
5705
+
``
5706
`+
PyObject **p = array;
`
``
5707
`+
Py_CLEAR(*p++);
`
``
5708
`+
assert(array[0] == NULL);
`
``
5709
`+
assert(p == array + 1);
`
``
5710
+
``
5711
`+
Py_RETURN_NONE;
`
``
5712
`+
}
`
``
5713
+
``
5714
+
``
5715
`+
// Test Py_SETREF() and Py_XSETREF() macros, similar to test_py_clear()
`
``
5716
`+
static PyObject*
`
``
5717
`+
test_py_setref(PyObject *self, PyObject *Py_UNUSED(ignored))
`
``
5718
`+
{
`
``
5719
`+
// Py_SETREF() simple case with a variable
`
``
5720
`+
PyObject *obj = PyList_New(0);
`
``
5721
`+
if (obj == NULL) {
`
``
5722
`+
return NULL;
`
``
5723
`+
}
`
``
5724
`+
Py_SETREF(obj, NULL);
`
``
5725
`+
assert(obj == NULL);
`
``
5726
+
``
5727
`+
// Py_XSETREF() simple case with a variable
`
``
5728
`+
PyObject *obj2 = PyList_New(0);
`
``
5729
`+
if (obj2 == NULL) {
`
``
5730
`+
return NULL;
`
``
5731
`+
}
`
``
5732
`+
Py_XSETREF(obj2, NULL);
`
``
5733
`+
assert(obj2 == NULL);
`
``
5734
`+
// test Py_XSETREF() when the argument is NULL
`
``
5735
`+
Py_XSETREF(obj2, NULL);
`
``
5736
`+
assert(obj2 == NULL);
`
``
5737
+
``
5738
`+
// gh-98724: complex case, Py_SETREF() argument has a side effect
`
``
5739
`+
PyObject* array[1];
`
``
5740
`+
array[0] = PyList_New(0);
`
``
5741
`+
if (array[0] == NULL) {
`
``
5742
`+
return NULL;
`
``
5743
`+
}
`
``
5744
+
``
5745
`+
PyObject **p = array;
`
``
5746
`+
Py_SETREF(*p++, NULL);
`
``
5747
`+
assert(array[0] == NULL);
`
``
5748
`+
assert(p == array + 1);
`
``
5749
+
``
5750
`+
// gh-98724: complex case, Py_XSETREF() argument has a side effect
`
``
5751
`+
PyObject* array2[1];
`
``
5752
`+
array2[0] = PyList_New(0);
`
``
5753
`+
if (array2[0] == NULL) {
`
``
5754
`+
return NULL;
`
``
5755
`+
}
`
``
5756
+
``
5757
`+
PyObject **p2 = array2;
`
``
5758
`+
Py_XSETREF(*p2++, NULL);
`
``
5759
`+
assert(array2[0] == NULL);
`
``
5760
`+
assert(p2 == array2 + 1);
`
``
5761
+
``
5762
`+
// test Py_XSETREF() when the argument is NULL
`
``
5763
`+
p2 = array2;
`
``
5764
`+
Py_XSETREF(*p2++, NULL);
`
``
5765
`+
assert(array2[0] == NULL);
`
``
5766
`+
assert(p2 == array2 + 1);
`
``
5767
+
``
5768
`+
Py_RETURN_NONE;
`
``
5769
`+
}
`
``
5770
+
``
5771
+
5687
5772
`#define TEST_REFCOUNT() \
`
5688
5773
` do { \
`
5689
5774
` PyObject *obj = PyList_New(0); \
`
`@@ -6475,6 +6560,8 @@ static PyMethodDef TestMethods[] = {
`
6475
6560
` {"pynumber_tobase", pynumber_tobase, METH_VARARGS},
`
6476
6561
` {"without_gc", without_gc, METH_O},
`
6477
6562
` {"test_set_type_size", test_set_type_size, METH_NOARGS},
`
``
6563
`+
{"test_py_clear", test_py_clear, METH_NOARGS},
`
``
6564
`+
{"test_py_setref", test_py_setref, METH_NOARGS},
`
6478
6565
` {"test_refcount_macros", test_refcount_macros, METH_NOARGS},
`
6479
6566
` {"test_refcount_funcs", test_refcount_funcs, METH_NOARGS},
`
6480
6567
` {"test_py_is_macros", test_py_is_macros, METH_NOARGS},
`