@@ -1950,6 +1950,73 @@ static int test_repeated_init_and_inittab(void)
19501950 return 0 ;
19511951}
19521952
1953+ static void wrap_allocator (PyMemAllocatorEx * allocator );
1954+ static void unwrap_allocator (PyMemAllocatorEx * allocator );
1955+
1956+ static void *
1957+ malloc_wrapper (void * ctx , size_t size )
1958+ {
1959+ PyMemAllocatorEx * allocator = (PyMemAllocatorEx * )ctx ;
1960+ unwrap_allocator (allocator );
1961+ PyEval_GetFrame (); // BOOM!
1962+ wrap_allocator (allocator );
1963+ return allocator -> malloc (allocator -> ctx , size );
1964+ }
1965+
1966+ static void *
1967+ calloc_wrapper (void * ctx , size_t nelem , size_t elsize )
1968+ {
1969+ PyMemAllocatorEx * allocator = (PyMemAllocatorEx * )ctx ;
1970+ return allocator -> calloc (allocator -> ctx , nelem , elsize );
1971+ }
1972+
1973+ static void *
1974+ realloc_wrapper (void * ctx , void * ptr , size_t new_size )
1975+ {
1976+ PyMemAllocatorEx * allocator = (PyMemAllocatorEx * )ctx ;
1977+ return allocator -> realloc (allocator -> ctx , ptr , new_size );
1978+ }
1979+
1980+ static void
1981+ free_wrapper (void * ctx , void * ptr )
1982+ {
1983+ PyMemAllocatorEx * allocator = (PyMemAllocatorEx * )ctx ;
1984+ allocator -> free (allocator -> ctx , ptr );
1985+ }
1986+
1987+ static void
1988+ wrap_allocator (PyMemAllocatorEx * allocator )
1989+ {
1990+ PyMem_GetAllocator (PYMEM_DOMAIN_OBJ , allocator );
1991+ PyMemAllocatorEx wrapper = {
1992+ .malloc = & malloc_wrapper ,
1993+ .calloc = & calloc_wrapper ,
1994+ .realloc = & realloc_wrapper ,
1995+ .free = & free_wrapper ,
1996+ .ctx = allocator ,
1997+ };
1998+ PyMem_SetAllocator (PYMEM_DOMAIN_OBJ , & wrapper );
1999+ }
2000+
2001+ static void
2002+ unwrap_allocator (PyMemAllocatorEx * allocator )
2003+ {
2004+ PyMem_SetAllocator (PYMEM_DOMAIN_OBJ , allocator );
2005+ }
2006+
2007+ static int
2008+ test_get_incomplete_frame (void )
2009+ {
2010+ _testembed_Py_Initialize ();
2011+ PyMemAllocatorEx allocator ;
2012+ wrap_allocator (& allocator );
2013+ // Force an allocation with an incomplete (generator) frame:
2014+ int result = PyRun_SimpleString ("(_ for _ in ())" );
2015+ unwrap_allocator (& allocator );
2016+ Py_Finalize ();
2017+ return result ;
2018+ }
2019+
19532020
19542021/* *********************************************************
19552022 * List of test cases and the function that implements it.
@@ -2032,6 +2099,7 @@ static struct TestCase TestCases[] = {
20322099#ifndef MS_WINDOWS
20332100 {"test_frozenmain" , test_frozenmain },
20342101#endif
2102+ {"test_get_incomplete_frame" , test_get_incomplete_frame },
20352103
20362104 {NULL , NULL }
20372105};
0 commit comments