From 2e9b4236c3204ba3e33e97558d6649d1d437d7c7 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 13 Jul 2023 11:18:16 +0300 Subject: [PATCH 1/6] gh-111789: Use PyDict_GetItemRef() --- Modules/_asynciomodule.c | 8 +-- Modules/_csv.c | 10 +-- Modules/_ctypes/_ctypes.c | 100 +++++++++++++-------------- Modules/_ctypes/callproc.c | 33 ++++----- Modules/_elementtree.c | 25 ++++--- Modules/_sqlite/cursor.c | 8 +-- Modules/_sqlite/microprotocols.c | 8 +-- Modules/_struct.c | 9 ++- Modules/_threadmodule.c | 9 +-- Modules/_zoneinfo.c | 19 ++---- Modules/pyexpat.c | 17 ++--- Objects/abstract.c | 7 +- Objects/funcobject.c | 9 ++- Objects/moduleobject.c | 27 +++----- Objects/object.c | 28 +++----- Objects/typeobject.c | 114 ++++++++++++------------------- Python/_warnings.c | 8 +-- Python/bltinmodule.c | 9 +-- Python/bytecodes.c | 63 +++++------------ Python/ceval.c | 32 ++++----- Python/codecs.c | 9 ++- Python/compile.c | 9 ++- Python/executor_cases.c.h | 64 +++++------------ Python/generated_cases.c.h | 64 +++++------------ Python/import.c | 32 ++++----- Python/symtable.c | 12 ++-- 26 files changed, 264 insertions(+), 469 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 6d06208dd1d70d..3a11cdc926f138 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -3514,15 +3514,11 @@ _asyncio_current_task_impl(PyObject *module, PyObject *loop) Py_INCREF(loop); } - ret = PyDict_GetItemWithError(state->current_tasks, loop); + int rc = PyDict_GetItemRef(state->current_tasks, loop, &ret); Py_DECREF(loop); - if (ret == NULL && PyErr_Occurred()) { - return NULL; - } - else if (ret == NULL) { + if (rc == 0) { Py_RETURN_NONE; } - Py_INCREF(ret); return ret; } diff --git a/Modules/_csv.c b/Modules/_csv.c index 714fbef08d22c9..ae6b6457ffad9a 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -160,15 +160,9 @@ static PyObject * get_dialect_from_registry(PyObject *name_obj, _csvstate *module_state) { PyObject *dialect_obj; - - dialect_obj = PyDict_GetItemWithError(module_state->dialects, name_obj); - if (dialect_obj == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(module_state->error_obj, "unknown dialect"); + if (PyDict_GetItemRef(module_state->dialects, name_obj, &dialect_obj) == 0) { + PyErr_SetString(module_state->error_obj, "unknown dialect"); } - else - Py_INCREF(dialect_obj); - return dialect_obj; } diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 6e0709cc1e4a4d..93e471a2a99b41 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -243,26 +243,19 @@ PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item) static int _PyDict_GetItemProxy(PyObject *dict, PyObject *key, PyObject **presult) { - PyObject *item = PyDict_GetItemWithError(dict, key); - if (item == NULL) { - if (PyErr_Occurred()) { - return -1; - } + int rc = PyDict_GetItemRef(dict, key, presult); + if (rc <= 0) { // error or not found *presult = NULL; - return 0; + return rc; } + PyObject *item = *presult; if (!PyWeakref_CheckProxy(item)) { - *presult = Py_NewRef(item); - return 0; - } - PyObject *ref; - if (PyWeakref_GetRef(item, &ref) < 0) { - return -1; + return 1; } - // ref is NULL if the referenced object was destroyed - *presult = ref; - return 0; + rc = PyWeakref_GetRef(item, presult); + Py_DECREF(item); + return rc; } /******************************************************************/ @@ -565,18 +558,19 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt dict->paramfunc = StructUnionType_paramfunc; - fields = PyDict_GetItemWithError((PyObject *)dict, &_Py_ID(_fields_)); + if (PyDict_GetItemRef((PyObject *)dict, &_Py_ID(_fields_), &fields) < 0) { + Py_DECREF(result); + return NULL; + } if (fields) { if (PyObject_SetAttr((PyObject *)result, &_Py_ID(_fields_), fields) < 0) { Py_DECREF(result); + Py_DECREF(fields); return NULL; } + Py_DECREF(fields); return (PyObject *)result; } - else if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } else { StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base); @@ -1110,11 +1104,15 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict->paramfunc = PyCPointerType_paramfunc; stgdict->flags |= TYPEFLAG_ISPOINTER; - proto = PyDict_GetItemWithError(typedict, &_Py_ID(_type_)); /* Borrowed ref */ + if (PyDict_GetItemRef(typedict, &_Py_ID(_type_), &proto) < 0) { + Py_DECREF((PyObject *)stgdict); + return NULL; + } if (proto) { StgDictObject *itemdict; const char *current_format; if (-1 == PyCPointerType_SetProto(stgdict, proto)) { + Py_DECREF(proto); Py_DECREF((PyObject *)stgdict); return NULL; } @@ -1134,15 +1132,12 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } else { stgdict->format = _ctypes_alloc_format_string("&", current_format); } + Py_DECREF(proto); if (stgdict->format == NULL) { Py_DECREF((PyObject *)stgdict); return NULL; } } - else if (PyErr_Occurred()) { - Py_DECREF((PyObject *)stgdict); - return NULL; - } /* create the new instance (which is a class, since we are a metatype!) */ @@ -2461,58 +2456,61 @@ make_funcptrtype_dict(StgDictObject *stgdict) stgdict->getfunc = NULL; stgdict->ffi_type_pointer = ffi_type_pointer; - ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_flags_)); + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py_ID(_flags_), &ob) < 0) { + return -1; + } if (!ob || !PyLong_Check(ob)) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_TypeError, "class must define _flags_ which must be an integer"); - } + Py_XDECREF(ob); return -1; } stgdict->flags = PyLong_AsUnsignedLongMask(ob) | TYPEFLAG_ISPOINTER; + Py_DECREF(ob); /* _argtypes_ is optional... */ - ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_argtypes_)); + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py_ID(_argtypes_), &ob) < 0) { + return -1; + } if (ob) { converters = converters_from_argtypes(ob); - if (!converters) + if (!converters) { + Py_DECREF(ob); return -1; - stgdict->argtypes = Py_NewRef(ob); + } + stgdict->argtypes = ob; stgdict->converters = converters; } - else if (PyErr_Occurred()) { + + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py_ID(_restype_), &ob) < 0) { return -1; } - - ob = PyDict_GetItemWithError((PyObject *)stgdict, &_Py_ID(_restype_)); if (ob) { if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { PyErr_SetString(PyExc_TypeError, "_restype_ must be a type, a callable, or None"); + Py_DECREF(ob); return -1; } - stgdict->restype = Py_NewRef(ob); + stgdict->restype = ob; if (PyObject_GetOptionalAttr(ob, &_Py_ID(_check_retval_), &stgdict->checker) < 0) { return -1; } } - else if (PyErr_Occurred()) { +/* XXX later, maybe. + if (PyDict_GetItemRef((PyObject *)stgdict, &_Py _ID(_errcheck_), &ob) < 0) { return -1; } -/* XXX later, maybe. - ob = _PyDict_GetItemIdWithError((PyObject *)stgdict, &PyId__errcheck_); if (ob) { if (!PyCallable_Check(ob)) { PyErr_SetString(PyExc_TypeError, "_errcheck_ must be callable"); + Py_DECREF(ob); return -1; } - stgdict->errcheck = Py_NewRef(ob); - } - else if (PyErr_Occurred()) { - return -1; + stgdict->errcheck = ob; } */ return 0; @@ -3812,13 +3810,12 @@ _get_arg(int *pindex, PyObject *name, PyObject *defval, PyObject *inargs, PyObje return Py_NewRef(v); } if (kwds && name) { - v = PyDict_GetItemWithError(kwds, name); + if (PyDict_GetItemRef(kwds, name, &v) < 0) { + return NULL; + } if (v) { ++*pindex; - return Py_NewRef(v); - } - else if (PyErr_Occurred()) { - return NULL; + return v; } } if (defval) { @@ -4870,11 +4867,8 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) return NULL; PyObject *result; - if (_PyDict_GetItemProxy(cache, key, &result) < 0) { - Py_DECREF(key); - return NULL; - } - if (result) { + if (_PyDict_GetItemProxy(cache, key, &result) != 0) { + // error or found Py_DECREF(key); return result; } diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 2a0c26a0fec1b6..0fb5c087ccb593 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -168,16 +168,18 @@ _ctypes_get_errobj(int **pspace) if (error_object_name == NULL) return NULL; } - errobj = PyDict_GetItemWithError(dict, error_object_name); + if (PyDict_GetItemRef(dict, error_object_name, &errobj) < 0) { + return NULL; + } if (errobj) { if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_NAME_PYMEM)) { PyErr_SetString(PyExc_RuntimeError, "ctypes.error_object is an invalid capsule"); + Py_DECREF(errobj); return NULL; } - Py_INCREF(errobj); } - else if (!PyErr_Occurred()) { + else { void *space = PyMem_Calloc(2, sizeof(int)); if (space == NULL) return NULL; @@ -192,9 +194,6 @@ _ctypes_get_errobj(int **pspace) return NULL; } } - else { - return NULL; - } *pspace = (int *)PyCapsule_GetPointer(errobj, CTYPES_CAPSULE_NAME_PYMEM); return errobj; } @@ -1922,12 +1921,8 @@ create_pointer_type(PyObject *module, PyObject *cls) PyTypeObject *typ; PyObject *key; - result = PyDict_GetItemWithError(_ctypes_ptrtype_cache, cls); - if (result) { - return Py_NewRef(result); - } - else if (PyErr_Occurred()) { - return NULL; + if (PyDict_GetItemRef(_ctypes_ptrtype_cache, cls, &result) != 0) { + return result; } if (PyUnicode_CheckExact(cls)) { PyObject *name = PyUnicode_FromFormat("LP_%U", cls); @@ -1986,16 +1981,14 @@ create_pointer_inst(PyObject *module, PyObject *arg) PyObject *result; PyObject *typ; - typ = PyDict_GetItemWithError(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg)); - if (typ) { - return PyObject_CallOneArg(typ, arg); - } - else if (PyErr_Occurred()) { + if (PyDict_GetItemRef(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { return NULL; } - typ = create_pointer_type(NULL, (PyObject *)Py_TYPE(arg)); - if (typ == NULL) - return NULL; + if (typ == NULL) { + typ = create_pointer_type(NULL, (PyObject *)Py_TYPE(arg)); + if (typ == NULL) + return NULL; + } result = PyObject_CallOneArg(typ, arg); Py_DECREF(typ); return result; diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index f9d5793f9b6497..8e5ffcbc986665 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -372,9 +372,11 @@ get_attrib_from_keywords(PyObject *kwds) if (attrib_str == NULL) { return NULL; } - PyObject *attrib = PyDict_GetItemWithError(kwds, attrib_str); - - if (attrib) { + PyObject *attrib; + if (PyDict_GetItemRef(kwds, attrib_str, &attrib) == 0) { + attrib = PyDict_New(); + } + else if (attrib) { /* If attrib was found in kwds, copy its value and remove it from * kwds */ @@ -382,16 +384,14 @@ get_attrib_from_keywords(PyObject *kwds) Py_DECREF(attrib_str); PyErr_Format(PyExc_TypeError, "attrib must be dict, not %.100s", Py_TYPE(attrib)->tp_name); + Py_DECREF(attrib); return NULL; } - attrib = PyDict_Copy(attrib); + Py_SETREF(attrib, PyDict_Copy(attrib)); if (attrib && PyDict_DelItem(kwds, attrib_str) < 0) { Py_SETREF(attrib, NULL); } } - else if (!PyErr_Occurred()) { - attrib = PyDict_New(); - } Py_DECREF(attrib_str); @@ -1421,11 +1421,12 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, { if (self->extra && self->extra->attrib) { PyObject *attrib = Py_NewRef(self->extra->attrib); - PyObject *value = Py_XNewRef(PyDict_GetItemWithError(attrib, key)); - Py_DECREF(attrib); - if (value != NULL || PyErr_Occurred()) { + PyObject *value; + if (PyDict_GetItemRef(attrib, key, &value) != 0) { + Py_DECREF(attrib); return value; } + Py_DECREF(attrib); } return Py_NewRef(default_value); @@ -3085,9 +3086,7 @@ makeuniversal(XMLParserObject* self, const char* string) if (!key) return NULL; - value = Py_XNewRef(PyDict_GetItemWithError(self->names, key)); - - if (value == NULL && !PyErr_Occurred()) { + if (PyDict_GetItemRef(self->names, key, &value) == 0) { /* new name. convert to universal name, and decode as necessary */ diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 618ce532b2518d..0704efcaa6055e 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -737,12 +737,8 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self, if (!binding_name_obj) { return; } - if (PyDict_CheckExact(parameters)) { - PyObject *item = PyDict_GetItemWithError(parameters, binding_name_obj); - current_param = Py_XNewRef(item); - } else { - current_param = PyObject_GetItem(parameters, binding_name_obj); - } + PyObject *current_param; + (void)PyMapping_GetOptionalItem(parameters, binding_name_obj, ¤t_param); Py_DECREF(binding_name_obj); if (!current_param) { if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) { diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index 92f0148bd4c217..d6405433502d69 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -85,17 +85,15 @@ pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj, if (!key) { return NULL; } - adapter = PyDict_GetItemWithError(state->psyco_adapters, key); + if (PyDict_GetItemRef(state->psyco_adapters, key, &adapter) < 0) { + return NULL; + } Py_DECREF(key); if (adapter) { - Py_INCREF(adapter); adapted = PyObject_CallOneArg(adapter, obj); Py_DECREF(adapter); return adapted; } - if (PyErr_Occurred()) { - return NULL; - } /* try to have the protocol adapt this object */ if (PyObject_GetOptionalAttr(proto, state->str___adapt__, &adapter) < 0) { diff --git a/Modules/_struct.c b/Modules/_struct.c index ff1bf4e96c5f21..3637958933b40c 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -2256,14 +2256,13 @@ cache_struct_converter(PyObject *module, PyObject *fmt, PyStructObject **ptr) return 0; } - s_object = PyDict_GetItemWithError(state->cache, fmt); + if (PyDict_GetItemRef(state->cache, fmt, &s_object) < 0) { + return 0; + } if (s_object != NULL) { - *ptr = (PyStructObject *)Py_NewRef(s_object); + *ptr = (PyStructObject *)s_object; return Py_CLEANUP_SUPPORTED; } - else if (PyErr_Occurred()) { - return 0; - } s_object = PyObject_CallOneArg(state->PyStructType, fmt); if (s_object != NULL) { diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 88ca9032b5e679..0e155ede0ebe4c 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1118,12 +1118,9 @@ local_getattro(localobject *self, PyObject *name) } /* Optimization: just look in dict ourselves */ - PyObject *value = PyDict_GetItemWithError(ldict, name); - if (value != NULL) { - return Py_NewRef(value); - } - if (PyErr_Occurred()) { - return NULL; + PyObject *value; + if (PyDict_GetItemRef(ldict, name, &value) != 0) { + return value; } /* Fall back on generic to get __class__ and __dict__ */ diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index 77644c3155bc33..fcd4af64df0be9 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -853,28 +853,19 @@ load_timedelta(zoneinfo_state *state, long seconds) if (pyoffset == NULL) { return NULL; } - rv = PyDict_GetItemWithError(state->TIMEDELTA_CACHE, pyoffset); - if (rv == NULL) { - if (PyErr_Occurred()) { - goto error; - } + if (PyDict_GetItemRef(state->TIMEDELTA_CACHE, pyoffset, &rv) == 0) { PyObject *tmp = PyDateTimeAPI->Delta_FromDelta( 0, seconds, 0, 1, PyDateTimeAPI->DeltaType); - if (tmp == NULL) { - goto error; + if (tmp != NULL) { + rv = PyDict_SetDefault(state->TIMEDELTA_CACHE, pyoffset, tmp); + Py_XINCREF(rv); + Py_DECREF(tmp); } - - rv = PyDict_SetDefault(state->TIMEDELTA_CACHE, pyoffset, tmp); - Py_DECREF(tmp); } - Py_XINCREF(rv); Py_DECREF(pyoffset); return rv; -error: - Py_DECREF(pyoffset); - return NULL; } /* Constructor for _ttinfo object - this starts by initializing the _ttinfo diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 21579a80dd7f70..9d95309dbb7aa6 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -240,19 +240,12 @@ string_intern(xmlparseobject *self, const char* str) return result; if (!self->intern) return result; - value = PyDict_GetItemWithError(self->intern, result); - if (!value) { - if (!PyErr_Occurred() && - PyDict_SetItem(self->intern, result, result) == 0) - { - return result; - } - else { - Py_DECREF(result); - return NULL; - } + if (PyDict_GetItemRef(self->intern, result, &value) == 0 && + PyDict_SetItem(self->intern, result, result) == 0) + { + return result; } - Py_INCREF(value); + assert((value != NULL) == !PyErr_Occurred()); Py_DECREF(result); return value; } diff --git a/Objects/abstract.c b/Objects/abstract.c index 070e762c58a192..a08e209fe41ef4 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -204,12 +204,7 @@ int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) { if (PyDict_CheckExact(obj)) { - *result = PyDict_GetItemWithError(obj, key); /* borrowed */ - if (*result) { - Py_INCREF(*result); - return 1; - } - return PyErr_Occurred() ? -1 : 0; + return PyDict_GetItemRef(obj, key, result); } *result = PyObject_GetItem(obj, key); diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 8ce1bff7660618..74a2cfa3778e81 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -92,8 +92,8 @@ PyFunction_ClearWatcher(int watcher_id) PyFunctionObject * _PyFunction_FromConstructor(PyFrameConstructor *constr) { - PyObject *module = Py_XNewRef(PyDict_GetItemWithError(constr->fc_globals, &_Py_ID(__name__))); - if (!module && PyErr_Occurred()) { + PyObject *module; + if (PyDict_GetItemRef(constr->fc_globals, &_Py_ID(__name__), &module) < 0) { return NULL; } @@ -158,12 +158,11 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname Py_INCREF(doc); // __module__: Use globals['__name__'] if it exists, or NULL. - PyObject *module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); + PyObject *module; PyObject *builtins = NULL; - if (module == NULL && _PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(globals, &_Py_ID(__name__), &module) < 0) { goto error; } - Py_XINCREF(module); builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref if (builtins == NULL) { diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index a3d55b76aa1012..e1df584e41934b 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -816,28 +816,28 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) PyErr_Clear(); } assert(m->md_dict != NULL); - getattr = PyDict_GetItemWithError(m->md_dict, &_Py_ID(__getattr__)); + if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__getattr__), &getattr) < 0) { + return NULL; + } if (getattr) { PyObject *result = PyObject_CallOneArg(getattr, name); if (result == NULL && suppress == 1 && PyErr_ExceptionMatches(PyExc_AttributeError)) { // suppress AttributeError PyErr_Clear(); } + Py_DECREF(getattr); return result; } - if (PyErr_Occurred()) { + if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__name__), &mod_name) < 0) { return NULL; } - mod_name = PyDict_GetItemWithError(m->md_dict, &_Py_ID(__name__)); if (mod_name && PyUnicode_Check(mod_name)) { - Py_INCREF(mod_name); - PyObject *spec = PyDict_GetItemWithError(m->md_dict, &_Py_ID(__spec__)); - if (spec == NULL && PyErr_Occurred()) { + PyObject *spec; + if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__spec__), &spec) < 0) { Py_DECREF(mod_name); return NULL; } if (suppress != 1) { - Py_XINCREF(spec); if (_PyModuleSpec_IsInitializing(spec)) { PyErr_Format(PyExc_AttributeError, "partially initialized " @@ -856,14 +856,12 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) "module '%U' has no attribute '%U'", mod_name, name); } - Py_XDECREF(spec); } + Py_XDECREF(spec); Py_DECREF(mod_name); return NULL; } - else if (PyErr_Occurred()) { - return NULL; - } + Py_XDECREF(mod_name); if (suppress != 1) { PyErr_Format(PyExc_AttributeError, "module has no attribute '%U'", name); @@ -957,11 +955,8 @@ module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored)) return NULL; } - PyObject *annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__)); - if (annotations) { - Py_INCREF(annotations); - } - else if (!PyErr_Occurred()) { + PyObject *annotations; + if (PyDict_GetItemRef(dict, &_Py_ID(__annotations__), &annotations) == 0) { annotations = PyDict_New(); if (annotations) { int result = PyDict_SetItem( diff --git a/Objects/object.c b/Objects/object.c index 1cc3f914646709..bfc53ec003bf02 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1482,19 +1482,12 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) } if (dict != NULL) { Py_INCREF(dict); - PyObject *attr = PyDict_GetItemWithError(dict, name); - if (attr != NULL) { - *method = Py_NewRef(attr); + if (PyDict_GetItemRef(dict, name, method) != 0) { Py_DECREF(dict); Py_XDECREF(descr); return 0; } Py_DECREF(dict); - - if (PyErr_Occurred()) { - Py_XDECREF(descr); - return 0; - } } if (meth_found) { @@ -1600,20 +1593,17 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, if (dict != NULL) { Py_INCREF(dict); res = PyDict_GetItemWithError(dict, name); + int rc = PyDict_GetItemRef(dict, name, &res); + Py_DECREF(dict); if (res != NULL) { - Py_INCREF(res); - Py_DECREF(dict); goto done; } - else { - Py_DECREF(dict); - if (PyErr_Occurred()) { - if (suppress && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - } - else { - goto done; - } + else if (rc < 0) { + if (suppress && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + else { + goto done; } } } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f44e30cf0446a5..62f229b78908b6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1092,14 +1092,9 @@ type_module(PyTypeObject *type, void *context) if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { PyObject *dict = lookup_tp_dict(type); - mod = PyDict_GetItemWithError(dict, &_Py_ID(__module__)); - if (mod == NULL) { - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "__module__"); - } - return NULL; + if (PyDict_GetItemRef(dict, &_Py_ID(__module__), &mod) == 0) { + PyErr_Format(PyExc_AttributeError, "__module__"); } - Py_INCREF(mod); } else { const char *s = strrchr(type->tp_name, '.'); @@ -1134,17 +1129,16 @@ type_abstractmethods(PyTypeObject *type, void *context) PyObject *mod = NULL; /* type itself has an __abstractmethods__ descriptor (this). Don't return that. */ - if (type != &PyType_Type) { - PyObject *dict = lookup_tp_dict(type); - mod = PyDict_GetItemWithError(dict, &_Py_ID(__abstractmethods__)); + if (type == &PyType_Type) { + PyErr_SetObject(PyExc_AttributeError, &_Py_ID(__abstractmethods__)); } - if (!mod) { - if (!PyErr_Occurred()) { + else { + PyObject *dict = lookup_tp_dict(type); + if (PyDict_GetItemRef(dict, &_Py_ID(__abstractmethods__), &mod) == 0) { PyErr_SetObject(PyExc_AttributeError, &_Py_ID(__abstractmethods__)); } - return NULL; } - return Py_NewRef(mod); + return mod; } static int @@ -1435,18 +1429,12 @@ type_get_doc(PyTypeObject *type, void *context) return _PyType_GetDocFromInternalDoc(type->tp_name, type->tp_doc); } PyObject *dict = lookup_tp_dict(type); - result = PyDict_GetItemWithError(dict, &_Py_ID(__doc__)); - if (result == NULL) { - if (!PyErr_Occurred()) { - result = Py_NewRef(Py_None); - } - } - else if (Py_TYPE(result)->tp_descr_get) { - result = Py_TYPE(result)->tp_descr_get(result, NULL, - (PyObject *)type); + if (PyDict_GetItemRef(dict, &_Py_ID(__doc__), &result) == 0) { + result = Py_NewRef(Py_None); } - else { - Py_INCREF(result); + else if (result && Py_TYPE(result)->tp_descr_get) { + Py_SETREF(result, Py_TYPE(result)->tp_descr_get(result, NULL, + (PyObject *)type)); } return result; } @@ -1477,16 +1465,16 @@ type_get_annotations(PyTypeObject *type, void *context) PyObject *annotations; PyObject *dict = lookup_tp_dict(type); - annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__)); + if (PyDict_GetItemRef(dict, &_Py_ID(__annotations__), &annotations) < 0) { + return NULL; + } if (annotations) { if (Py_TYPE(annotations)->tp_descr_get) { - annotations = Py_TYPE(annotations)->tp_descr_get( - annotations, NULL, (PyObject *)type); - } else { - Py_INCREF(annotations); + Py_SETREF(annotations, Py_TYPE(annotations)->tp_descr_get( + annotations, NULL, (PyObject *)type)); } } - else if (!PyErr_Occurred()) { + else { annotations = PyDict_New(); if (annotations) { int result = PyDict_SetItem( @@ -1533,16 +1521,11 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context) static PyObject * type_get_type_params(PyTypeObject *type, void *context) { - PyObject *params = PyDict_GetItemWithError(lookup_tp_dict(type), &_Py_ID(__type_params__)); - - if (params) { - return Py_NewRef(params); - } - if (PyErr_Occurred()) { - return NULL; + PyObject *params; + if (PyDict_GetItemRef(lookup_tp_dict(type), &_Py_ID(__type_params__), ¶ms) == 0) { + params = PyTuple_New(0); } - - return PyTuple_New(0); + return params; } static int @@ -3436,18 +3419,12 @@ type_new_set_module(PyTypeObject *type) return 0; } - PyObject *module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); - if (module == NULL) { - if (PyErr_Occurred()) { - return -1; - } - return 0; + PyObject *module; + r = PyDict_GetItemRef(globals, &_Py_ID(__name__), &module); + if (module) { + r = PyDict_SetItem(dict, &_Py_ID(__module__), module); } - - if (PyDict_SetItem(dict, &_Py_ID(__module__), module) < 0) { - return -1; - } - return 0; + return r; } @@ -3458,23 +3435,24 @@ type_new_set_ht_name(PyTypeObject *type) { PyHeapTypeObject *et = (PyHeapTypeObject *)type; PyObject *dict = lookup_tp_dict(type); - PyObject *qualname = PyDict_GetItemWithError(dict, &_Py_ID(__qualname__)); + PyObject *qualname; + if (PyDict_GetItemRef(dict, &_Py_ID(__qualname__), &qualname) < 0) { + return -1; + } if (qualname != NULL) { if (!PyUnicode_Check(qualname)) { PyErr_Format(PyExc_TypeError, "type __qualname__ must be a str, not %s", Py_TYPE(qualname)->tp_name); + Py_DECREF(qualname); return -1; } - et->ht_qualname = Py_NewRef(qualname); + et->ht_qualname = qualname; if (PyDict_DelItem(dict, &_Py_ID(__qualname__)) < 0) { return -1; } } else { - if (PyErr_Occurred()) { - return -1; - } et->ht_qualname = Py_NewRef(et->ht_name); } return 0; @@ -5887,24 +5865,22 @@ _PyType_GetSlotNames(PyTypeObject *cls) /* Get the slot names from the cache in the class if possible. */ PyObject *dict = lookup_tp_dict(cls); - slotnames = PyDict_GetItemWithError(dict, &_Py_ID(__slotnames__)); + if (PyDict_GetItemRef(dict, &_Py_ID(__slotnames__), &slotnames) < 0) { + return NULL; + } if (slotnames != NULL) { if (slotnames != Py_None && !PyList_Check(slotnames)) { PyErr_Format(PyExc_TypeError, "%.200s.__slotnames__ should be a list or None, " "not %.200s", cls->tp_name, Py_TYPE(slotnames)->tp_name); + Py_DECREF(slotnames); return NULL; } - return Py_NewRef(slotnames); - } - else { - if (PyErr_Occurred()) { - return NULL; - } - /* The class does not have the slot names cached yet. */ + return slotnames; } + /* The class does not have the slot names cached yet. */ copyreg = import_copyreg(); if (copyreg == NULL) return NULL; @@ -10263,23 +10239,17 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * return NULL; /* keep a strong reference to mro because su_obj_type->tp_mro can be - replaced during PyDict_GetItemWithError(dict, name) */ + replaced during PyDict_GetItemRef(dict, name, &res) */ Py_INCREF(mro); do { PyObject *obj = PyTuple_GET_ITEM(mro, i); PyObject *dict = lookup_tp_dict(_PyType_CAST(obj)); assert(dict != NULL && PyDict_Check(dict)); - res = PyDict_GetItemWithError(dict, name); - if (res != NULL) { - Py_INCREF(res); + if (PyDict_GetItemRef(dict, name, &res) != 0) { Py_DECREF(mro); return res; } - else if (PyErr_Occurred()) { - Py_DECREF(mro); - return NULL; - } i++; } while (i < n); diff --git a/Python/_warnings.c b/Python/_warnings.c index 4b7fb888247145..d4765032824e56 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -425,15 +425,15 @@ already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key, Py_DECREF(version_obj); } else { - already_warned = PyDict_GetItemWithError(registry, key); + if (PyDict_GetItemRef(registry, key, &already_warned) < 0) { + return -1; + } if (already_warned != NULL) { int rc = PyObject_IsTrue(already_warned); + Py_DECREF(already_warned); if (rc != 0) return rc; } - else if (PyErr_Occurred()) { - return -1; - } } /* This warning wasn't found in the registry, set it. */ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index c373585c0986ce..4266d724bad5ee 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -5,7 +5,6 @@ #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_Vector() #include "pycore_compile.h" // _PyAST_Compile() -#include "pycore_dict.h" // _PyDict_GetItemWithError() #include "pycore_long.h" // _PyLong_CompactValue #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_object.h" // _Py_AddToAllObjects() @@ -141,18 +140,16 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, goto error; } - meta = _PyDict_GetItemWithError(mkw, &_Py_ID(metaclass)); + if (PyDict_GetItemRef(mkw, &_Py_ID(metaclass), &meta) < 0) { + goto error; + } if (meta != NULL) { - Py_INCREF(meta); if (PyDict_DelItem(mkw, &_Py_ID(metaclass)) < 0) { goto error; } /* metaclass is explicitly given, check if it's indeed a class */ isclass = PyType_Check(meta); } - else if (PyErr_Occurred()) { - goto error; - } } if (meta == NULL) { /* if there are no bases, use type: */ diff --git a/Python/bytecodes.c b/Python/bytecodes.c index f487e95854b7fa..983e1c92df13c0 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -638,16 +638,12 @@ dummy_func( inst(BINARY_SUBSCR_DICT, (unused/1, dict, sub -- res)) { DEOPT_IF(!PyDict_CheckExact(dict)); STAT_INC(BINARY_SUBSCR, hit); - res = PyDict_GetItemWithError(dict, sub); - if (res == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetKeyError(sub); - } - DECREF_INPUTS(); - ERROR_IF(true, error); + int rc = PyDict_GetItemRef(dict, sub, &res); + if (rc == 0) { + _PyErr_SetKeyError(sub); } - Py_INCREF(res); // Do this before DECREF'ing dict, sub DECREF_INPUTS(); + ERROR_IF(rc <= 0, error); } inst(BINARY_SUBSCR_GETITEM, (unused/1, container, sub -- unused)) { @@ -1344,14 +1340,10 @@ dummy_func( GOTO_ERROR(error); } if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { GOTO_ERROR(error); } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1378,14 +1370,10 @@ dummy_func( GOTO_ERROR(error); } if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { GOTO_ERROR(error); } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1658,34 +1646,17 @@ dummy_func( ERROR_IF(true, error); } /* check if __annotations__ in locals()... */ - if (PyDict_CheckExact(LOCALS())) { - ann_dict = _PyDict_GetItemWithError(LOCALS(), - &_Py_ID(__annotations__)); - if (ann_dict == NULL) { - ERROR_IF(_PyErr_Occurred(tstate), error); - /* ...if not, create a new one */ - ann_dict = PyDict_New(); - ERROR_IF(ann_dict == NULL, error); - err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - ERROR_IF(err, error); - } + ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + ERROR_IF(ann_dict == NULL, error); + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + ERROR_IF(err, error); } else { - /* do the same if locals() is not a dict */ - ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - ERROR_IF(ann_dict == NULL, error); - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - ERROR_IF(err, error); - } - else { - Py_DECREF(ann_dict); - } + Py_DECREF(ann_dict); } } diff --git a/Python/ceval.c b/Python/ceval.c index 670f312f126201..57424d5c44e71c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1586,14 +1586,14 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func, continue; PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i); if (func->func_kwdefaults != NULL) { - PyObject *def = PyDict_GetItemWithError(func->func_kwdefaults, varname); + PyObject *def; + if (PyDict_GetItemRef(func->func_kwdefaults, varname, &def) < 0) { + goto fail_post_args; + } if (def) { - localsplus[i] = Py_NewRef(def); + localsplus[i] = def; continue; } - else if (_PyErr_Occurred(tstate)) { - goto fail_post_args; - } } missing++; } @@ -2395,13 +2395,9 @@ PyEval_GetBuiltins(void) PyObject * _PyEval_GetBuiltin(PyObject *name) { - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *attr = PyDict_GetItemWithError(PyEval_GetBuiltins(), name); - if (attr) { - Py_INCREF(attr); - } - else if (!_PyErr_Occurred(tstate)) { - _PyErr_SetObject(tstate, PyExc_AttributeError, name); + PyObject *attr; + if (PyDict_GetItemRef(PyEval_GetBuiltins(), name, &attr) == 0) { + PyErr_SetObject(PyExc_AttributeError, name); } return attr; } @@ -2552,12 +2548,12 @@ static PyObject * import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name, PyObject *fromlist, PyObject *level) { - PyObject *import_func = _PyDict_GetItemWithError(frame->f_builtins, - &_Py_ID(__import__)); + PyObject *import_func; + if (PyDict_GetItemRef(frame->f_builtins, &_Py_ID(__import__), &import_func) < 0) { + return NULL; + } if (import_func == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found"); - } + _PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found"); return NULL; } @@ -2568,6 +2564,7 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, /* Fast path for not overloaded __import__. */ if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) { + Py_DECREF(import_func); int ilevel = PyLong_AsInt(level); if (ilevel == -1 && _PyErr_Occurred(tstate)) { return NULL; @@ -2581,7 +2578,6 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, } PyObject* args[5] = {name, frame->f_globals, locals, fromlist, level}; - Py_INCREF(import_func); PyObject *res = PyObject_Vectorcall(import_func, args, 5, NULL); Py_DECREF(import_func); return res; diff --git a/Python/codecs.c b/Python/codecs.c index b79bf555f2f22a..545bf82e00dca1 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -146,15 +146,14 @@ PyObject *_PyCodec_Lookup(const char *encoding) PyUnicode_InternInPlace(&v); /* First, try to lookup the name in the registry dictionary */ - PyObject *result = PyDict_GetItemWithError(interp->codec_search_cache, v); + PyObject *result; + if (PyDict_GetItemRef(interp->codec_search_cache, v, &result) < 0) { + goto onError; + } if (result != NULL) { - Py_INCREF(result); Py_DECREF(v); return result; } - else if (PyErr_Occurred()) { - goto onError; - } /* Next, scan the search functions in order of registration */ const Py_ssize_t len = PyList_Size(interp->codec_search_path); diff --git a/Python/compile.c b/Python/compile.c index 6c64b405b2b286..5da09229f02c09 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -944,11 +944,10 @@ dict_add_o(PyObject *dict, PyObject *o) PyObject *v; Py_ssize_t arg; - v = PyDict_GetItemWithError(dict, o); + if (PyDict_GetItemRef(dict, o, &v) < 0) { + return ERROR; + } if (!v) { - if (PyErr_Occurred()) { - return ERROR; - } arg = PyDict_GET_SIZE(dict); v = PyLong_FromSsize_t(arg); if (!v) { @@ -958,10 +957,10 @@ dict_add_o(PyObject *dict, PyObject *o) Py_DECREF(v); return ERROR; } - Py_DECREF(v); } else arg = PyLong_AsLong(v); + Py_DECREF(v); return arg; } diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index eb56c34b432783..859e1c959e441e 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -512,18 +512,13 @@ dict = stack_pointer[-2]; DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); - res = PyDict_GetItemWithError(dict, sub); - if (res == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetKeyError(sub); - } - Py_DECREF(dict); - Py_DECREF(sub); - if (true) goto pop_2_error_tier_two; + int rc = PyDict_GetItemRef(dict, sub, &res); + if (rc == 0) { + _PyErr_SetKeyError(sub); } - Py_INCREF(res); // Do this before DECREF'ing dict, sub Py_DECREF(dict); Py_DECREF(sub); + if (rc <= 0) goto pop_2_error_tier_two; STACK_SHRINK(1); stack_pointer[-1] = res; break; @@ -1040,14 +1035,10 @@ GOTO_ERROR(error); } if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { GOTO_ERROR(error); } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1077,14 +1068,10 @@ GOTO_ERROR(error); } if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { GOTO_ERROR(error); } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1422,34 +1409,17 @@ if (true) goto error_tier_two; } /* check if __annotations__ in locals()... */ - if (PyDict_CheckExact(LOCALS())) { - ann_dict = _PyDict_GetItemWithError(LOCALS(), - &_Py_ID(__annotations__)); - if (ann_dict == NULL) { - if (_PyErr_Occurred(tstate)) goto error_tier_two; - /* ...if not, create a new one */ - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error_tier_two; - err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error_tier_two; - } + if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error_tier_two; + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error_tier_two; + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error_tier_two; } else { - /* do the same if locals() is not a dict */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error_tier_two; - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error_tier_two; - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error_tier_two; - } - else { - Py_DECREF(ann_dict); - } + Py_DECREF(ann_dict); } break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 12e4f5204cc3dc..a02e8457817d1d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -896,18 +896,13 @@ dict = stack_pointer[-2]; DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); - res = PyDict_GetItemWithError(dict, sub); - if (res == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetKeyError(sub); - } - Py_DECREF(dict); - Py_DECREF(sub); - if (true) goto pop_2_error; + int rc = PyDict_GetItemRef(dict, sub, &res); + if (rc == 0) { + _PyErr_SetKeyError(sub); } - Py_INCREF(res); // Do this before DECREF'ing dict, sub Py_DECREF(dict); Py_DECREF(sub); + if (rc <= 0) goto pop_2_error; STACK_SHRINK(1); stack_pointer[-1] = res; DISPATCH(); @@ -1950,14 +1945,10 @@ GOTO_ERROR(error); } if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { GOTO_ERROR(error); } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1990,14 +1981,10 @@ GOTO_ERROR(error); } if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { GOTO_ERROR(error); } - else { + if (v == NULL) { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -2422,34 +2409,17 @@ if (true) goto error; } /* check if __annotations__ in locals()... */ - if (PyDict_CheckExact(LOCALS())) { - ann_dict = _PyDict_GetItemWithError(LOCALS(), - &_Py_ID(__annotations__)); - if (ann_dict == NULL) { - if (_PyErr_Occurred(tstate)) goto error; - /* ...if not, create a new one */ - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error; - err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error; - } + if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error; + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error; } else { - /* do the same if locals() is not a dict */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error; - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error; - } - else { - Py_DECREF(ann_dict); - } + Py_DECREF(ann_dict); } DISPATCH(); } diff --git a/Python/import.c b/Python/import.c index b6ffba5c5746e2..ab39866b86e6c2 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2372,9 +2372,8 @@ get_path_importer(PyThreadState *tstate, PyObject *path_importer_cache, if (nhooks < 0) return NULL; /* Shouldn't happen */ - importer = PyDict_GetItemWithError(path_importer_cache, p); - if (importer != NULL || _PyErr_Occurred(tstate)) { - return Py_XNewRef(importer); + if (PyDict_GetItemRef(path_importer_cache, p, &importer) != 0) { + return importer; } /* set path_importer_cache[p] to None to avoid recursion */ @@ -2565,7 +2564,7 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level { PyObject *abs_name; PyObject *package = NULL; - PyObject *spec; + PyObject *spec = NULL; Py_ssize_t last_dot; PyObject *base; int level_up; @@ -2578,20 +2577,18 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level _PyErr_SetString(tstate, PyExc_TypeError, "globals must be a dict"); goto error; } - package = PyDict_GetItemWithError(globals, &_Py_ID(__package__)); + if (PyDict_GetItemRef(globals, &_Py_ID(__package__), &package) < 0) { + goto error; + } if (package == Py_None) { + Py_DECREF(package); package = NULL; } - else if (package == NULL && _PyErr_Occurred(tstate)) { - goto error; - } - spec = PyDict_GetItemWithError(globals, &_Py_ID(__spec__)); - if (spec == NULL && _PyErr_Occurred(tstate)) { + if (PyDict_GetItemRef(globals, &_Py_ID(__spec__), &spec) < 0) { goto error; } if (package != NULL) { - Py_INCREF(package); if (!PyUnicode_Check(package)) { _PyErr_SetString(tstate, PyExc_TypeError, "package must be a string"); @@ -2635,16 +2632,15 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level goto error; } - package = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); + if (PyDict_GetItemRef(globals, &_Py_ID(__name__), &package) < 0) { + goto error; + } if (package == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetString(tstate, PyExc_KeyError, - "'__name__' not in globals"); - } + _PyErr_SetString(tstate, PyExc_KeyError, + "'__name__' not in globals"); goto error; } - Py_INCREF(package); if (!PyUnicode_Check(package)) { _PyErr_SetString(tstate, PyExc_TypeError, "__name__ must be a string"); @@ -2692,6 +2688,7 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level } } + Py_XDECREF(spec); base = PyUnicode_Substring(package, 0, last_dot); Py_DECREF(package); if (base == NULL || PyUnicode_GET_LENGTH(name) == 0) { @@ -2708,6 +2705,7 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level "with no known parent package"); error: + Py_XDECREF(spec); Py_XDECREF(package); return NULL; } diff --git a/Python/symtable.c b/Python/symtable.c index da7fec0ee7cf0c..52d5932896b263 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -497,18 +497,14 @@ _PySymtable_Lookup(struct symtable *st, void *key) k = PyLong_FromVoidPtr(key); if (k == NULL) return NULL; - v = PyDict_GetItemWithError(st->st_blocks, k); - Py_DECREF(k); - - if (v) { - assert(PySTEntry_Check(v)); - } - else if (!PyErr_Occurred()) { + if (PyDict_GetItemRef(st->st_blocks, k, &v) == 0) { PyErr_SetString(PyExc_KeyError, "unknown symbol table entry"); } + Py_DECREF(k); - return (PySTEntryObject *)Py_XNewRef(v); + assert(v == NULL || PySTEntry_Check(v)); + return (PySTEntryObject *)v; } long From 2d132e6fae6a31993359aec74dd4d8ce28e94144 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 7 Nov 2023 18:52:58 +0200 Subject: [PATCH 2/6] Add more comments. --- Modules/_ctypes/_ctypes.c | 2 +- Modules/_ctypes/callproc.c | 2 ++ Modules/_elementtree.c | 2 ++ Modules/_threadmodule.c | 1 + Objects/moduleobject.c | 2 ++ Objects/object.c | 2 ++ Objects/typeobject.c | 1 + Python/import.c | 3 ++- 8 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 93e471a2a99b41..73ba59dcc9ff57 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4872,7 +4872,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) Py_DECREF(key); return result; } - + // not found if (!PyType_Check(itemtype)) { PyErr_SetString(PyExc_TypeError, "Expected a type object"); diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 0fb5c087ccb593..4693ab1b7d5fac 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1922,8 +1922,10 @@ create_pointer_type(PyObject *module, PyObject *cls) PyObject *key; if (PyDict_GetItemRef(_ctypes_ptrtype_cache, cls, &result) != 0) { + // error or found return result; } + // not found if (PyUnicode_CheckExact(cls)) { PyObject *name = PyUnicode_FromFormat("LP_%U", cls); result = PyObject_CallFunction((PyObject *)Py_TYPE(&PyCPointer_Type), diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 8e5ffcbc986665..ff343a83fb1aed 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1423,9 +1423,11 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, PyObject *attrib = Py_NewRef(self->extra->attrib); PyObject *value; if (PyDict_GetItemRef(attrib, key, &value) != 0) { + // error or found Py_DECREF(attrib); return value; } + // not found Py_DECREF(attrib); } diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 0e155ede0ebe4c..882d18880d6199 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1120,6 +1120,7 @@ local_getattro(localobject *self, PyObject *name) /* Optimization: just look in dict ourselves */ PyObject *value; if (PyDict_GetItemRef(ldict, name, &value) != 0) { + // error or found return value; } diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index e1df584e41934b..bba77ce8ab7e7b 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -522,6 +522,7 @@ PyModule_GetNameObject(PyObject *mod) } PyObject *name; if (PyDict_GetItemRef(dict, &_Py_ID(__name__), &name) <= 0) { + // error or not found goto error; } if (!PyUnicode_Check(name)) { @@ -562,6 +563,7 @@ PyModule_GetFilenameObject(PyObject *mod) } PyObject *fileobj; if (PyDict_GetItemRef(dict, &_Py_ID(__file__), &fileobj) <= 0) { + // error or not found goto error; } if (!PyUnicode_Check(fileobj)) { diff --git a/Objects/object.c b/Objects/object.c index da80b351bb0922..f38565477af75a 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1489,10 +1489,12 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) if (dict != NULL) { Py_INCREF(dict); if (PyDict_GetItemRef(dict, name, method) != 0) { + // error or found Py_DECREF(dict); Py_XDECREF(descr); return 0; } + // not found Py_DECREF(dict); } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 62f229b78908b6..74ad42d86bc4e9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -10247,6 +10247,7 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * assert(dict != NULL && PyDict_Check(dict)); if (PyDict_GetItemRef(dict, name, &res) != 0) { + // error or found Py_DECREF(mro); return res; } diff --git a/Python/import.c b/Python/import.c index ab39866b86e6c2..b1eefc1a617b47 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2373,9 +2373,10 @@ get_path_importer(PyThreadState *tstate, PyObject *path_importer_cache, return NULL; /* Shouldn't happen */ if (PyDict_GetItemRef(path_importer_cache, p, &importer) != 0) { + // error or found return importer; } - + // not found /* set path_importer_cache[p] to None to avoid recursion */ if (PyDict_SetItem(path_importer_cache, p, Py_None) != 0) return NULL; From 353380027cbb8180a6cc645f6dc5e39a19bd48c3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 7 Nov 2023 20:34:17 +0200 Subject: [PATCH 3/6] Fixes and polishing. --- Modules/_ctypes/_ctypes.c | 12 +++--------- Objects/typeobject.c | 1 + Python/bytecodes.c | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 73ba59dcc9ff57..550107953cc028 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -244,17 +244,11 @@ static int _PyDict_GetItemProxy(PyObject *dict, PyObject *key, PyObject **presult) { int rc = PyDict_GetItemRef(dict, key, presult); - if (rc <= 0) { // error or not found - *presult = NULL; - return rc; - } - PyObject *item = *presult; - if (!PyWeakref_CheckProxy(item)) { - return 1; + if (item && PyWeakref_CheckProxy(item)) { + rc = PyWeakref_GetRef(item, presult); + Py_DECREF(item); } - rc = PyWeakref_GetRef(item, presult); - Py_DECREF(item); return rc; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 74ad42d86bc4e9..63db437c5e4010 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3423,6 +3423,7 @@ type_new_set_module(PyTypeObject *type) r = PyDict_GetItemRef(globals, &_Py_ID(__name__), &module); if (module) { r = PyDict_SetItem(dict, &_Py_ID(__module__), module); + Py_DECREF(module); } return r; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 2408884cff8393..c2d30a22db9df3 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -648,7 +648,7 @@ dummy_func( _PyErr_SetKeyError(sub); } DECREF_INPUTS(); - ERROR_IF(rc <= 0, error); + ERROR_IF(rc <= 0, error); // not found or error } inst(BINARY_SUBSCR_GETITEM, (unused/1, container, sub -- unused)) { From de4794cb243d7e54c9b84c8a6666ddb48408538f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 8 Nov 2023 09:20:34 +0200 Subject: [PATCH 4/6] Fix a leak. --- Modules/_sqlite/microprotocols.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index d6405433502d69..f77458d94a8573 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -86,6 +86,7 @@ pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj, return NULL; } if (PyDict_GetItemRef(state->psyco_adapters, key, &adapter) < 0) { + Py_DECREF(key); return NULL; } Py_DECREF(key); From 046072456177228589dcbd64fbc95c072434aec7 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 13 Nov 2023 15:41:20 +0200 Subject: [PATCH 5/6] "found or error". --- Modules/_ctypes/_ctypes.c | 2 +- Modules/_ctypes/callproc.c | 2 +- Modules/_elementtree.c | 2 +- Modules/_threadmodule.c | 2 +- Objects/object.c | 2 +- Objects/typeobject.c | 2 +- Python/import.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 550107953cc028..f909a9496b6526 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4862,7 +4862,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) PyObject *result; if (_PyDict_GetItemProxy(cache, key, &result) != 0) { - // error or found + // found or error Py_DECREF(key); return result; } diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 4693ab1b7d5fac..3b11cd7f58ce4b 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1922,7 +1922,7 @@ create_pointer_type(PyObject *module, PyObject *cls) PyObject *key; if (PyDict_GetItemRef(_ctypes_ptrtype_cache, cls, &result) != 0) { - // error or found + // found or error return result; } // not found diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index ff343a83fb1aed..5d02946d23ef5f 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1423,7 +1423,7 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, PyObject *attrib = Py_NewRef(self->extra->attrib); PyObject *value; if (PyDict_GetItemRef(attrib, key, &value) != 0) { - // error or found + // found or error Py_DECREF(attrib); return value; } diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 882d18880d6199..fc4b0fc4aa8bc4 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1120,7 +1120,7 @@ local_getattro(localobject *self, PyObject *name) /* Optimization: just look in dict ourselves */ PyObject *value; if (PyDict_GetItemRef(ldict, name, &value) != 0) { - // error or found + // found or error return value; } diff --git a/Objects/object.c b/Objects/object.c index 16ad0e72eb106d..5632a331422609 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1491,7 +1491,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) if (dict != NULL) { Py_INCREF(dict); if (PyDict_GetItemRef(dict, name, method) != 0) { - // error or found + // found or error Py_DECREF(dict); Py_XDECREF(descr); return 0; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f82329c5fe7939..86fd168d0b873d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -10247,7 +10247,7 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject * assert(dict != NULL && PyDict_Check(dict)); if (PyDict_GetItemRef(dict, name, &res) != 0) { - // error or found + // found or error Py_DECREF(mro); return res; } diff --git a/Python/import.c b/Python/import.c index b1eefc1a617b47..12f586abc2eed8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2373,7 +2373,7 @@ get_path_importer(PyThreadState *tstate, PyObject *path_importer_cache, return NULL; /* Shouldn't happen */ if (PyDict_GetItemRef(path_importer_cache, p, &importer) != 0) { - // error or found + // found or error return importer; } // not found From e47bc0da08070d132287da3fe0b8e919131a22a6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 14 Nov 2023 13:46:48 +0200 Subject: [PATCH 6/6] Exclude Python/bytecodes.c. --- Python/bytecodes.c | 63 +++++++++++++++++++++++++++---------- Python/executor_cases.c.h | 64 ++++++++++++++++++++++++++++---------- Python/generated_cases.c.h | 64 ++++++++++++++++++++++++++++---------- 3 files changed, 140 insertions(+), 51 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index bb8123ee0bdfe3..d914f27ba9dcf0 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -643,12 +643,16 @@ dummy_func( inst(BINARY_SUBSCR_DICT, (unused/1, dict, sub -- res)) { DEOPT_IF(!PyDict_CheckExact(dict)); STAT_INC(BINARY_SUBSCR, hit); - int rc = PyDict_GetItemRef(dict, sub, &res); - if (rc == 0) { - _PyErr_SetKeyError(sub); + res = PyDict_GetItemWithError(dict, sub); + if (res == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetKeyError(sub); + } + DECREF_INPUTS(); + ERROR_IF(true, error); } + Py_INCREF(res); // Do this before DECREF'ing dict, sub DECREF_INPUTS(); - ERROR_IF(rc <= 0, error); // not found or error } inst(BINARY_SUBSCR_GETITEM, (unused/1, container, sub -- unused)) { @@ -1345,10 +1349,14 @@ dummy_func( GOTO_ERROR(error); } if (v == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { GOTO_ERROR(error); } - if (v == NULL) { + else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1375,10 +1383,14 @@ dummy_func( GOTO_ERROR(error); } if (v == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { GOTO_ERROR(error); } - if (v == NULL) { + else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1651,17 +1663,34 @@ dummy_func( ERROR_IF(true, error); } /* check if __annotations__ in locals()... */ - ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - ERROR_IF(ann_dict == NULL, error); - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - ERROR_IF(err, error); + if (PyDict_CheckExact(LOCALS())) { + ann_dict = _PyDict_GetItemWithError(LOCALS(), + &_Py_ID(__annotations__)); + if (ann_dict == NULL) { + ERROR_IF(_PyErr_Occurred(tstate), error); + /* ...if not, create a new one */ + ann_dict = PyDict_New(); + ERROR_IF(ann_dict == NULL, error); + err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + ERROR_IF(err, error); + } } else { - Py_DECREF(ann_dict); + /* do the same if locals() is not a dict */ + ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + ERROR_IF(ann_dict == NULL, error); + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + ERROR_IF(err, error); + } + else { + Py_DECREF(ann_dict); + } } } diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index ac542a562ea6ca..877328a4ab67ab 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -512,13 +512,18 @@ dict = stack_pointer[-2]; DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); - int rc = PyDict_GetItemRef(dict, sub, &res); - if (rc == 0) { - _PyErr_SetKeyError(sub); + res = PyDict_GetItemWithError(dict, sub); + if (res == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetKeyError(sub); + } + Py_DECREF(dict); + Py_DECREF(sub); + if (true) goto pop_2_error_tier_two; } + Py_INCREF(res); // Do this before DECREF'ing dict, sub Py_DECREF(dict); Py_DECREF(sub); - if (rc <= 0) goto pop_2_error_tier_two; STACK_SHRINK(1); stack_pointer[-1] = res; break; @@ -1017,10 +1022,14 @@ GOTO_ERROR(error); } if (v == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { GOTO_ERROR(error); } - if (v == NULL) { + else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1050,10 +1059,14 @@ GOTO_ERROR(error); } if (v == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { GOTO_ERROR(error); } - if (v == NULL) { + else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1391,17 +1404,34 @@ if (true) goto error_tier_two; } /* check if __annotations__ in locals()... */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error_tier_two; - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error_tier_two; - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error_tier_two; + if (PyDict_CheckExact(LOCALS())) { + ann_dict = _PyDict_GetItemWithError(LOCALS(), + &_Py_ID(__annotations__)); + if (ann_dict == NULL) { + if (_PyErr_Occurred(tstate)) goto error_tier_two; + /* ...if not, create a new one */ + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error_tier_two; + err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error_tier_two; + } } else { - Py_DECREF(ann_dict); + /* do the same if locals() is not a dict */ + if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error_tier_two; + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error_tier_two; + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error_tier_two; + } + else { + Py_DECREF(ann_dict); + } } break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 6cbc54c8e6201e..b9a2b2275491e7 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -896,13 +896,18 @@ dict = stack_pointer[-2]; DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); - int rc = PyDict_GetItemRef(dict, sub, &res); - if (rc == 0) { - _PyErr_SetKeyError(sub); + res = PyDict_GetItemWithError(dict, sub); + if (res == NULL) { + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetKeyError(sub); + } + Py_DECREF(dict); + Py_DECREF(sub); + if (true) goto pop_2_error; } + Py_INCREF(res); // Do this before DECREF'ing dict, sub Py_DECREF(dict); Py_DECREF(sub); - if (rc <= 0) goto pop_2_error; STACK_SHRINK(1); stack_pointer[-1] = res; DISPATCH(); @@ -1945,10 +1950,14 @@ GOTO_ERROR(error); } if (v == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { GOTO_ERROR(error); } - if (v == NULL) { + else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -1981,10 +1990,14 @@ GOTO_ERROR(error); } if (v == NULL) { - if (PyDict_GetItemRef(GLOBALS(), name, &v) < 0) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { GOTO_ERROR(error); } - if (v == NULL) { + else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { GOTO_ERROR(error); } @@ -2409,17 +2422,34 @@ if (true) goto error; } /* check if __annotations__ in locals()... */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; - if (ann_dict == NULL) { - ann_dict = PyDict_New(); - if (ann_dict == NULL) goto error; - err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), - ann_dict); - Py_DECREF(ann_dict); - if (err) goto error; + if (PyDict_CheckExact(LOCALS())) { + ann_dict = _PyDict_GetItemWithError(LOCALS(), + &_Py_ID(__annotations__)); + if (ann_dict == NULL) { + if (_PyErr_Occurred(tstate)) goto error; + /* ...if not, create a new one */ + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error; + err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error; + } } else { - Py_DECREF(ann_dict); + /* do the same if locals() is not a dict */ + if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; + if (ann_dict == NULL) { + ann_dict = PyDict_New(); + if (ann_dict == NULL) goto error; + err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), + ann_dict); + Py_DECREF(ann_dict); + if (err) goto error; + } + else { + Py_DECREF(ann_dict); + } } DISPATCH(); }