[3.11] GH-96569: Avoid undefined behavior (#96616)

Co-authored-by: Michael Droettboom <mdboom@gmail.com>
This commit is contained in:
Mark Shannon 2022-09-08 12:00:04 +01:00 committed by GitHub
parent 3d6e6beb0d
commit e72f469e85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 16 deletions

View file

@ -192,17 +192,25 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear);
extern _PyInterpreterFrame * extern _PyInterpreterFrame *
_PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size); _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size);
static inline bool
_PyThreadState_HasStackSpace(PyThreadState *tstate, size_t size)
{
assert(
(tstate->datastack_top == NULL && tstate->datastack_limit == NULL)
||
(tstate->datastack_top != NULL && tstate->datastack_limit != NULL)
);
return tstate->datastack_top != NULL &&
size < (size_t)(tstate->datastack_limit - tstate->datastack_top);
}
static inline _PyInterpreterFrame * static inline _PyInterpreterFrame *
_PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size) _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size)
{ {
PyObject **base = tstate->datastack_top; if (_PyThreadState_HasStackSpace(tstate, size)) {
if (base) { _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top;
PyObject **top = base + size; tstate->datastack_top += size;
assert(tstate->datastack_limit); return res;
if (top < tstate->datastack_limit) {
tstate->datastack_top = top;
return (_PyInterpreterFrame *)base;
}
} }
return _PyThreadState_BumpFramePointerSlow(tstate, size); return _PyThreadState_BumpFramePointerSlow(tstate, size);
} }

View file

@ -0,0 +1 @@
Remove two cases of undefined behavior, by adding NULL checks.

View file

@ -2178,16 +2178,16 @@ push_chunk(PyThreadState *tstate, int size)
_PyInterpreterFrame * _PyInterpreterFrame *
_PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size) _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size)
{ {
assert(size < INT_MAX/sizeof(PyObject *)); if (_PyThreadState_HasStackSpace(tstate, size)) {
PyObject **base = tstate->datastack_top; _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top;
PyObject **top = base + size; tstate->datastack_top += size;
if (top >= tstate->datastack_limit) { return res;
base = push_chunk(tstate, (int)size);
} }
else { if (size > INT_MAX/2) {
tstate->datastack_top = top; PyErr_NoMemory();
return NULL;
} }
return (_PyInterpreterFrame *)base; return (_PyInterpreterFrame *)push_chunk(tstate, (int)size);
} }
void void