Skip to content

Commit 552ceb2

Browse files
[3.12] gh-110572: Fix potential leaks in test_*_code in _testcapi/getargs.c (GH-110573) (GH-111161)
(cherry picked from commit f71cd53) Co-authored-by: Nikita Sobolev <[email protected]>
1 parent 0409057 commit 552ceb2

File tree

1 file changed

+57
-33
lines changed

1 file changed

+57
-33
lines changed

Modules/_testcapi/getargs.c

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -361,68 +361,83 @@ getargs_K(PyObject *self, PyObject *args)
361361
static PyObject *
362362
test_k_code(PyObject *self, PyObject *Py_UNUSED(ignored))
363363
{
364-
PyObject *tuple, *num;
365-
unsigned long value;
366-
367-
tuple = PyTuple_New(1);
364+
PyObject *tuple = PyTuple_New(1);
368365
if (tuple == NULL) {
369366
return NULL;
370367
}
371368

372369
/* a number larger than ULONG_MAX even on 64-bit platforms */
373-
num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
370+
PyObject *num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
374371
if (num == NULL) {
375-
return NULL;
372+
goto error;
376373
}
377374

378-
value = PyLong_AsUnsignedLongMask(num);
379-
if (value != ULONG_MAX) {
375+
unsigned long value = PyLong_AsUnsignedLongMask(num);
376+
if (value == (unsigned long)-1 && PyErr_Occurred()) {
377+
Py_DECREF(num);
378+
goto error;
379+
}
380+
else if (value != ULONG_MAX) {
381+
Py_DECREF(num);
380382
PyErr_SetString(PyExc_AssertionError,
381383
"test_k_code: "
382384
"PyLong_AsUnsignedLongMask() returned wrong value for long 0xFFF...FFF");
383-
return NULL;
385+
goto error;
384386
}
385387

386388
PyTuple_SET_ITEM(tuple, 0, num);
387389

388390
value = 0;
389391
if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) {
390-
return NULL;
392+
goto error;
391393
}
392394
if (value != ULONG_MAX) {
393395
PyErr_SetString(PyExc_AssertionError,
394396
"test_k_code: k code returned wrong value for long 0xFFF...FFF");
395-
return NULL;
397+
goto error;
396398
}
397399

398-
Py_DECREF(num);
400+
Py_DECREF(tuple); // also clears `num`
401+
tuple = PyTuple_New(1);
402+
if (tuple == NULL) {
403+
return NULL;
404+
}
399405
num = PyLong_FromString("-FFFFFFFF000000000000000042", NULL, 16);
400406
if (num == NULL) {
401-
return NULL;
407+
goto error;
402408
}
403409

404410
value = PyLong_AsUnsignedLongMask(num);
405-
if (value != (unsigned long)-0x42) {
411+
if (value == (unsigned long)-1 && PyErr_Occurred()) {
412+
Py_DECREF(num);
413+
goto error;
414+
}
415+
else if (value != (unsigned long)-0x42) {
416+
Py_DECREF(num);
406417
PyErr_SetString(PyExc_AssertionError,
407418
"test_k_code: "
408419
"PyLong_AsUnsignedLongMask() returned wrong value for long -0xFFF..000042");
409-
return NULL;
420+
goto error;
410421
}
411422

412423
PyTuple_SET_ITEM(tuple, 0, num);
413424

414425
value = 0;
415426
if (!PyArg_ParseTuple(tuple, "k:test_k_code", &value)) {
416-
return NULL;
427+
goto error;
417428
}
418429
if (value != (unsigned long)-0x42) {
419430
PyErr_SetString(PyExc_AssertionError,
420431
"test_k_code: k code returned wrong value for long -0xFFF..000042");
421-
return NULL;
432+
goto error;
422433
}
423434

424435
Py_DECREF(tuple);
425436
Py_RETURN_NONE;
437+
438+
error:
439+
Py_DECREF(tuple);
440+
return NULL;
426441
}
427442

428443
static PyObject *
@@ -760,51 +775,56 @@ getargs_et_hash(PyObject *self, PyObject *args)
760775
static PyObject *
761776
test_L_code(PyObject *self, PyObject *Py_UNUSED(ignored))
762777
{
763-
PyObject *tuple, *num;
764-
long long value;
765-
766-
tuple = PyTuple_New(1);
778+
PyObject *tuple = PyTuple_New(1);
767779
if (tuple == NULL) {
768780
return NULL;
769781
}
770782

771-
num = PyLong_FromLong(42);
783+
PyObject *num = PyLong_FromLong(42);
772784
if (num == NULL) {
773-
return NULL;
785+
goto error;
774786
}
775787

776788
PyTuple_SET_ITEM(tuple, 0, num);
777789

778-
value = -1;
790+
long long value = -1;
779791
if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) {
780-
return NULL;
792+
goto error;
781793
}
782794
if (value != 42) {
783795
PyErr_SetString(PyExc_AssertionError,
784796
"test_L_code: L code returned wrong value for long 42");
785-
return NULL;
797+
goto error;
786798
}
787799

788-
Py_DECREF(num);
800+
Py_DECREF(tuple); // also clears `num`
801+
tuple = PyTuple_New(1);
802+
if (tuple == NULL) {
803+
return NULL;
804+
}
789805
num = PyLong_FromLong(42);
790806
if (num == NULL) {
791-
return NULL;
807+
goto error;
792808
}
793809

794810
PyTuple_SET_ITEM(tuple, 0, num);
795811

796812
value = -1;
797813
if (!PyArg_ParseTuple(tuple, "L:test_L_code", &value)) {
798-
return NULL;
814+
goto error;
799815
}
800816
if (value != 42) {
801817
PyErr_SetString(PyExc_AssertionError,
802818
"test_L_code: L code returned wrong value for int 42");
803-
return NULL;
819+
goto error;
804820
}
805821

806822
Py_DECREF(tuple);
807823
Py_RETURN_NONE;
824+
825+
error:
826+
Py_DECREF(tuple);
827+
return NULL;
808828
}
809829

810830
/* Test the s and z codes for PyArg_ParseTuple.
@@ -821,7 +841,7 @@ test_s_code(PyObject *self, PyObject *Py_UNUSED(ignored))
821841
PyObject *obj = PyUnicode_Decode("t\xeate", strlen("t\xeate"),
822842
"latin-1", NULL);
823843
if (obj == NULL) {
824-
return NULL;
844+
goto error;
825845
}
826846

827847
PyTuple_SET_ITEM(tuple, 0, obj);
@@ -831,15 +851,19 @@ test_s_code(PyObject *self, PyObject *Py_UNUSED(ignored))
831851
*/
832852
char *value;
833853
if (!PyArg_ParseTuple(tuple, "s:test_s_code1", &value)) {
834-
return NULL;
854+
goto error;
835855
}
836856

837857
if (!PyArg_ParseTuple(tuple, "z:test_s_code2", &value)) {
838-
return NULL;
858+
goto error;
839859
}
840860

841861
Py_DECREF(tuple);
842862
Py_RETURN_NONE;
863+
864+
error:
865+
Py_DECREF(tuple);
866+
return NULL;
843867
}
844868

845869
#undef PyArg_ParseTupleAndKeywords

0 commit comments

Comments
 (0)