gh-111178: Fix function signature in pyexpat.c (#131674)

Move _Py_NO_SANITIZE_UNDEFINED macro from faulthandler.c to pyport.h.
This commit is contained in:
Victor Stinner 2025-03-24 18:22:45 +01:00 committed by GitHub
parent d16f455cd8
commit 5fef4ff9ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 33 deletions

View File

@ -655,4 +655,24 @@ extern "C" {
# define _Py_FALLTHROUGH do { } while (0) # define _Py_FALLTHROUGH do { } while (0)
#endif #endif
// _Py_NO_SANITIZE_UNDEFINED(): Disable Undefined Behavior sanitizer (UBsan)
// on a function.
//
// Clang and GCC 9.0+ use __attribute__((no_sanitize("undefined"))).
// GCC 4.9+ uses __attribute__((no_sanitize_undefined)).
#if defined(__has_feature)
# if __has_feature(undefined_behavior_sanitizer)
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
# endif
#endif
#if !defined(_Py_NO_SANITIZE_UNDEFINED) && defined(__GNUC__) \
&& ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
#endif
#ifndef _Py_NO_SANITIZE_UNDEFINED
# define _Py_NO_SANITIZE_UNDEFINED
#endif
#endif /* Py_PYPORT_H */ #endif /* Py_PYPORT_H */

View File

@ -40,23 +40,6 @@
#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, strlen(str)) #define PUTS(fd, str) (void)_Py_write_noraise(fd, str, strlen(str))
// Clang and GCC 9.0+ use __attribute__((no_sanitize("undefined")))
#if defined(__has_feature)
# if __has_feature(undefined_behavior_sanitizer)
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
# endif
#endif
// GCC 4.9+ uses __attribute__((no_sanitize_undefined))
#if !defined(_Py_NO_SANITIZE_UNDEFINED) && defined(__GNUC__) \
&& ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))
# define _Py_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
#endif
#ifndef _Py_NO_SANITIZE_UNDEFINED
# define _Py_NO_SANITIZE_UNDEFINED
#endif
typedef struct { typedef struct {
int signum; int signum;
int enabled; int enabled;

View File

@ -110,11 +110,15 @@ struct HandlerInfo {
static struct HandlerInfo handler_info[64]; static struct HandlerInfo handler_info[64];
#define CALL_XML_HANDLER_SETTER(HANDLER_INFO, XML_PARSER, XML_HANDLER) \ // gh-111178: Use _Py_NO_SANITIZE_UNDEFINED, rather than using the exact
do { \ // handler API for each handler.
xmlhandlersetter setter = (xmlhandlersetter)(HANDLER_INFO).setter; \ static inline void _Py_NO_SANITIZE_UNDEFINED
setter((XML_PARSER), (XML_HANDLER)); \ CALL_XML_HANDLER_SETTER(const struct HandlerInfo *handler_info,
} while (0) XML_Parser xml_parser, xmlhandler xml_handler)
{
xmlhandlersetter setter = (xmlhandlersetter)handler_info->setter;
setter(xml_parser, xml_handler);
}
/* Set an integer attribute on the error object; return true on success, /* Set an integer attribute on the error object; return true on success,
* false on an exception. * false on an exception.
@ -182,6 +186,12 @@ conv_string_to_unicode(const XML_Char *str)
return PyUnicode_DecodeUTF8(str, strlen(str), "strict"); return PyUnicode_DecodeUTF8(str, strlen(str), "strict");
} }
static PyObject *
conv_string_to_unicode_void(void *arg)
{
return conv_string_to_unicode((const XML_Char *)arg);
}
static PyObject * static PyObject *
conv_string_len_to_unicode(const XML_Char *str, int len) conv_string_len_to_unicode(const XML_Char *str, int len)
{ {
@ -498,7 +508,7 @@ VOID_HANDLER(ProcessingInstruction,
(void *userData, (void *userData,
const XML_Char *target, const XML_Char *target,
const XML_Char *data), const XML_Char *data),
("(NO&)", string_intern(self, target), conv_string_to_unicode ,data)) ("(NO&)", string_intern(self, target), conv_string_to_unicode_void, data))
VOID_HANDLER(UnparsedEntityDecl, VOID_HANDLER(UnparsedEntityDecl,
(void *userData, (void *userData,
@ -535,12 +545,13 @@ VOID_HANDLER(XmlDecl,
const XML_Char *encoding, const XML_Char *encoding,
int standalone), int standalone),
("(O&O&i)", ("(O&O&i)",
conv_string_to_unicode ,version, conv_string_to_unicode ,encoding, conv_string_to_unicode_void, version,
conv_string_to_unicode_void, encoding,
standalone)) standalone))
static PyObject * static PyObject *
conv_content_model(XML_Content * const model, conv_content_model(XML_Content * const model,
PyObject *(*conv_string)(const XML_Char *)) PyObject *(*conv_string)(void *))
{ {
PyObject *result = NULL; PyObject *result = NULL;
PyObject *children = PyTuple_New(model->numchildren); PyObject *children = PyTuple_New(model->numchildren);
@ -559,7 +570,7 @@ conv_content_model(XML_Content * const model,
} }
result = Py_BuildValue("(iiO&N)", result = Py_BuildValue("(iiO&N)",
model->type, model->quant, model->type, model->quant,
conv_string,model->name, children); conv_string, model->name, children);
} }
return result; return result;
} }
@ -581,7 +592,7 @@ my_ElementDeclHandler(void *userData,
if (flush_character_buffer(self) < 0) if (flush_character_buffer(self) < 0)
goto finally; goto finally;
modelobj = conv_content_model(model, (conv_string_to_unicode)); modelobj = conv_content_model(model, conv_string_to_unicode_void);
if (modelobj == NULL) { if (modelobj == NULL) {
flag_error(self); flag_error(self);
goto finally; goto finally;
@ -622,7 +633,8 @@ VOID_HANDLER(AttlistDecl,
int isrequired), int isrequired),
("(NNO&O&i)", ("(NNO&O&i)",
string_intern(self, elname), string_intern(self, attname), string_intern(self, elname), string_intern(self, attname),
conv_string_to_unicode ,att_type, conv_string_to_unicode ,dflt, conv_string_to_unicode_void, att_type,
conv_string_to_unicode_void, dflt,
isrequired)) isrequired))
#if XML_COMBINED_VERSION >= 19504 #if XML_COMBINED_VERSION >= 19504
@ -658,7 +670,7 @@ VOID_HANDLER(EndNamespaceDecl,
VOID_HANDLER(Comment, VOID_HANDLER(Comment,
(void *userData, const XML_Char *data), (void *userData, const XML_Char *data),
("(O&)", conv_string_to_unicode ,data)) ("(O&)", conv_string_to_unicode_void, data))
VOID_HANDLER(StartCdataSection, VOID_HANDLER(StartCdataSection,
(void *userData), (void *userData),
@ -689,7 +701,8 @@ RC_HANDLER(int, ExternalEntityRef,
const XML_Char *publicId), const XML_Char *publicId),
int rc=0;, int rc=0;,
("(O&NNN)", ("(O&NNN)",
conv_string_to_unicode ,context, string_intern(self, base), conv_string_to_unicode_void, context,
string_intern(self, base),
string_intern(self, systemId), string_intern(self, publicId)), string_intern(self, systemId), string_intern(self, publicId)),
rc = PyLong_AsLong(rv);, rc, rc = PyLong_AsLong(rv);, rc,
XML_GetUserData(parser)) XML_GetUserData(parser))
@ -1050,7 +1063,7 @@ pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self,
if (handler != NULL) { if (handler != NULL) {
new_parser->handlers[i] = Py_NewRef(handler); new_parser->handlers[i] = Py_NewRef(handler);
struct HandlerInfo info = handler_info[i]; struct HandlerInfo info = handler_info[i];
CALL_XML_HANDLER_SETTER(info, new_parser->itself, info.handler); CALL_XML_HANDLER_SETTER(&info, new_parser->itself, info.handler);
} }
} }
@ -1361,7 +1374,7 @@ xmlparse_handler_setter(PyObject *op, PyObject *v, void *closure)
c_handler = handler_info[handlernum].handler; c_handler = handler_info[handlernum].handler;
} }
Py_XSETREF(self->handlers[handlernum], v); Py_XSETREF(self->handlers[handlernum], v);
CALL_XML_HANDLER_SETTER(handler_info[handlernum], self->itself, c_handler); CALL_XML_HANDLER_SETTER(&handler_info[handlernum], self->itself, c_handler);
return 0; return 0;
} }
@ -2204,7 +2217,7 @@ clear_handlers(xmlparseobject *self, int initial)
} }
else { else {
Py_CLEAR(self->handlers[i]); Py_CLEAR(self->handlers[i]);
CALL_XML_HANDLER_SETTER(handler_info[i], self->itself, NULL); CALL_XML_HANDLER_SETTER(&handler_info[i], self->itself, NULL);
} }
} }
} }