@@ -98,7 +98,11 @@ typedef struct {
98
98
99
99
#define CHARACTER_DATA_BUFFER_SIZE 8192
100
100
101
- typedef const void * xmlhandler ;
101
+ // A generic function type for storage.
102
+ // To avoid undefined behaviors, a handler must be cast to the correct
103
+ // function type before it's called; see SETTER_WRAPPER below.
104
+ typedef void (* xmlhandler )(void );
105
+
102
106
typedef void (* xmlhandlersetter )(XML_Parser self , xmlhandler handler );
103
107
104
108
struct HandlerInfo {
@@ -110,9 +114,7 @@ struct HandlerInfo {
110
114
111
115
static struct HandlerInfo handler_info [64 ];
112
116
113
- // gh-111178: Use _Py_NO_SANITIZE_UNDEFINED, rather than using the exact
114
- // handler API for each handler.
115
- static inline void _Py_NO_SANITIZE_UNDEFINED
117
+ static inline void
116
118
CALL_XML_HANDLER_SETTER (const struct HandlerInfo * handler_info ,
117
119
XML_Parser xml_parser , xmlhandler xml_handler )
118
120
{
@@ -1365,7 +1367,7 @@ xmlparse_handler_setter(PyObject *op, PyObject *v, void *closure)
1365
1367
elaborate system of handlers and state could remove the
1366
1368
C handler more effectively. */
1367
1369
if (handlernum == CharacterData && self -> in_callback ) {
1368
- c_handler = noop_character_data_handler ;
1370
+ c_handler = ( xmlhandler ) noop_character_data_handler ;
1369
1371
}
1370
1372
v = NULL ;
1371
1373
}
@@ -2222,13 +2224,84 @@ clear_handlers(xmlparseobject *self, int initial)
2222
2224
}
2223
2225
}
2224
2226
2227
+ /* To avoid undefined behaviors, a function must be *called* via a function
2228
+ * pointer of the correct type.
2229
+ * So, for each `XML_Set*` function, we define a wrapper that calls `XML_Set*`
2230
+ * with its argument cast to the appropriate type.
2231
+ */
2232
+
2233
+ typedef void (* parser_only )(void * );
2234
+ typedef int (* not_standalone )(void * );
2235
+ typedef void (* parser_and_data )(void * , const XML_Char * );
2236
+ typedef void (* parser_and_data_and_int )(void * , const XML_Char * , int );
2237
+ typedef void (* parser_and_data_and_data )(
2238
+ void * , const XML_Char * , const XML_Char * );
2239
+ typedef void (* start_element )(void * , const XML_Char * , const XML_Char * * );
2240
+ typedef void (* element_decl )(void * , const XML_Char * , XML_Content * );
2241
+ typedef void (* xml_decl )(
2242
+ void * , const XML_Char * , const XML_Char * , int );
2243
+ typedef void (* start_doctype_decl )(
2244
+ void * , const XML_Char * , const XML_Char * , const XML_Char * , int );
2245
+ typedef void (* notation_decl )(
2246
+ void * ,
2247
+ const XML_Char * , const XML_Char * , const XML_Char * , const XML_Char * );
2248
+ typedef void (* attlist_decl )(
2249
+ void * ,
2250
+ const XML_Char * , const XML_Char * , const XML_Char * , const XML_Char * ,
2251
+ int );
2252
+ typedef void (* unparsed_entity_decl )(
2253
+ void * ,
2254
+ const XML_Char * , const XML_Char * ,
2255
+ const XML_Char * , const XML_Char * , const XML_Char * );
2256
+ typedef void (* entity_decl )(
2257
+ void * ,
2258
+ const XML_Char * , int ,
2259
+ const XML_Char * , int ,
2260
+ const XML_Char * , const XML_Char * , const XML_Char * , const XML_Char * );
2261
+ typedef int (* external_entity_ref )(
2262
+ XML_Parser ,
2263
+ const XML_Char * , const XML_Char * , const XML_Char * , const XML_Char * );
2264
+
2265
+ #define SETTER_WRAPPER (NAME , TYPE ) \
2266
+ static inline void \
2267
+ pyexpat_Set ## NAME (XML_Parser parser, xmlhandler handler) \
2268
+ { \
2269
+ (void)XML_Set ## NAME (parser, (TYPE)handler); \
2270
+ }
2271
+
2272
+ SETTER_WRAPPER (StartElementHandler , start_element )
2273
+ SETTER_WRAPPER (EndElementHandler , parser_and_data )
2274
+ SETTER_WRAPPER (ProcessingInstructionHandler , parser_and_data_and_data )
2275
+ SETTER_WRAPPER (CharacterDataHandler , parser_and_data_and_int )
2276
+ SETTER_WRAPPER (UnparsedEntityDeclHandler , unparsed_entity_decl )
2277
+ SETTER_WRAPPER (NotationDeclHandler , notation_decl )
2278
+ SETTER_WRAPPER (StartNamespaceDeclHandler , parser_and_data_and_data )
2279
+ SETTER_WRAPPER (EndNamespaceDeclHandler , parser_and_data )
2280
+ SETTER_WRAPPER (CommentHandler , parser_and_data )
2281
+ SETTER_WRAPPER (StartCdataSectionHandler , parser_only )
2282
+ SETTER_WRAPPER (EndCdataSectionHandler , parser_only )
2283
+ SETTER_WRAPPER (DefaultHandler , parser_and_data_and_int )
2284
+ SETTER_WRAPPER (DefaultHandlerExpand , parser_and_data_and_int )
2285
+ SETTER_WRAPPER (NotStandaloneHandler , not_standalone )
2286
+ SETTER_WRAPPER (ExternalEntityRefHandler , external_entity_ref )
2287
+ SETTER_WRAPPER (StartDoctypeDeclHandler , start_doctype_decl )
2288
+ SETTER_WRAPPER (EndDoctypeDeclHandler , parser_only )
2289
+ SETTER_WRAPPER (EntityDeclHandler , entity_decl )
2290
+ SETTER_WRAPPER (XmlDeclHandler , xml_decl )
2291
+ SETTER_WRAPPER (ElementDeclHandler , element_decl )
2292
+ SETTER_WRAPPER (AttlistDeclHandler , attlist_decl )
2293
+ #if XML_COMBINED_VERSION >= 19504
2294
+ SETTER_WRAPPER (SkippedEntityHandler , parser_and_data_and_int )
2295
+ #endif
2296
+ #undef SETTER_WRAPPER
2297
+
2225
2298
static struct HandlerInfo handler_info [] = {
2226
2299
2227
2300
// The cast to `xmlhandlersetter` is needed as the signature of XML
2228
2301
// handler functions is not compatible with `xmlhandlersetter` since
2229
2302
// their second parameter is narrower than a `const void *`.
2230
2303
#define HANDLER_INFO (name ) \
2231
- {#name , (xmlhandlersetter)XML_Set ##name, my_##name},
2304
+ {#name , (xmlhandlersetter)pyexpat_Set ##name, (xmlhandler) my_##name},
2232
2305
2233
2306
HANDLER_INFO (StartElementHandler )
2234
2307
HANDLER_INFO (EndElementHandler )
0 commit comments