Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Lib/test/test_marshal.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,17 @@ def test_same_filename_used(self):
if isinstance(obj, types.CodeType):
self.assertIs(co.co_filename, obj.co_filename)

def test_huge_stacksize(self):
# gh-158648: a code object's stacksize shouldnt overflow
# co_framesize (nlocalsplus + stacksize + FRAME_SPECIALS_SIZE)
# is stored and used as a C int throughout the interpreter.
# marshal data is explicitly documented as unsafe for untrusted
# input, but unmarshalling a maliciously crafted stacksize must
# still fail cleanly
co = ExceptionTestCase.test_exceptions.__code__
with self.assertRaises(OverflowError):
co.replace(co_stacksize=2**31 - 1)

class ContainerTestCase(unittest.TestCase, HelperMixin):
d = {'astring': 'foo@bar.baz.spam',
'afloat': 7283.43,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fix an integer overflow in code object construction
(:mod:`marshal`, :func:`types.CodeType`, and :meth:`CodeType.replace`)
where excessively large ``co_stacksize`` could overflow
``co_framesize`` and corrupt the interpreter's stack.
``stacksize`` is now rejected with :exc:`OverflowError`.
8 changes: 8 additions & 0 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,14 @@ _PyCode_Validate(struct _PyCodeConstructor *con)
return -1;
}

/* co_framesize (nlocalsplus + stacksize + FRAME_SPECIALS_SIZE) is stored and used
as C int throughout the interpreter. untrusted stacksize shouldnt overflow. */
Py_ssize_t nlocalsplus = PyTuple_GET_SIZE(con->localsplusnames);
if (con->stacksize > INT_MAX - nlocalsplus - FRAME_SPECIALS_SIZE) {
PyErr_SetString(PyExc_OverflowError, "code: co_stacksize is too large");
return -1;
}

return 0;
}

Expand Down
Loading