Skip to content

Commit f97464b

Browse files
[3.15] gh-159739: Fix crash in _PyTuple_Resize() with an invalid size (GH-159804) (#159976)
gh-159739: Fix crash in _PyTuple_Resize() with an invalid size (GH-159804) _PyTuple_Resize() did not validate newsize for non-empty tuples. Raise SystemError for a negative size and MemoryError for a too-large size, like PyTuple_New() already does for the empty-tuple path. (cherry picked from commit c360884) Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
1 parent 815057b commit f97464b

3 files changed

Lines changed: 16 additions & 1 deletion

File tree

‎Lib/test/test_capi/test_tuple.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,10 @@ def test__tuple_resize(self):
327327
self.assertRaises(MemoryError, resize, a, PY_SSIZE_T_MAX)
328328
self.assertRaises(SystemError, resize, a, -1)
329329
self.assertRaises(SystemError, resize, a, PY_SSIZE_T_MIN)
330+
a = ([1], [2], [3])
331+
self.assertRaises(MemoryError, resize, a, PY_SSIZE_T_MAX)
332+
self.assertRaises(SystemError, resize, a, -1)
333+
self.assertRaises(SystemError, resize, a, PY_SSIZE_T_MIN)
330334
# refcount > 1
331335
a = (1, 2, 3)
332336
self.assertRaises(SystemError, resize, a, 3, False)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a crash in :c:func:`_PyTuple_Resize` when resizing a non-empty tuple to a
2+
negative or too large size. It now raises :exc:`SystemError` or
3+
:exc:`MemoryError` respectively.

‎Objects/tupleobject.c‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
10411041
Py_ssize_t oldsize;
10421042

10431043
v = (PyTupleObject *) *pv;
1044-
if (v == NULL || !Py_IS_TYPE(v, &PyTuple_Type) ||
1044+
if (v == NULL || !Py_IS_TYPE(v, &PyTuple_Type) || newsize < 0 ||
10451045
(Py_SIZE(v) != 0 && !_PyObject_IsUniquelyReferenced(*pv))) {
10461046
*pv = 0;
10471047
Py_XDECREF(v);
@@ -1068,6 +1068,14 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
10681068
*pv = PyTuple_New(newsize);
10691069
return *pv == NULL ? -1 : 0;
10701070
}
1071+
/* Check for overflow */
1072+
if ((size_t)newsize > ((size_t)PY_SSIZE_T_MAX - (sizeof(PyTupleObject) -
1073+
sizeof(PyObject *))) / sizeof(PyObject *)) {
1074+
*pv = NULL;
1075+
Py_DECREF(v);
1076+
PyErr_NoMemory();
1077+
return -1;
1078+
}
10711079

10721080
if (_PyObject_GC_IS_TRACKED(v)) {
10731081
_PyObject_GC_UNTRACK(v);

0 commit comments

Comments
 (0)