3939 * ============================================================================ */
4040
4141#define GET_MEMBER (type , obj , offset ) (*(type*)((char*)(obj) + (offset)))
42+ #define CLEAR_PTR_TAG (ptr ) (((uintptr_t)(ptr) & ~Py_TAG_BITS))
43+ #define GET_MEMBER_NO_TAG (type , obj , offset ) (type)(CLEAR_PTR_TAG(*(type*)((char*)(obj) + (offset))))
4244
4345/* Size macros for opaque buffers */
4446#define SIZEOF_BYTES_OBJ sizeof(PyBytesObject)
@@ -212,6 +214,8 @@ typedef struct {
212214#endif
213215} RemoteUnwinderObject ;
214216
217+ #define RemoteUnwinder_CAST (op ) ((RemoteUnwinderObject *)(op))
218+
215219typedef struct
216220{
217221 int lineno ;
@@ -243,6 +247,13 @@ module _remote_debugging
243247 * FORWARD DECLARATIONS
244248 * ============================================================================ */
245249
250+ static inline int
251+ is_frame_valid (
252+ RemoteUnwinderObject * unwinder ,
253+ uintptr_t frame_addr ,
254+ uintptr_t code_object_addr
255+ );
256+
246257static int
247258parse_tasks_in_set (
248259 RemoteUnwinderObject * unwinder ,
@@ -734,8 +745,7 @@ parse_task_name(
734745 return NULL ;
735746 }
736747
737- uintptr_t task_name_addr = GET_MEMBER (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_name );
738- task_name_addr &= ~Py_TAG_BITS ;
748+ uintptr_t task_name_addr = GET_MEMBER_NO_TAG (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_name );
739749
740750 // The task name can be a long or a string so we need to check the type
741751 char task_name_obj [SIZEOF_PYOBJECT ];
@@ -798,8 +808,7 @@ static int parse_task_awaited_by(
798808 return -1 ;
799809 }
800810
801- uintptr_t task_ab_addr = GET_MEMBER (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_awaited_by );
802- task_ab_addr &= ~Py_TAG_BITS ;
811+ uintptr_t task_ab_addr = GET_MEMBER_NO_TAG (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_awaited_by );
803812
804813 if ((void * )task_ab_addr == NULL ) {
805814 return 0 ;
@@ -849,8 +858,7 @@ handle_yield_from_frame(
849858 return -1 ;
850859 }
851860
852- uintptr_t stackpointer_addr = GET_MEMBER (uintptr_t , iframe , unwinder -> debug_offsets .interpreter_frame .stackpointer );
853- stackpointer_addr &= ~Py_TAG_BITS ;
861+ uintptr_t stackpointer_addr = GET_MEMBER_NO_TAG (uintptr_t , iframe , unwinder -> debug_offsets .interpreter_frame .stackpointer );
854862
855863 if ((void * )stackpointer_addr != NULL ) {
856864 uintptr_t gi_await_addr ;
@@ -917,6 +925,11 @@ parse_coro_chain(
917925 return -1 ;
918926 }
919927
928+ int8_t frame_state = GET_MEMBER (int8_t , gen_object , unwinder -> debug_offsets .gen_object .gi_frame_state );
929+ if (frame_state == FRAME_CLEARED ) {
930+ return 0 ;
931+ }
932+
920933 uintptr_t gen_type_addr = GET_MEMBER (uintptr_t , gen_object , unwinder -> debug_offsets .pyobject .ob_type );
921934
922935 PyObject * name = NULL ;
@@ -936,7 +949,7 @@ parse_coro_chain(
936949 }
937950 Py_DECREF (name );
938951
939- if (GET_MEMBER ( int8_t , gen_object , unwinder -> debug_offsets . gen_object . gi_frame_state ) == FRAME_SUSPENDED_YIELD_FROM ) {
952+ if (frame_state == FRAME_SUSPENDED_YIELD_FROM ) {
940953 return handle_yield_from_frame (unwinder , gi_iframe_addr , gen_type_addr , render_to );
941954 }
942955
@@ -981,8 +994,7 @@ create_task_result(
981994 goto error ;
982995 }
983996
984- coro_addr = GET_MEMBER (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_coro );
985- coro_addr &= ~Py_TAG_BITS ;
997+ coro_addr = GET_MEMBER_NO_TAG (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_coro );
986998
987999 if ((void * )coro_addr != NULL ) {
9881000 if (parse_coro_chain (unwinder , coro_addr , call_stack ) < 0 ) {
@@ -1816,10 +1828,10 @@ parse_frame_from_chunks(
18161828
18171829 char * frame = (char * )frame_ptr ;
18181830 * previous_frame = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .previous );
1819-
1820- if ( GET_MEMBER ( char , frame , unwinder -> debug_offsets . interpreter_frame . owner ) >= FRAME_OWNED_BY_INTERPRETER ||
1821- ! GET_MEMBER ( uintptr_t , frame , unwinder -> debug_offsets . interpreter_frame . executable ) ) {
1822- return 0 ;
1831+ uintptr_t code_object = GET_MEMBER_NO_TAG ( uintptr_t , frame_ptr , unwinder -> debug_offsets . interpreter_frame . executable );
1832+ int frame_valid = is_frame_valid ( unwinder , ( uintptr_t ) frame , code_object );
1833+ if ( frame_valid != 1 ) {
1834+ return frame_valid ;
18231835 }
18241836
18251837 uintptr_t instruction_pointer = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .instr_ptr );
@@ -1832,9 +1844,7 @@ parse_frame_from_chunks(
18321844 }
18331845#endif
18341846
1835- return parse_code_object (
1836- unwinder , result , GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable ),
1837- instruction_pointer , previous_frame , tlbc_index );
1847+ return parse_code_object (unwinder , result , code_object , instruction_pointer , previous_frame , tlbc_index );
18381848}
18391849
18401850/* ============================================================================
@@ -2077,6 +2087,33 @@ find_running_task_and_coro(
20772087 * FRAME PARSING FUNCTIONS
20782088 * ============================================================================ */
20792089
2090+ static inline int
2091+ is_frame_valid (
2092+ RemoteUnwinderObject * unwinder ,
2093+ uintptr_t frame_addr ,
2094+ uintptr_t code_object_addr
2095+ ) {
2096+ if ((void * )code_object_addr == NULL ) {
2097+ return 0 ;
2098+ }
2099+
2100+ void * frame = (void * )frame_addr ;
2101+
2102+ if (GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) == FRAME_OWNED_BY_CSTACK ||
2103+ GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) == FRAME_OWNED_BY_INTERPRETER ) {
2104+ return 0 ; // C frame
2105+ }
2106+
2107+ if (GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) != FRAME_OWNED_BY_GENERATOR
2108+ && GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) != FRAME_OWNED_BY_THREAD ) {
2109+ PyErr_Format (PyExc_RuntimeError , "Unhandled frame owner %d.\n" ,
2110+ GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ));
2111+ set_exception_cause (unwinder , PyExc_RuntimeError , "Unhandled frame owner type in async frame" );
2112+ return -1 ;
2113+ }
2114+ return 1 ;
2115+ }
2116+
20802117static int
20812118parse_frame_object (
20822119 RemoteUnwinderObject * unwinder ,
@@ -2098,13 +2135,10 @@ parse_frame_object(
20982135 }
20992136
21002137 * previous_frame = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .previous );
2101-
2102- if (GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) >= FRAME_OWNED_BY_INTERPRETER ) {
2103- return 0 ;
2104- }
2105-
2106- if ((void * )GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable ) == NULL ) {
2107- return 0 ;
2138+ uintptr_t code_object = GET_MEMBER_NO_TAG (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable );
2139+ int frame_valid = is_frame_valid (unwinder , (uintptr_t )frame , code_object );
2140+ if (frame_valid != 1 ) {
2141+ return frame_valid ;
21082142 }
21092143
21102144 uintptr_t instruction_pointer = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .instr_ptr );
@@ -2117,9 +2151,7 @@ parse_frame_object(
21172151 }
21182152#endif
21192153
2120- return parse_code_object (
2121- unwinder , result , GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable ),
2122- instruction_pointer , previous_frame , tlbc_index );
2154+ return parse_code_object (unwinder , result , code_object ,instruction_pointer , previous_frame , tlbc_index );
21232155}
21242156
21252157static int
@@ -2144,26 +2176,10 @@ parse_async_frame_object(
21442176 }
21452177
21462178 * previous_frame = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .previous );
2147-
2148- * code_object = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable );
2149- // Strip tag bits for consistent comparison
2150- * code_object &= ~Py_TAG_BITS ;
2151- assert (code_object != NULL );
2152- if ((void * )* code_object == NULL ) {
2153- return 0 ;
2154- }
2155-
2156- if (GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) == FRAME_OWNED_BY_CSTACK ||
2157- GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) == FRAME_OWNED_BY_INTERPRETER ) {
2158- return 0 ; // C frame
2159- }
2160-
2161- if (GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) != FRAME_OWNED_BY_GENERATOR
2162- && GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) != FRAME_OWNED_BY_THREAD ) {
2163- PyErr_Format (PyExc_RuntimeError , "Unhandled frame owner %d.\n" ,
2164- GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ));
2165- set_exception_cause (unwinder , PyExc_RuntimeError , "Unhandled frame owner type in async frame" );
2166- return -1 ;
2179+ * code_object = GET_MEMBER_NO_TAG (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable );
2180+ int frame_valid = is_frame_valid (unwinder , (uintptr_t )frame , * code_object );
2181+ if (frame_valid != 1 ) {
2182+ return frame_valid ;
21672183 }
21682184
21692185 uintptr_t instruction_pointer = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .instr_ptr );
@@ -2899,8 +2915,9 @@ static PyMethodDef RemoteUnwinder_methods[] = {
28992915};
29002916
29012917static void
2902- RemoteUnwinder_dealloc (RemoteUnwinderObject * self )
2918+ RemoteUnwinder_dealloc (PyObject * op )
29032919{
2920+ RemoteUnwinderObject * self = RemoteUnwinder_CAST (op );
29042921 PyTypeObject * tp = Py_TYPE (self );
29052922 if (self -> code_object_cache ) {
29062923 _Py_hashtable_destroy (self -> code_object_cache );
0 commit comments