39
39
* ============================================================================ */
40
40
41
41
#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))))
42
44
43
45
/* Size macros for opaque buffers */
44
46
#define SIZEOF_BYTES_OBJ sizeof(PyBytesObject)
@@ -243,6 +245,13 @@ module _remote_debugging
243
245
* FORWARD DECLARATIONS
244
246
* ============================================================================ */
245
247
248
+ static inline int
249
+ is_frame_valid (
250
+ RemoteUnwinderObject * unwinder ,
251
+ uintptr_t frame_addr ,
252
+ uintptr_t code_object_addr
253
+ );
254
+
246
255
static int
247
256
parse_tasks_in_set (
248
257
RemoteUnwinderObject * unwinder ,
@@ -734,8 +743,7 @@ parse_task_name(
734
743
return NULL ;
735
744
}
736
745
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 ;
746
+ uintptr_t task_name_addr = GET_MEMBER_NO_TAG (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_name );
739
747
740
748
// The task name can be a long or a string so we need to check the type
741
749
char task_name_obj [SIZEOF_PYOBJECT ];
@@ -798,8 +806,7 @@ static int parse_task_awaited_by(
798
806
return -1 ;
799
807
}
800
808
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 ;
809
+ uintptr_t task_ab_addr = GET_MEMBER_NO_TAG (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_awaited_by );
803
810
804
811
if ((void * )task_ab_addr == NULL ) {
805
812
return 0 ;
@@ -849,8 +856,7 @@ handle_yield_from_frame(
849
856
return -1 ;
850
857
}
851
858
852
- uintptr_t stackpointer_addr = GET_MEMBER (uintptr_t , iframe , unwinder -> debug_offsets .interpreter_frame .stackpointer );
853
- stackpointer_addr &= ~Py_TAG_BITS ;
859
+ uintptr_t stackpointer_addr = GET_MEMBER_NO_TAG (uintptr_t , iframe , unwinder -> debug_offsets .interpreter_frame .stackpointer );
854
860
855
861
if ((void * )stackpointer_addr != NULL ) {
856
862
uintptr_t gi_await_addr ;
@@ -917,6 +923,11 @@ parse_coro_chain(
917
923
return -1 ;
918
924
}
919
925
926
+ int8_t frame_state = GET_MEMBER (int8_t , gen_object , unwinder -> debug_offsets .gen_object .gi_frame_state );
927
+ if (frame_state == FRAME_CLEARED ) {
928
+ return 0 ;
929
+ }
930
+
920
931
uintptr_t gen_type_addr = GET_MEMBER (uintptr_t , gen_object , unwinder -> debug_offsets .pyobject .ob_type );
921
932
922
933
PyObject * name = NULL ;
@@ -936,7 +947,7 @@ parse_coro_chain(
936
947
}
937
948
Py_DECREF (name );
938
949
939
- if (GET_MEMBER ( int8_t , gen_object , unwinder -> debug_offsets . gen_object . gi_frame_state ) == FRAME_SUSPENDED_YIELD_FROM ) {
950
+ if (frame_state == FRAME_SUSPENDED_YIELD_FROM ) {
940
951
return handle_yield_from_frame (unwinder , gi_iframe_addr , gen_type_addr , render_to );
941
952
}
942
953
@@ -981,8 +992,7 @@ create_task_result(
981
992
goto error ;
982
993
}
983
994
984
- coro_addr = GET_MEMBER (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_coro );
985
- coro_addr &= ~Py_TAG_BITS ;
995
+ coro_addr = GET_MEMBER_NO_TAG (uintptr_t , task_obj , unwinder -> async_debug_offsets .asyncio_task_object .task_coro );
986
996
987
997
if ((void * )coro_addr != NULL ) {
988
998
if (parse_coro_chain (unwinder , coro_addr , call_stack ) < 0 ) {
@@ -1816,10 +1826,10 @@ parse_frame_from_chunks(
1816
1826
1817
1827
char * frame = (char * )frame_ptr ;
1818
1828
* 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 ;
1829
+ uintptr_t code_object = GET_MEMBER_NO_TAG ( uintptr_t , frame_ptr , unwinder -> debug_offsets . interpreter_frame . executable );
1830
+ int frame_valid = is_frame_valid ( unwinder , ( uintptr_t ) frame , code_object );
1831
+ if ( frame_valid != 1 ) {
1832
+ return frame_valid ;
1823
1833
}
1824
1834
1825
1835
uintptr_t instruction_pointer = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .instr_ptr );
@@ -1832,9 +1842,7 @@ parse_frame_from_chunks(
1832
1842
}
1833
1843
#endif
1834
1844
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 );
1845
+ return parse_code_object (unwinder , result , code_object , instruction_pointer , previous_frame , tlbc_index );
1838
1846
}
1839
1847
1840
1848
/* ============================================================================
@@ -2077,6 +2085,33 @@ find_running_task_and_coro(
2077
2085
* FRAME PARSING FUNCTIONS
2078
2086
* ============================================================================ */
2079
2087
2088
+ static inline int
2089
+ is_frame_valid (
2090
+ RemoteUnwinderObject * unwinder ,
2091
+ uintptr_t frame_addr ,
2092
+ uintptr_t code_object_addr
2093
+ ) {
2094
+ if ((void * )code_object_addr == NULL ) {
2095
+ return 0 ;
2096
+ }
2097
+
2098
+ void * frame = (void * )frame_addr ;
2099
+
2100
+ if (GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) == FRAME_OWNED_BY_CSTACK ||
2101
+ GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) == FRAME_OWNED_BY_INTERPRETER ) {
2102
+ return 0 ; // C frame
2103
+ }
2104
+
2105
+ if (GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) != FRAME_OWNED_BY_GENERATOR
2106
+ && GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ) != FRAME_OWNED_BY_THREAD ) {
2107
+ PyErr_Format (PyExc_RuntimeError , "Unhandled frame owner %d.\n" ,
2108
+ GET_MEMBER (char , frame , unwinder -> debug_offsets .interpreter_frame .owner ));
2109
+ set_exception_cause (unwinder , PyExc_RuntimeError , "Unhandled frame owner type in async frame" );
2110
+ return -1 ;
2111
+ }
2112
+ return 1 ;
2113
+ }
2114
+
2080
2115
static int
2081
2116
parse_frame_object (
2082
2117
RemoteUnwinderObject * unwinder ,
@@ -2098,13 +2133,10 @@ parse_frame_object(
2098
2133
}
2099
2134
2100
2135
* 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 ;
2136
+ uintptr_t code_object = GET_MEMBER_NO_TAG (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable );
2137
+ int frame_valid = is_frame_valid (unwinder , (uintptr_t )frame , code_object );
2138
+ if (frame_valid != 1 ) {
2139
+ return frame_valid ;
2108
2140
}
2109
2141
2110
2142
uintptr_t instruction_pointer = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .instr_ptr );
@@ -2117,9 +2149,7 @@ parse_frame_object(
2117
2149
}
2118
2150
#endif
2119
2151
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 );
2152
+ return parse_code_object (unwinder , result , code_object ,instruction_pointer , previous_frame , tlbc_index );
2123
2153
}
2124
2154
2125
2155
static int
@@ -2144,26 +2174,10 @@ parse_async_frame_object(
2144
2174
}
2145
2175
2146
2176
* 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 ;
2177
+ * code_object = GET_MEMBER_NO_TAG (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .executable );
2178
+ int frame_valid = is_frame_valid (unwinder , (uintptr_t )frame , * code_object );
2179
+ if (frame_valid != 1 ) {
2180
+ return frame_valid ;
2167
2181
}
2168
2182
2169
2183
uintptr_t instruction_pointer = GET_MEMBER (uintptr_t , frame , unwinder -> debug_offsets .interpreter_frame .instr_ptr );
0 commit comments