@@ -98,7 +98,11 @@ typedef struct {
9898
9999#define  CHARACTER_DATA_BUFFER_SIZE  8192
100100
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+ 
102106typedef  void  (* xmlhandlersetter )(XML_Parser  self , xmlhandler  handler );
103107
104108struct  HandlerInfo  {
@@ -110,9 +114,7 @@ struct HandlerInfo {
110114
111115static  struct  HandlerInfo  handler_info [64 ];
112116
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 
116118CALL_XML_HANDLER_SETTER (const  struct  HandlerInfo  * handler_info ,
117119                        XML_Parser  xml_parser , xmlhandler  xml_handler )
118120{
@@ -1365,7 +1367,7 @@ xmlparse_handler_setter(PyObject *op, PyObject *v, void *closure)
13651367           elaborate system of handlers and state could remove the 
13661368           C handler more effectively. */ 
13671369        if  (handlernum  ==  CharacterData  &&  self -> in_callback ) {
1368-             c_handler  =  noop_character_data_handler ;
1370+             c_handler  =  ( xmlhandler ) noop_character_data_handler ;
13691371        }
13701372        v  =  NULL ;
13711373    }
@@ -2222,13 +2224,84 @@ clear_handlers(xmlparseobject *self, int initial)
22222224    }
22232225}
22242226
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+ 
22252298static  struct  HandlerInfo  handler_info [] =  {
22262299
22272300    // The cast to `xmlhandlersetter` is needed as the signature of XML 
22282301    // handler functions is not compatible with `xmlhandlersetter` since 
22292302    // their second parameter is narrower than a `const void *`. 
22302303#define  HANDLER_INFO (name ) \
2231-     {#name , (xmlhandlersetter)XML_Set ##name, my_##name},
2304+     {#name , (xmlhandlersetter)pyexpat_Set ##name, (xmlhandler) my_##name},
22322305
22332306    HANDLER_INFO (StartElementHandler )
22342307    HANDLER_INFO (EndElementHandler )
0 commit comments