Skip to content

Commit e72f469

Browse files
markshannonmdboom
andauthored
[3.11] GH-96569: Avoid undefined behavior (#96616)
Co-authored-by: Michael Droettboom <[email protected]>
1 parent 3d6e6be commit e72f469

File tree

3 files changed

+25
-16
lines changed

3 files changed

+25
-16
lines changed

Include/internal/pycore_frame.h

+16-8
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,25 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear);
192192
extern _PyInterpreterFrame *
193193
_PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size);
194194

195+
static inline bool
196+
_PyThreadState_HasStackSpace(PyThreadState *tstate, size_t size)
197+
{
198+
assert(
199+
(tstate->datastack_top == NULL && tstate->datastack_limit == NULL)
200+
||
201+
(tstate->datastack_top != NULL && tstate->datastack_limit != NULL)
202+
);
203+
return tstate->datastack_top != NULL &&
204+
size < (size_t)(tstate->datastack_limit - tstate->datastack_top);
205+
}
206+
195207
static inline _PyInterpreterFrame *
196208
_PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size)
197209
{
198-
PyObject **base = tstate->datastack_top;
199-
if (base) {
200-
PyObject **top = base + size;
201-
assert(tstate->datastack_limit);
202-
if (top < tstate->datastack_limit) {
203-
tstate->datastack_top = top;
204-
return (_PyInterpreterFrame *)base;
205-
}
210+
if (_PyThreadState_HasStackSpace(tstate, size)) {
211+
_PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top;
212+
tstate->datastack_top += size;
213+
return res;
206214
}
207215
return _PyThreadState_BumpFramePointerSlow(tstate, size);
208216
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Remove two cases of undefined behavior, by adding NULL checks.

Python/pystate.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -2178,16 +2178,16 @@ push_chunk(PyThreadState *tstate, int size)
21782178
_PyInterpreterFrame *
21792179
_PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size)
21802180
{
2181-
assert(size < INT_MAX/sizeof(PyObject *));
2182-
PyObject **base = tstate->datastack_top;
2183-
PyObject **top = base + size;
2184-
if (top >= tstate->datastack_limit) {
2185-
base = push_chunk(tstate, (int)size);
2181+
if (_PyThreadState_HasStackSpace(tstate, size)) {
2182+
_PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top;
2183+
tstate->datastack_top += size;
2184+
return res;
21862185
}
2187-
else {
2188-
tstate->datastack_top = top;
2186+
if (size > INT_MAX/2) {
2187+
PyErr_NoMemory();
2188+
return NULL;
21892189
}
2190-
return (_PyInterpreterFrame *)base;
2190+
return (_PyInterpreterFrame *)push_chunk(tstate, (int)size);
21912191
}
21922192

21932193
void

0 commit comments

Comments
 (0)