Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dbf3d61
fix overflow in frame's stacksizes
picnixz Oct 29, 2024
a566469
blurb
picnixz Oct 29, 2024
222de28
blurb v2
picnixz Oct 29, 2024
303109b
fix more cases
picnixz Oct 29, 2024
d743a3d
improve test coverage!
picnixz Oct 29, 2024
6b34c22
improve test coverage!
picnixz Oct 29, 2024
044d1a5
fix logic
picnixz Oct 31, 2024
d6f3bc4
remove un-necessary assertion
picnixz Oct 31, 2024
31f36de
skip a test on free-threaded builds to avoid crash
picnixz Oct 31, 2024
b26dd72
fix tests on 32-bit platforms
picnixz Oct 31, 2024
fe0b04e
fix casts
picnixz Oct 31, 2024
1fe8e28
fix boundary conditions
picnixz Oct 31, 2024
40d8b91
Merge remote-tracking branch 'upstream/main' into fix/overflow-in-fra…
picnixz Oct 31, 2024
8c7ce9c
Update Lib/test/test_frame.py
picnixz Nov 7, 2024
f8a0eef
Update Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-11-47-19.gh-issu…
picnixz Nov 7, 2024
3130f94
change co_stacksize upper limit
picnixz Nov 8, 2024
91f95de
remove test that cannot overflow now
picnixz Nov 8, 2024
c5d7596
fix tests
picnixz Nov 8, 2024
a0b85d4
remove unused imports
picnixz Nov 8, 2024
04abc46
update comment
picnixz Nov 9, 2024
0187b72
remove assertions from `gen_sizeof` and `frame_sizeof`
picnixz Nov 9, 2024
c9969a4
update test
picnixz Nov 9, 2024
6c0e1a6
update test
picnixz Nov 9, 2024
a498df9
Merge branch 'main' into fix/overflow-in-frame-sizeof-126119
picnixz Feb 23, 2025
6284de6
Merge branch 'main' into fix/overflow-in-frame-sizeof-126119
picnixz May 11, 2025
fdb2e89
address review
picnixz May 15, 2025
990a69c
Merge remote-tracking branch 'upstream/main' into fix/code/overflow-1…
picnixz Jun 2, 2025
d027b6a
Merge branch 'main' into fix/overflow-in-frame-sizeof-126119
picnixz Sep 9, 2025
6e52b03
Merge branch 'main' into fix/overflow-in-frame-sizeof-126119
picnixz Oct 10, 2025
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
12 changes: 12 additions & 0 deletions Lib/test/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,18 @@ def test_code_equal_with_instrumentation(self):
self.assertNotEqual(code1, code2)
sys.settrace(None)

def test_co_stacksize_overflow(self):
# See: https://github.com/python/cpython/issues/126119.

# Since co_framesize = nlocalsplus + co_stacksize + FRAME_SPECIALS_SIZE,
# we need to check that co_stacksize is not too large. We could fortify
# the test by explicitly checking that bound, but this needs to expose
# FRAME_SPECIALS_SIZE and a getter for 'nlocalsplus'.

c = (lambda: ...).__code__
with self.assertRaisesRegex(OverflowError, "co_stacksize"):
c.__replace__(co_stacksize=2147483647)


def isinterned(s):
return s is sys.intern(('_' + s + '_')[1:-1])
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix a crash in DEBUG builds due to an overflow when the :attr:`co_stacksize
<codeobject.co_stacksize>` field of a :ref:`code object <code-objects>` is
set to an absurdely large integer.
Reported by Valery Fedorenko. Patch by Bénédikt Tran.
7 changes: 6 additions & 1 deletion Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,12 @@ _PyCode_Validate(struct _PyCodeConstructor *con)
PyErr_SetString(PyExc_ValueError, "code: co_varnames is too small");
return -1;
}

/* Ensure that the framesize will not overflow */
int nlocalsplus = (int)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
19 changes: 15 additions & 4 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1804,11 +1804,22 @@ PyDoc_STRVAR(clear__doc__,
static PyObject *
frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
{
Py_ssize_t res;
res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus);
Py_ssize_t res = offsetof(PyFrameObject, _f_frame_data)
+ offsetof(_PyInterpreterFrame, localsplus);
PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
return PyLong_FromSsize_t(res);
int nslots = _PyFrame_NumSlotsForCodeObject(code);
assert(nslots >= 0);
if ((size_t)nslots >= (PY_SSIZE_T_MAX - res) / sizeof(PyObject *)) {
// This could happen if the underlying code object has a
// very large stacksize (but at most INT_MAX) yet that the
// above offsets make the result overflow.
//
// This should normally only happen if PY_SSIZE_T_MAX == INT_MAX,
// but we anyway raise an exception on other systems for safety.
PyErr_SetString(PyExc_OverflowError, "size exceeds PY_SSIZE_T_MAX");
return NULL;
}
return PyLong_FromSsize_t(res + nslots * sizeof(PyObject *));
}

PyDoc_STRVAR(sizeof__doc__,
Expand Down
Loading