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},

`