mirror of
https://github.com/python/cpython
synced 2024-09-15 22:48:24 +00:00
GH-96975: Skip incomplete frames in PyEval_GetFrame (GH-97003)
This commit is contained in:
parent
ec403536f1
commit
8fd2c3b75b
|
@ -1713,6 +1713,9 @@ def test_audit_run_stdin(self):
|
||||||
timeout=support.SHORT_TIMEOUT,
|
timeout=support.SHORT_TIMEOUT,
|
||||||
returncode=1)
|
returncode=1)
|
||||||
|
|
||||||
|
def test_get_incomplete_frame(self):
|
||||||
|
self.run_embedded_interpreter("test_get_incomplete_frame")
|
||||||
|
|
||||||
|
|
||||||
class MiscTests(EmbeddingTestsMixin, unittest.TestCase):
|
class MiscTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
def test_unicode_id_init(self):
|
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;
|
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.
|
* List of test cases and the function that implements it.
|
||||||
|
@ -2032,6 +2099,7 @@ static struct TestCase TestCases[] = {
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
{"test_frozenmain", test_frozenmain},
|
{"test_frozenmain", test_frozenmain},
|
||||||
#endif
|
#endif
|
||||||
|
{"test_get_incomplete_frame", test_get_incomplete_frame},
|
||||||
|
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6520,11 +6520,14 @@ _PyEval_GetFrame(void)
|
||||||
PyFrameObject *
|
PyFrameObject *
|
||||||
PyEval_GetFrame(void)
|
PyEval_GetFrame(void)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
_PyInterpreterFrame *frame = _PyEval_GetFrame();
|
||||||
if (tstate->cframe->current_frame == NULL) {
|
while (frame && _PyFrame_IsIncomplete(frame)) {
|
||||||
|
frame = frame->previous;
|
||||||
|
}
|
||||||
|
if (frame == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyFrameObject *f = _PyFrame_GetFrameObject(tstate->cframe->current_frame);
|
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue