mirror of https://github.com/python/cpython
GH-96975: Skip incomplete frames in PyEval_GetFrame (GH-97003)
This commit is contained in:
parent
ec403536f1
commit
8fd2c3b75b
|
@ -1713,6 +1713,9 @@ class AuditingTests(EmbeddingTestsMixin, unittest.TestCase):
|
|||
timeout=support.SHORT_TIMEOUT,
|
||||
returncode=1)
|
||||
|
||||
def test_get_incomplete_frame(self):
|
||||
self.run_embedded_interpreter("test_get_incomplete_frame")
|
||||
|
||||
|
||||
class MiscTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||
def test_unicode_id_init(self):
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix a crash occurring when :c:func:`PyEval_GetFrame` is called while the
|
||||
topmost Python frame is in a partially-initialized state.
|
|
@ -1950,6 +1950,73 @@ static int test_repeated_init_and_inittab(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wrap_allocator(PyMemAllocatorEx *allocator);
|
||||
static void unwrap_allocator(PyMemAllocatorEx *allocator);
|
||||
|
||||
static void *
|
||||
malloc_wrapper(void *ctx, size_t size)
|
||||
{
|
||||
PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
|
||||
unwrap_allocator(allocator);
|
||||
PyEval_GetFrame(); // BOOM!
|
||||
wrap_allocator(allocator);
|
||||
return allocator->malloc(allocator->ctx, size);
|
||||
}
|
||||
|
||||
static void *
|
||||
calloc_wrapper(void *ctx, size_t nelem, size_t elsize)
|
||||
{
|
||||
PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
|
||||
return allocator->calloc(allocator->ctx, nelem, elsize);
|
||||
}
|
||||
|
||||
static void *
|
||||
realloc_wrapper(void *ctx, void *ptr, size_t new_size)
|
||||
{
|
||||
PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
|
||||
return allocator->realloc(allocator->ctx, ptr, new_size);
|
||||
}
|
||||
|
||||
static void
|
||||
free_wrapper(void *ctx, void *ptr)
|
||||
{
|
||||
PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
|
||||
allocator->free(allocator->ctx, ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
wrap_allocator(PyMemAllocatorEx *allocator)
|
||||
{
|
||||
PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, allocator);
|
||||
PyMemAllocatorEx wrapper = {
|
||||
.malloc = &malloc_wrapper,
|
||||
.calloc = &calloc_wrapper,
|
||||
.realloc = &realloc_wrapper,
|
||||
.free = &free_wrapper,
|
||||
.ctx = allocator,
|
||||
};
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &wrapper);
|
||||
}
|
||||
|
||||
static void
|
||||
unwrap_allocator(PyMemAllocatorEx *allocator)
|
||||
{
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, allocator);
|
||||
}
|
||||
|
||||
static int
|
||||
test_get_incomplete_frame(void)
|
||||
{
|
||||
_testembed_Py_Initialize();
|
||||
PyMemAllocatorEx allocator;
|
||||
wrap_allocator(&allocator);
|
||||
// Force an allocation with an incomplete (generator) frame:
|
||||
int result = PyRun_SimpleString("(_ for _ in ())");
|
||||
unwrap_allocator(&allocator);
|
||||
Py_Finalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* *********************************************************
|
||||
* List of test cases and the function that implements it.
|
||||
|
@ -2032,6 +2099,7 @@ static struct TestCase TestCases[] = {
|
|||
#ifndef MS_WINDOWS
|
||||
{"test_frozenmain", test_frozenmain},
|
||||
#endif
|
||||
{"test_get_incomplete_frame", test_get_incomplete_frame},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
|
|
@ -6520,11 +6520,14 @@ _PyEval_GetFrame(void)
|
|||
PyFrameObject *
|
||||
PyEval_GetFrame(void)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
if (tstate->cframe->current_frame == NULL) {
|
||||
_PyInterpreterFrame *frame = _PyEval_GetFrame();
|
||||
while (frame && _PyFrame_IsIncomplete(frame)) {
|
||||
frame = frame->previous;
|
||||
}
|
||||
if (frame == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyFrameObject *f = _PyFrame_GetFrameObject(tstate->cframe->current_frame);
|
||||
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
|
||||
if (f == NULL) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue