Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
Description
Bug report
I don't think it is very important, since this is just a test, but why have it when it is spotted?
test_k_code:cpython/Modules/_testcapi/getargs.c
Lines 331 to 398 in 326c6c4
/* This function not only tests the 'k' getargs code, but also the PyLong_AsUnsignedLongMask() function. */ staticPyObject* test_k_code(PyObject*self, PyObject*Py_UNUSED(ignored)) { PyObject*tuple, *num; unsigned longvalue; tuple=PyTuple_New(1); if (tuple==NULL){ returnNULL; } /* a number larger than ULONG_MAX even on 64-bit platforms */ num=PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16); if (num==NULL){ returnNULL; } value=PyLong_AsUnsignedLongMask(num); if (value!=ULONG_MAX){ PyErr_SetString(PyExc_AssertionError, "test_k_code: " "PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF"); returnNULL; } PyTuple_SET_ITEM(tuple, 0, num); value=0; if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)){ returnNULL; } if (value!=ULONG_MAX){ PyErr_SetString(PyExc_AssertionError, "test_k_code: k code returned wrong value for long 0xFFF...FFF"); returnNULL; } Py_DECREF(num); num=PyLong_FromString("-FFFFFFFF000000000000000042", NULL, 16); if (num==NULL){ returnNULL; } value=PyLong_AsUnsignedLongMask(num); if (value!= (unsigned long)-0x42){ PyErr_SetString(PyExc_AssertionError, "test_k_code: " "PyLong_AsUnsignedLongMask() returned wrong value for long -0xFFF..000042"); returnNULL; } PyTuple_SET_ITEM(tuple, 0, num); value=0; if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)){ returnNULL; } if (value!= (unsigned long)-0x42){ PyErr_SetString(PyExc_AssertionError, "test_k_code: k code returned wrong value for long -0xFFF..000042"); returnNULL; } Py_DECREF(tuple); Py_RETURN_NONE; }
On errors tuple is not decrefed.
Also, note these lines:
cpython/Modules/_testcapi/getargs.c
Lines 358 to 374 in 326c6c4
| PyTuple_SET_ITEM(tuple, 0, num); | |
| value=0; | |
| if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)){ | |
| returnNULL; | |
| } | |
| if (value!=ULONG_MAX){ | |
| PyErr_SetString(PyExc_AssertionError, | |
| "test_k_code: k code returned wrong value for long 0xFFF...FFF"); | |
| returnNULL; | |
| } | |
| Py_DECREF(num); | |
| num=PyLong_FromString("-FFFFFFFF000000000000000042", NULL, 16); | |
| if (num==NULL){ | |
| returnNULL; | |
| } |
Here' we leave a tuple is a semi-broken state. Its 0'th item has a reference count of 0.
We should also recreate a tuple here with the new items. test_L_code also has this problem.
cpython/Modules/_testcapi/getargs.c
Lines 684 to 732 in 326c6c4
staticPyObject* test_L_code(PyObject*self, PyObject*Py_UNUSED(ignored)) { PyObject*tuple, *num; long longvalue; tuple=PyTuple_New(1); if (tuple==NULL){ returnNULL; } num=PyLong_FromLong(42); if (num==NULL){ returnNULL; } PyTuple_SET_ITEM(tuple, 0, num); value=-1; if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)){ returnNULL; } if (value!=42){ PyErr_SetString(PyExc_AssertionError, "test_L_code: L code returned wrong value for long 42"); returnNULL; } Py_DECREF(num); num=PyLong_FromLong(42); if (num==NULL){ returnNULL; } PyTuple_SET_ITEM(tuple, 0, num); value=-1; if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)){ returnNULL; } if (value!=42){ PyErr_SetString(PyExc_AssertionError, "test_L_code: L code returned wrong value for int 42"); returnNULL; } Py_DECREF(tuple); Py_RETURN_NONE; }
On errors tuple is not decrefed. And num is re-assigned without tuple cleanup.
cpython/Modules/_testcapi/getargs.c
Lines 734 to 767 in 326c6c4
/* Test the s and z codes for PyArg_ParseTuple. */ staticPyObject* test_s_code(PyObject*self, PyObject*Py_UNUSED(ignored)) { /* Unicode strings should be accepted */ PyObject*tuple=PyTuple_New(1); if (tuple==NULL){ returnNULL; } PyObject*obj=PyUnicode_Decode("t\xeate", strlen("t\xeate"), "latin-1", NULL); if (obj==NULL){ returnNULL; } PyTuple_SET_ITEM(tuple, 0, obj); /* These two blocks used to raise a TypeError: * "argument must be string without null bytes, not str" */ char*value; if (!PyArg_ParseTuple(tuple, "s:test_s_code1", &value)){ returnNULL; } if (!PyArg_ParseTuple(tuple, "z:test_s_code2", &value)){ returnNULL; } Py_DECREF(tuple); Py_RETURN_NONE; }
As well, tuple is leaked on errors.
I have a PR ready.