diff options
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_heapqmodule.c | 6 | ||||
-rw-r--r-- | Modules/_localemodule.c | 2 | ||||
-rw-r--r-- | Modules/_testcapi/abstract.c | 38 | ||||
-rw-r--r-- | Modules/_testcapi/vectorcall.c | 8 | ||||
-rw-r--r-- | Modules/_testinternalcapi.c | 2 | ||||
-rw-r--r-- | Modules/_threadmodule.c | 18 | ||||
-rw-r--r-- | Modules/getpath.py | 11 | ||||
-rw-r--r-- | Modules/pyexpat.c | 85 |
8 files changed, 144 insertions, 26 deletions
diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c index 560fe431fca..05d01acd771 100644 --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -463,11 +463,11 @@ siftup_max(PyListObject *heap, Py_ssize_t pos) return -1; } - /* Bubble up the smaller child until hitting a leaf. */ + /* Bubble up the larger child until hitting a leaf. */ arr = _PyList_ITEMS(heap); limit = endpos >> 1; /* smallest pos that has no child */ while (pos < limit) { - /* Set childpos to index of smaller child. */ + /* Set childpos to index of larger child. */ childpos = 2*pos + 1; /* leftmost child position */ if (childpos + 1 < endpos) { PyObject* a = arr[childpos + 1]; @@ -487,7 +487,7 @@ siftup_max(PyListObject *heap, Py_ssize_t pos) return -1; } } - /* Move the smaller child up. */ + /* Move the larger child up. */ tmp1 = arr[childpos]; tmp2 = arr[pos]; FT_ATOMIC_STORE_PTR_RELAXED(arr[childpos], tmp2); diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index c1f56008b7c..41e6d48b1db 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -692,7 +692,7 @@ _locale_nl_langinfo_impl(PyObject *module, int item) result = result != NULL ? result : ""; char *oldloc = NULL; if (langinfo_constants[i].category != LC_CTYPE - && ( + && *result && ( #ifdef __GLIBC__ // gh-133740: Always change the locale for ALT_DIGITS and ERA # ifdef ALT_DIGITS diff --git a/Modules/_testcapi/abstract.c b/Modules/_testcapi/abstract.c index d4045afd515..c1f769456ac 100644 --- a/Modules/_testcapi/abstract.c +++ b/Modules/_testcapi/abstract.c @@ -178,6 +178,42 @@ sequence_fast_get_item(PyObject *self, PyObject *args) } +static PyObject * +object_setattr_null_exc(PyObject *self, PyObject *args) +{ + PyObject *obj, *name, *exc; + if (!PyArg_ParseTuple(args, "OOO", &obj, &name, &exc)) { + return NULL; + } + + PyErr_SetObject((PyObject*)Py_TYPE(exc), exc); + if (PyObject_SetAttr(obj, name, NULL) < 0) { + return NULL; + } + assert(PyErr_Occurred()); + return NULL; +} + + +static PyObject * +object_setattrstring_null_exc(PyObject *self, PyObject *args) +{ + PyObject *obj, *exc; + const char *name; + Py_ssize_t size; + if (!PyArg_ParseTuple(args, "Oz#O", &obj, &name, &size, &exc)) { + return NULL; + } + + PyErr_SetObject((PyObject*)Py_TYPE(exc), exc); + if (PyObject_SetAttrString(obj, name, NULL) < 0) { + return NULL; + } + assert(PyErr_Occurred()); + return NULL; +} + + static PyMethodDef test_methods[] = { {"object_getoptionalattr", object_getoptionalattr, METH_VARARGS}, {"object_getoptionalattrstring", object_getoptionalattrstring, METH_VARARGS}, @@ -191,6 +227,8 @@ static PyMethodDef test_methods[] = { {"sequence_fast_get_size", sequence_fast_get_size, METH_O}, {"sequence_fast_get_item", sequence_fast_get_item, METH_VARARGS}, + {"object_setattr_null_exc", object_setattr_null_exc, METH_VARARGS}, + {"object_setattrstring_null_exc", object_setattrstring_null_exc, METH_VARARGS}, {NULL}, }; diff --git a/Modules/_testcapi/vectorcall.c b/Modules/_testcapi/vectorcall.c index 03aaacb328e..f89dcb6c4cf 100644 --- a/Modules/_testcapi/vectorcall.c +++ b/Modules/_testcapi/vectorcall.c @@ -179,14 +179,14 @@ _testcapi_VectorCallClass_set_vectorcall_impl(PyObject *self, if (!PyObject_TypeCheck(self, type)) { return PyErr_Format( PyExc_TypeError, - "expected %s instance", - PyType_GetName(type)); + "expected %N instance", + type); } if (!type->tp_vectorcall_offset) { return PyErr_Format( PyExc_TypeError, - "type %s has no vectorcall offset", - PyType_GetName(type)); + "type %N has no vectorcall offset", + type); } *(vectorcallfunc*)((char*)self + type->tp_vectorcall_offset) = ( VectorCallClass_vectorcall); diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index fdf22a0c994..8027f0015c7 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -121,7 +121,7 @@ get_c_recursion_remaining(PyObject *self, PyObject *Py_UNUSED(args)) PyThreadState *tstate = _PyThreadState_GET(); uintptr_t here_addr = _Py_get_machine_stack_pointer(); _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; - int remaining = (int)((here_addr - _tstate->c_stack_soft_limit)/PYOS_STACK_MARGIN_BYTES * 50); + int remaining = (int)((here_addr - _tstate->c_stack_soft_limit) / _PyOS_STACK_MARGIN_BYTES * 50); return PyLong_FromLong(remaining); } diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index b6ccca943f2..8886a9d6bd0 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -834,9 +834,14 @@ lock_PyThread_acquire_lock(PyObject *op, PyObject *args, PyObject *kwds) return NULL; } - PyLockStatus r = _PyMutex_LockTimed(&self->lock, timeout, - _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH); + PyLockStatus r = _PyMutex_LockTimed( + &self->lock, timeout, + _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH); if (r == PY_LOCK_INTR) { + assert(PyErr_Occurred()); + return NULL; + } + if (r == PY_LOCK_FAILURE && PyErr_Occurred()) { return NULL; } @@ -1054,9 +1059,14 @@ rlock_acquire(PyObject *op, PyObject *args, PyObject *kwds) return NULL; } - PyLockStatus r = _PyRecursiveMutex_LockTimed(&self->lock, timeout, - _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH); + PyLockStatus r = _PyRecursiveMutex_LockTimed( + &self->lock, timeout, + _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH); if (r == PY_LOCK_INTR) { + assert(PyErr_Occurred()); + return NULL; + } + if (r == PY_LOCK_FAILURE && PyErr_Occurred()) { return NULL; } diff --git a/Modules/getpath.py b/Modules/getpath.py index be2210345af..b89d7427e3f 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -364,10 +364,9 @@ if not py_setpath: venv_prefix = None pyvenvcfg = [] - # Search for the 'home' key in pyvenv.cfg. Currently, we don't consider the - # presence of a pyvenv.cfg file without a 'home' key to signify the - # existence of a virtual environment — we quietly ignore them. - # XXX: If we don't find a 'home' key, we don't look for another pyvenv.cfg! + # Search for the 'home' key in pyvenv.cfg. If a home key isn't found, + # then it means a venv is active and home is based on the venv's + # executable (if its a symlink, home is where the symlink points). for line in pyvenvcfg: key, had_equ, value = line.partition('=') if had_equ and key.strip().lower() == 'home': @@ -412,10 +411,8 @@ if not py_setpath: if isfile(candidate): base_executable = candidate break + # home key found; stop iterating over lines break - else: - # We didn't find a 'home' key in pyvenv.cfg (no break), reset venv_prefix. - venv_prefix = None # ****************************************************************************** diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index fa153d86543..c449dd848d1 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -98,7 +98,11 @@ typedef struct { #define CHARACTER_DATA_BUFFER_SIZE 8192 -typedef const void *xmlhandler; +// A generic function type for storage. +// To avoid undefined behaviors, a handler must be cast to the correct +// function type before it's called; see SETTER_WRAPPER below. +typedef void (*xmlhandler)(void); + typedef void (*xmlhandlersetter)(XML_Parser self, xmlhandler handler); struct HandlerInfo { @@ -110,9 +114,7 @@ struct HandlerInfo { static struct HandlerInfo handler_info[64]; -// gh-111178: Use _Py_NO_SANITIZE_UNDEFINED, rather than using the exact -// handler API for each handler. -static inline void _Py_NO_SANITIZE_UNDEFINED +static inline void CALL_XML_HANDLER_SETTER(const struct HandlerInfo *handler_info, XML_Parser xml_parser, xmlhandler xml_handler) { @@ -1365,7 +1367,7 @@ xmlparse_handler_setter(PyObject *op, PyObject *v, void *closure) elaborate system of handlers and state could remove the C handler more effectively. */ if (handlernum == CharacterData && self->in_callback) { - c_handler = noop_character_data_handler; + c_handler = (xmlhandler)noop_character_data_handler; } v = NULL; } @@ -2222,13 +2224,84 @@ clear_handlers(xmlparseobject *self, int initial) } } +/* To avoid undefined behaviors, a function must be *called* via a function + * pointer of the correct type. + * So, for each `XML_Set*` function, we define a wrapper that calls `XML_Set*` + * with its argument cast to the appropriate type. + */ + +typedef void (*parser_only)(void *); +typedef int (*not_standalone)(void *); +typedef void (*parser_and_data)(void *, const XML_Char *); +typedef void (*parser_and_data_and_int)(void *, const XML_Char *, int); +typedef void (*parser_and_data_and_data)( + void *, const XML_Char *, const XML_Char *); +typedef void (*start_element)(void *, const XML_Char *, const XML_Char **); +typedef void (*element_decl)(void *, const XML_Char *, XML_Content *); +typedef void (*xml_decl)( + void *, const XML_Char *, const XML_Char *, int); +typedef void (*start_doctype_decl)( + void *, const XML_Char *, const XML_Char *, const XML_Char *, int); +typedef void (*notation_decl)( + void *, + const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *); +typedef void (*attlist_decl)( + void *, + const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *, + int); +typedef void (*unparsed_entity_decl)( + void *, + const XML_Char *, const XML_Char *, + const XML_Char *, const XML_Char *, const XML_Char *); +typedef void (*entity_decl)( + void *, + const XML_Char *, int, + const XML_Char *, int, + const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *); +typedef int (*external_entity_ref)( + XML_Parser, + const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *); + +#define SETTER_WRAPPER(NAME, TYPE) \ + static inline void \ + pyexpat_Set ## NAME (XML_Parser parser, xmlhandler handler) \ + { \ + (void)XML_Set ## NAME (parser, (TYPE)handler); \ + } + +SETTER_WRAPPER(StartElementHandler, start_element) +SETTER_WRAPPER(EndElementHandler, parser_and_data) +SETTER_WRAPPER(ProcessingInstructionHandler, parser_and_data_and_data) +SETTER_WRAPPER(CharacterDataHandler, parser_and_data_and_int) +SETTER_WRAPPER(UnparsedEntityDeclHandler, unparsed_entity_decl) +SETTER_WRAPPER(NotationDeclHandler, notation_decl) +SETTER_WRAPPER(StartNamespaceDeclHandler, parser_and_data_and_data) +SETTER_WRAPPER(EndNamespaceDeclHandler, parser_and_data) +SETTER_WRAPPER(CommentHandler, parser_and_data) +SETTER_WRAPPER(StartCdataSectionHandler, parser_only) +SETTER_WRAPPER(EndCdataSectionHandler, parser_only) +SETTER_WRAPPER(DefaultHandler, parser_and_data_and_int) +SETTER_WRAPPER(DefaultHandlerExpand, parser_and_data_and_int) +SETTER_WRAPPER(NotStandaloneHandler, not_standalone) +SETTER_WRAPPER(ExternalEntityRefHandler, external_entity_ref) +SETTER_WRAPPER(StartDoctypeDeclHandler, start_doctype_decl) +SETTER_WRAPPER(EndDoctypeDeclHandler, parser_only) +SETTER_WRAPPER(EntityDeclHandler, entity_decl) +SETTER_WRAPPER(XmlDeclHandler, xml_decl) +SETTER_WRAPPER(ElementDeclHandler, element_decl) +SETTER_WRAPPER(AttlistDeclHandler, attlist_decl) +#if XML_COMBINED_VERSION >= 19504 +SETTER_WRAPPER(SkippedEntityHandler, parser_and_data_and_int) +#endif +#undef SETTER_WRAPPER + static struct HandlerInfo handler_info[] = { // The cast to `xmlhandlersetter` is needed as the signature of XML // handler functions is not compatible with `xmlhandlersetter` since // their second parameter is narrower than a `const void *`. #define HANDLER_INFO(name) \ - {#name, (xmlhandlersetter)XML_Set##name, my_##name}, + {#name, (xmlhandlersetter)pyexpat_Set##name, (xmlhandler)my_##name}, HANDLER_INFO(StartElementHandler) HANDLER_INFO(EndElementHandler) |