From 4c77e8bf0e9aad8d8b6df268d6b361eeadfaa606 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 24 Sep 2017 21:08:27 +0300 Subject: [PATCH 1/5] bpo-31572: Get rid of PyObject_HasAttrString() in ctypes. --- Modules/_ctypes/stgdict.c | 68 ++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index b66c6ecd2f3240..ea787d2ee56320 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -340,8 +340,9 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct Py_ssize_t union_size, total_align; Py_ssize_t field_size = 0; int bitofs; - PyObject *isPacked; - int pack = 0; + PyObject *tmp; + int isPacked; + int pack; Py_ssize_t ffi_ofs; int big_endian; @@ -356,32 +357,61 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct if (fields == NULL) return 0; -#ifdef WORDS_BIGENDIAN - big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1; -#else - big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0; -#endif + tmp = PyObject_GetAttrString(type, "_swappedbytes_"); + if (tmp) { + Py_DECREF(tmp); + big_endian = !PY_BIG_ENDIAN; + } + else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + big_endian = PY_BIG_ENDIAN; + } + else { + return -1; + } - use_broken_old_ctypes_semantics = \ - PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_"); + tmp = PyObject_GetAttrString(type, "_use_broken_old_ctypes_structure_semantics_"); + if (tmp) { + Py_DECREF(tmp); + use_broken_old_ctypes_semantics = 1; + } + else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + use_broken_old_ctypes_semantics = 0; + } + else { + return -1; + } - isPacked = PyObject_GetAttrString(type, "_pack_"); - if (isPacked) { - pack = _PyLong_AsInt(isPacked); - if (pack < 0 || PyErr_Occurred()) { - Py_XDECREF(isPacked); + tmp = PyObject_GetAttrString(type, "_pack_"); + if (tmp) { + isPacked = 1; + pack = _PyLong_AsInt(tmp); + Py_DECREF(tmp); + if (pack < 0 && (!PyErr_Occurred() || + PyErr_ExceptionMatches(PyExc_TypeError) || + PyErr_ExceptionMatches(PyExc_OverflowError))) + { PyErr_SetString(PyExc_ValueError, "_pack_ must be a non-negative integer"); return -1; } - Py_DECREF(isPacked); - } else + } + else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); + isPacked = 0; + pack = 0; + } + else { + return -1; + } - len = PySequence_Length(fields); + len = PySequence_Size(fields); if (len == -1) { - PyErr_SetString(PyExc_TypeError, - "'_fields_' must be a sequence of pairs"); + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + PyErr_SetString(PyExc_TypeError, + "'_fields_' must be a sequence of pairs"); + } return -1; } From ed1fb01a8aeede9844591d1fdf60b7a41918410f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 11 Nov 2017 17:03:47 +0200 Subject: [PATCH 2/5] Fix error handling for _pack_. --- Modules/_ctypes/stgdict.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 012f500d20cf50..c105b9b8e1b4c3 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -388,12 +388,14 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct isPacked = 1; pack = _PyLong_AsInt(tmp); Py_DECREF(tmp); - if (pack < 0 && (!PyErr_Occurred() || - PyErr_ExceptionMatches(PyExc_TypeError) || - PyErr_ExceptionMatches(PyExc_OverflowError))) - { - PyErr_SetString(PyExc_ValueError, - "_pack_ must be a non-negative integer"); + if (pack < 0) { + if (!PyErr_Occurred() || + PyErr_ExceptionMatches(PyExc_TypeError) || + PyErr_ExceptionMatches(PyExc_OverflowError)) + { + PyErr_SetString(PyExc_ValueError, + "_pack_ must be a non-negative integer"); + } return -1; } } From 70d31babe370b88a5c528e0b612d676291275757 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 11 Nov 2017 18:23:53 +0200 Subject: [PATCH 3/5] Don't silence errors when look up in a dict. --- Modules/_ctypes/_ctypes.c | 158 ++++++++++++++++++++++++------------ Modules/_ctypes/callbacks.c | 7 +- Modules/_ctypes/callproc.c | 22 +++-- Modules/_ctypes/cfield.c | 2 +- 4 files changed, 131 insertions(+), 58 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 4440ab0d69ce6a..3aea3a1c0140b8 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -236,7 +236,7 @@ PyObject * PyDict_GetItemProxy(PyObject *dict, PyObject *key) { PyObject *result; - PyObject *item = PyDict_GetItem(dict, key); + PyObject *item = PyDict_GetItemWithError(dict, key); if (item == NULL) return NULL; @@ -426,6 +426,8 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt PyTypeObject *result; PyObject *fields; StgDictObject *dict; + _Py_IDENTIFIER(_abstract_); + _Py_IDENTIFIER(_fields_); /* create the new instance (which is a class, since we are a metatype!) */ @@ -434,8 +436,12 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt return NULL; /* keep this for bw compatibility */ - if (PyDict_GetItemString(result->tp_dict, "_abstract_")) + if (_PyDict_GetItemIdWithError(result->tp_dict, &PyId__abstract_)) return (PyObject *)result; + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } dict = (StgDictObject *)_PyObject_CallNoArg((PyObject *)&PyCStgDict_Type); if (!dict) { @@ -458,8 +464,21 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt dict->paramfunc = StructUnionType_paramfunc; - fields = PyDict_GetItemString((PyObject *)dict, "_fields_"); - if (!fields) { + fields = _PyDict_GetItemIdWithError((PyObject *)dict, &PyId__fields_); + if (fields) { + if (-1 == PyObject_SetAttr((PyObject *)result, + _PyUnicode_FromId(&PyId__fields_), fields)) + { + Py_DECREF(result); + return NULL; + } + return (PyObject *)result; + } + else if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + else { StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base); if (basedict == NULL) @@ -473,12 +492,6 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt basedict->flags |= DICTFLAG_FINAL; /* set the 'final' flag in the baseclass dict */ return (PyObject *)result; } - - if (-1 == PyObject_SetAttrString((PyObject *)result, "_fields_", fields)) { - Py_DECREF(result); - return NULL; - } - return (PyObject *)result; } static PyObject * @@ -961,6 +974,7 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) StgDictObject *stgdict; PyObject *proto; PyObject *typedict; + _Py_IDENTIFIER(_type_); typedict = PyTuple_GetItem(args, 2); if (!typedict) @@ -980,15 +994,15 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict->paramfunc = PyCPointerType_paramfunc; stgdict->flags |= TYPEFLAG_ISPOINTER; - proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */ - if (proto && -1 == PyCPointerType_SetProto(stgdict, proto)) { - Py_DECREF((PyObject *)stgdict); - return NULL; - } - + proto = _PyDict_GetItemIdWithError(typedict, &PyId__type_); /* Borrowed ref */ if (proto) { - StgDictObject *itemdict = PyType_stgdict(proto); + StgDictObject *itemdict; const char *current_format; + if (-1 == PyCPointerType_SetProto(stgdict, proto)) { + Py_DECREF((PyObject *)stgdict); + return NULL; + } + itemdict = PyType_stgdict(proto); /* PyCPointerType_SetProto has verified proto has a stgdict. */ assert(itemdict); /* If itemdict->format is NULL, then this is a pointer to an @@ -1009,6 +1023,10 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 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!) */ @@ -1034,6 +1052,7 @@ static PyObject * PyCPointerType_set_type(PyTypeObject *self, PyObject *type) { StgDictObject *dict; + _Py_IDENTIFIER(_type_); dict = PyType_stgdict((PyObject *)self); if (!dict) { @@ -1045,7 +1064,7 @@ PyCPointerType_set_type(PyTypeObject *self, PyObject *type) if (-1 == PyCPointerType_SetProto(dict, type)) return NULL; - if (-1 == PyDict_SetItemString((PyObject *)dict, "_type_", type)) + if (-1 == _PyDict_SetItemId((PyObject *)dict, &PyId__type_, type)) return NULL; Py_RETURN_NONE; @@ -2278,6 +2297,10 @@ make_funcptrtype_dict(StgDictObject *stgdict) { PyObject *ob; PyObject *converters = NULL; + _Py_IDENTIFIER(_flags_); + _Py_IDENTIFIER(_argtypes_); + _Py_IDENTIFIER(_restype_); + _Py_IDENTIFIER(_check_retval_); stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment; stgdict->length = 1; @@ -2286,26 +2309,31 @@ make_funcptrtype_dict(StgDictObject *stgdict) stgdict->getfunc = NULL; stgdict->ffi_type_pointer = ffi_type_pointer; - ob = PyDict_GetItemString((PyObject *)stgdict, "_flags_"); + ob = _PyDict_GetItemIdWithError((PyObject *)stgdict, &PyId__flags_); if (!ob || !PyLong_Check(ob)) { - PyErr_SetString(PyExc_TypeError, - "class must define _flags_ which must be an integer"); + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "class must define _flags_ which must be an integer"); + } return -1; } - stgdict->flags = PyLong_AS_LONG(ob) | TYPEFLAG_ISPOINTER; + stgdict->flags = PyLong_AsUnsignedLongMask(ob) | TYPEFLAG_ISPOINTER; /* _argtypes_ is optional... */ - ob = PyDict_GetItemString((PyObject *)stgdict, "_argtypes_"); + ob = _PyDict_GetItemIdWithError((PyObject *)stgdict, &PyId__argtypes_); if (ob) { converters = converters_from_argtypes(ob); if (!converters) - goto error; + return -1; Py_INCREF(ob); stgdict->argtypes = ob; stgdict->converters = converters; } + else if (PyErr_Occurred()) { + return -1; + } - ob = PyDict_GetItemString((PyObject *)stgdict, "_restype_"); + ob = _PyDict_GetItemIdWithError((PyObject *)stgdict, &PyId__restype_); if (ob) { if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { PyErr_SetString(PyExc_TypeError, @@ -2314,12 +2342,19 @@ make_funcptrtype_dict(StgDictObject *stgdict) } Py_INCREF(ob); stgdict->restype = ob; - stgdict->checker = PyObject_GetAttrString(ob, "_check_retval_"); - if (stgdict->checker == NULL) + stgdict->checker = _PyObject_GetAttrId(ob, &PyId__check_retval_); + if (stgdict->checker == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + return -1; + } PyErr_Clear(); + } + } + else if (PyErr_Occurred()) { + return -1; } /* XXX later, maybe. - ob = PyDict_GetItemString((PyObject *)stgdict, "_errcheck_"); + ob = _PyDict_GetItemIdWithError((PyObject *)stgdict, &PyId__errcheck_); if (ob) { if (!PyCallable_Check(ob)) { PyErr_SetString(PyExc_TypeError, @@ -2329,13 +2364,11 @@ make_funcptrtype_dict(StgDictObject *stgdict) Py_INCREF(ob); stgdict->errcheck = ob; } + else if (PyErr_Occurred()) { + return -1; + } */ return 0; - - error: - Py_XDECREF(converters); - return -1; - } static PyCArgObject * @@ -3511,9 +3544,12 @@ PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) like that. */ /* - if (kwds && PyDict_GetItemString(kwds, "options")) { + if (kwds && _PyDict_GetItemIdWithError(kwds, &PyId_options)) { ... } + else if (PyErr_Occurred()) { + return NULL; + } */ dict = PyType_stgdict((PyObject *)type); @@ -3590,10 +3626,16 @@ _get_arg(int *pindex, PyObject *name, PyObject *defval, PyObject *inargs, PyObje Py_INCREF(v); return v; } - if (kwds && name && (v = PyDict_GetItem(kwds, name))) { - ++*pindex; - Py_INCREF(v); - return v; + if (kwds && name) { + v = PyDict_GetItemWithError(kwds, name); + if (v) { + ++*pindex; + Py_INCREF(v); + return v; + } + else if (PyErr_Occurred()) { + return NULL; + } } if (defval) { Py_INCREF(defval); @@ -3670,7 +3712,7 @@ _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes, for (i = 0; i < len; ++i) { PyObject *item = PyTuple_GET_ITEM(paramflags, i); PyObject *ob; - int flag; + unsigned int flag; PyObject *name = NULL; PyObject *defval = NULL; @@ -3678,7 +3720,7 @@ _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes, calls below. */ /* We HAVE already checked that the tuple can be parsed with "i|ZO", so... */ Py_ssize_t tsize = PyTuple_GET_SIZE(item); - flag = PyLong_AS_LONG(PyTuple_GET_ITEM(item, 0)); + flag = PyLong_AsUnsignedLongMask(PyTuple_GET_ITEM(item, 0)); name = tsize > 1 ? PyTuple_GET_ITEM(item, 1) : NULL; defval = tsize > 2 ? PyTuple_GET_ITEM(item, 2) : NULL; @@ -3758,7 +3800,7 @@ _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes, break; default: PyErr_Format(PyExc_ValueError, - "paramflag %d not yet implemented", flag); + "paramflag %u not yet implemented", flag); goto error; break; } @@ -4121,6 +4163,7 @@ _init_pos_args(PyObject *self, PyTypeObject *type, StgDictObject *dict; PyObject *fields; Py_ssize_t i; + _Py_IDENTIFIER(_fields_); if (PyType_stgdict((PyObject *)type->tp_base)) { index = _init_pos_args(self, type->tp_base, @@ -4131,9 +4174,13 @@ _init_pos_args(PyObject *self, PyTypeObject *type, } dict = PyType_stgdict((PyObject *)type); - fields = PyDict_GetItemString((PyObject *)dict, "_fields_"); - if (fields == NULL) + fields = _PyDict_GetItemIdWithError((PyObject *)dict, &PyId__fields_); + if (fields == NULL) { + if (PyErr_Occurred()) { + return -1; + } return index; + } for (i = 0; i < dict->length && (i+index) < PyTuple_GET_SIZE(args); @@ -4149,13 +4196,20 @@ _init_pos_args(PyObject *self, PyTypeObject *type, return -1; } val = PyTuple_GET_ITEM(args, i + index); - if (kwds && PyDict_GetItem(kwds, name)) { - PyErr_Format(PyExc_TypeError, - "duplicate values for field %R", - name); - Py_DECREF(pair); - Py_DECREF(name); - return -1; + if (kwds) { + if (PyDict_GetItemWithError(kwds, name)) { + PyErr_Format(PyExc_TypeError, + "duplicate values for field %R", + name); + Py_DECREF(pair); + Py_DECREF(name); + return -1; + } + else if (PyErr_Occurred()) { + Py_DECREF(pair); + Py_DECREF(name); + return -1; + } } res = PyObject_SetAttr(self, name, val); @@ -4626,6 +4680,10 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) Py_DECREF(key); return result; } + else if (PyErr_Occurred()) { + Py_DECREF(key); + return NULL; + } if (!PyType_Check(itemtype)) { PyErr_SetString(PyExc_TypeError, diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index d579291b62fea6..871bc4f4945809 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -107,9 +107,14 @@ static void TryAddRef(StgDictObject *dict, CDataObject *obj) { IUnknown *punk; + _Py_IDENTIFIER(_needs_com_addref_); - if (NULL == PyDict_GetItemString((PyObject *)dict, "_needs_com_addref_")) + if (!_PyDict_GetItemIdWithError((PyObject *)dict, &PyId__needs_com_addref_)) { + if (PyErr_Occurred()) { + PrintError("getting _needs_com_addref_"); + } return; + } punk = *(IUnknown **)obj->b_ptr; if (punk) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index bdc372811598e5..06a4e334861767 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -142,7 +142,7 @@ _ctypes_get_errobj(int **pspace) if (error_object_name == NULL) return NULL; } - errobj = PyDict_GetItem(dict, error_object_name); + errobj = PyDict_GetItemWithError(dict, error_object_name); if (errobj) { if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_NAME_PYMEM)) { PyErr_SetString(PyExc_RuntimeError, @@ -151,7 +151,7 @@ _ctypes_get_errobj(int **pspace) } Py_INCREF(errobj); } - else { + else if (!PyErr_Occurred()) { void *space = PyMem_Malloc(sizeof(int) * 2); if (space == NULL) return NULL; @@ -167,6 +167,9 @@ _ctypes_get_errobj(int **pspace) return NULL; } } + else { + return NULL; + } *pspace = (int *)PyCapsule_GetPointer(errobj, CTYPES_CAPSULE_NAME_PYMEM); return errobj; } @@ -1674,11 +1677,14 @@ POINTER(PyObject *self, PyObject *cls) PyObject *key; char *buf; - result = PyDict_GetItem(_ctypes_ptrtype_cache, cls); + result = PyDict_GetItemWithError(_ctypes_ptrtype_cache, cls); if (result) { Py_INCREF(result); return result; } + else if (PyErr_Occurred()) { + return NULL; + } if (PyUnicode_CheckExact(cls)) { const char *name = PyUnicode_AsUTF8(cls); if (name == NULL) @@ -1734,12 +1740,16 @@ pointer(PyObject *self, PyObject *arg) PyObject *result; PyObject *typ; - typ = PyDict_GetItem(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg)); - if (typ) + typ = PyDict_GetItemWithError(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg)); + if (typ) { return PyObject_CallFunctionObjArgs(typ, arg, NULL); + } + else if (PyErr_Occurred()) { + return NULL; + } typ = POINTER(NULL, (PyObject *)Py_TYPE(arg)); if (typ == NULL) - return NULL; + return NULL; result = PyObject_CallFunctionObjArgs(typ, arg, NULL); Py_DECREF(typ); return result; diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index e2b9aa8ed153c5..5f194e21550f7b 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1147,7 +1147,7 @@ c_set(void *ptr, PyObject *value, Py_ssize_t size) } if (PyLong_Check(value)) { - long longval = PyLong_AS_LONG(value); + long longval = PyLong_AsLong(value); if (longval < 0 || longval >= 256) goto error; *(char *)ptr = (char)longval; From e10a467028361a71ff0b06fff86217cc42ae4fb6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 1 Feb 2018 19:52:58 +0200 Subject: [PATCH 4/5] Use _PyObject_LookupAttrId(). --- Modules/_ctypes/_ctypes.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c9d9d7a35b3fec..2237800994af70 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -2342,12 +2342,10 @@ make_funcptrtype_dict(StgDictObject *stgdict) } Py_INCREF(ob); stgdict->restype = ob; - stgdict->checker = _PyObject_GetAttrId(ob, &PyId__check_retval_); - if (stgdict->checker == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - return -1; - } - PyErr_Clear(); + if (_PyObject_LookupAttrId(ob, &PyId__check_retval_, + &stgdict->checker) < 0) + { + return -1; } } else if (PyErr_Occurred()) { From d7bb65a508bce788c83133dd718787135a7c58aa Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 7 Feb 2018 13:37:32 +0200 Subject: [PATCH 5/5] More changes. --- Lib/ctypes/test/test_arrays.py | 2 +- Modules/_ctypes/_ctypes.c | 96 +++++++++++++++++++++++----------- Modules/_ctypes/callproc.c | 5 +- Modules/_ctypes/stgdict.c | 37 ++++++------- 4 files changed, 89 insertions(+), 51 deletions(-) diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index 4ed566b48e67e8..669647f3f194d8 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -176,7 +176,7 @@ class T(Array): class T(Array): _type_ = c_int _length_ = sys.maxsize * 2 - with self.assertRaises(AttributeError): + with self.assertRaises(TypeError): class T(Array): _type_ = c_int _length_ = 1.87 diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2237800994af70..6132cb090b7377 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -466,9 +466,7 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt fields = _PyDict_GetItemIdWithError((PyObject *)dict, &PyId__fields_); if (fields) { - if (-1 == PyObject_SetAttr((PyObject *)result, - _PyUnicode_FromId(&PyId__fields_), fields)) - { + if (_PyObject_SetAttrId((PyObject *)result, &PyId__fields_, fields) < 0) { Py_DECREF(result); return NULL; } @@ -706,6 +704,7 @@ static const char from_param_doc[] = static PyObject * CDataType_from_param(PyObject *type, PyObject *value) { + _Py_IDENTIFIER(_as_parameter_); PyObject *as_parameter; int res = PyObject_IsInstance(value, type); if (res == -1) @@ -739,7 +738,9 @@ CDataType_from_param(PyObject *type, PyObject *value) return NULL; } - as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); + if (_PyObject_LookupAttrId(value, &PyId__as_parameter_, &as_parameter) < 0) { + return NULL; + } if (as_parameter) { value = CDataType_from_param(type, as_parameter); Py_DECREF(as_parameter); @@ -1405,6 +1406,8 @@ PyCArrayType_paramfunc(CDataObject *self) static PyObject * PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + _Py_IDENTIFIER(_length_); + _Py_IDENTIFIER(_type_); PyTypeObject *result; StgDictObject *stgdict; StgDictObject *itemdict; @@ -1424,12 +1427,18 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict = NULL; type_attr = NULL; - length_attr = PyObject_GetAttrString((PyObject *)result, "_length_"); - if (!length_attr || !PyLong_Check(length_attr)) { + if (_PyObject_LookupAttrId((PyObject *)result, &PyId__length_, &length_attr) < 0) { + goto error; + } + if (!length_attr) { PyErr_SetString(PyExc_AttributeError, - "class must define a '_length_' attribute, " - "which must be a positive integer"); - Py_XDECREF(length_attr); + "class must define a '_length_' attribute"); + goto error; + } + if (!PyLong_Check(length_attr)) { + PyErr_SetString(PyExc_TypeError, + "The '_length_' attribute must be a positive integer"); + Py_DECREF(length_attr); goto error; } length = PyLong_AsLongAndOverflow(length_attr, &overflow); @@ -1441,7 +1450,9 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } Py_DECREF(length_attr); - type_attr = PyObject_GetAttrString((PyObject *)result, "_type_"); + if (_PyObject_LookupAttrId((PyObject *)result, &PyId__type_, &type_attr) < 0) { + goto error; + } if (!type_attr) { PyErr_SetString(PyExc_AttributeError, "class must define a '_type_' attribute"); @@ -1584,6 +1595,7 @@ static const char SIMPLE_TYPE_CHARS[] = "cbBhHiIlLdfuzZqQPXOv?g"; static PyObject * c_wchar_p_from_param(PyObject *type, PyObject *value) { + _Py_IDENTIFIER(_as_parameter_); PyObject *as_parameter; int res; if (value == Py_None) { @@ -1633,7 +1645,9 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) } } - as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); + if (_PyObject_LookupAttrId(value, &PyId__as_parameter_, &as_parameter) < 0) { + return NULL; + } if (as_parameter) { value = c_wchar_p_from_param(type, as_parameter); Py_DECREF(as_parameter); @@ -1648,6 +1662,7 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) static PyObject * c_char_p_from_param(PyObject *type, PyObject *value) { + _Py_IDENTIFIER(_as_parameter_); PyObject *as_parameter; int res; if (value == Py_None) { @@ -1697,7 +1712,9 @@ c_char_p_from_param(PyObject *type, PyObject *value) } } - as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); + if (_PyObject_LookupAttrId(value, &PyId__as_parameter_, &as_parameter) < 0) { + return NULL; + } if (as_parameter) { value = c_char_p_from_param(type, as_parameter); Py_DECREF(as_parameter); @@ -1712,6 +1729,7 @@ c_char_p_from_param(PyObject *type, PyObject *value) static PyObject * c_void_p_from_param(PyObject *type, PyObject *value) { + _Py_IDENTIFIER(_as_parameter_); StgDictObject *stgd; PyObject *as_parameter; int res; @@ -1833,7 +1851,9 @@ c_void_p_from_param(PyObject *type, PyObject *value) } } - as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); + if (_PyObject_LookupAttrId(value, &PyId__as_parameter_, &as_parameter) < 0) { + return NULL; + } if (as_parameter) { value = c_void_p_from_param(type, as_parameter); Py_DECREF(as_parameter); @@ -1950,6 +1970,7 @@ PyCSimpleType_paramfunc(CDataObject *self) static PyObject * PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + _Py_IDENTIFIER(_type_); PyTypeObject *result; StgDictObject *stgdict; PyObject *proto; @@ -1964,13 +1985,15 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (result == NULL) return NULL; - proto = PyObject_GetAttrString((PyObject *)result, "_type_"); /* new ref */ + if (_PyObject_LookupAttrId((PyObject *)result, &PyId__type_, &proto) < 0) { + return NULL; + } if (!proto) { PyErr_SetString(PyExc_AttributeError, "class must define a '_type_' attribute"); error: Py_XDECREF(proto); - Py_XDECREF(result); + Py_DECREF(result); return NULL; } if (PyUnicode_Check(proto)) { @@ -2132,6 +2155,7 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject * PyCSimpleType_from_param(PyObject *type, PyObject *value) { + _Py_IDENTIFIER(_as_parameter_); StgDictObject *dict; const char *fmt; PyCArgObject *parg; @@ -2175,7 +2199,9 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) PyErr_Clear(); Py_DECREF(parg); - as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); + if (_PyObject_LookupAttrId(value, &PyId__as_parameter_, &as_parameter) < 0) { + return NULL; + } if (as_parameter) { if (Py_EnterRecursiveCall("while processing _as_parameter_")) { Py_DECREF(as_parameter); @@ -2250,6 +2276,7 @@ PyTypeObject PyCSimpleType_Type = { static PyObject * converters_from_argtypes(PyObject *ob) { + _Py_IDENTIFIER(from_param); PyObject *converters; Py_ssize_t i; Py_ssize_t nArgs; @@ -2274,22 +2301,22 @@ converters_from_argtypes(PyObject *ob) */ for (i = 0; i < nArgs; ++i) { + PyObject *cnv; PyObject *tp = PyTuple_GET_ITEM(ob, i); - PyObject *cnv = PyObject_GetAttrString(tp, "from_param"); - if (!cnv) - goto argtypes_error_1; + if (_PyObject_LookupAttrId(tp, &PyId_from_param, &cnv) <= 0) { + Py_DECREF(converters); + Py_DECREF(ob); + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "item %zd in _argtypes_ has no from_param method", + i+1); + } + return NULL; + } PyTuple_SET_ITEM(converters, i, cnv); } Py_DECREF(ob); return converters; - - argtypes_error_1: - Py_XDECREF(converters); - Py_DECREF(ob); - PyErr_Format(PyExc_TypeError, - "item %zd in _argtypes_ has no from_param method", - i+1); - return NULL; } static int @@ -3101,9 +3128,13 @@ PyCFuncPtr_get_errcheck(PyCFuncPtrObject *self) static int PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob) { + _Py_IDENTIFIER(_check_retval_); + PyObject *checker, *oldchecker; if (ob == NULL) { + oldchecker = self->checker; + self->checker = NULL; Py_CLEAR(self->restype); - Py_CLEAR(self->checker); + Py_XDECREF(oldchecker); return 0; } if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { @@ -3111,11 +3142,14 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob) "restype must be a type, a callable, or None"); return -1; } + if (_PyObject_LookupAttrId(ob, &PyId__check_retval_, &checker) < 0) { + return -1; + } + oldchecker = self->checker; + self->checker = checker; Py_INCREF(ob); Py_XSETREF(self->restype, ob); - Py_XSETREF(self->checker, PyObject_GetAttrString(ob, "_check_retval_")); - if (self->checker == NULL) - PyErr_Clear(); + Py_XDECREF(oldchecker); return 0; } diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 06a4e334861767..a901c7e8eee824 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -684,8 +684,11 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) #endif { + _Py_IDENTIFIER(_as_parameter_); PyObject *arg; - arg = PyObject_GetAttrString(obj, "_as_parameter_"); + if (_PyObject_LookupAttrId(obj, &PyId__as_parameter_, &arg) < 0) { + return -1; + } /* Which types should we exactly allow here? integers are required for using Python classes as parameters (they have to expose the '_as_parameter_' diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index c105b9b8e1b4c3..3f8a0316616bf3 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -281,13 +281,15 @@ MakeFields(PyObject *type, CFieldObject *descr, static int MakeAnonFields(PyObject *type) { + _Py_IDENTIFIER(_anonymous_); PyObject *anon; PyObject *anon_names; Py_ssize_t i; - anon = PyObject_GetAttrString(type, "_anonymous_"); + if (_PyObject_LookupAttrId(type, &PyId__anonymous_, &anon) < 0) { + return -1; + } if (anon == NULL) { - PyErr_Clear(); return 0; } anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence"); @@ -335,6 +337,9 @@ MakeAnonFields(PyObject *type) int PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct) { + _Py_IDENTIFIER(_swappedbytes_); + _Py_IDENTIFIER(_use_broken_old_ctypes_structure_semantics_); + _Py_IDENTIFIER(_pack_); StgDictObject *stgdict, *basedict; Py_ssize_t len, offset, size, align, i; Py_ssize_t union_size, total_align; @@ -357,33 +362,33 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct if (fields == NULL) return 0; - tmp = PyObject_GetAttrString(type, "_swappedbytes_"); + if (_PyObject_LookupAttrId(type, &PyId__swappedbytes_, &tmp) < 0) { + return -1; + } if (tmp) { Py_DECREF(tmp); big_endian = !PY_BIG_ENDIAN; } - else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); + else { big_endian = PY_BIG_ENDIAN; } - else { + + if (_PyObject_LookupAttrId(type, + &PyId__use_broken_old_ctypes_structure_semantics_, &tmp) < 0) + { return -1; } - - tmp = PyObject_GetAttrString(type, "_use_broken_old_ctypes_structure_semantics_"); if (tmp) { Py_DECREF(tmp); use_broken_old_ctypes_semantics = 1; } - else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); + else { use_broken_old_ctypes_semantics = 0; } - else { + + if (_PyObject_LookupAttrId(type, &PyId__pack_, &tmp) < 0) { return -1; } - - tmp = PyObject_GetAttrString(type, "_pack_"); if (tmp) { isPacked = 1; pack = _PyLong_AsInt(tmp); @@ -399,14 +404,10 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct return -1; } } - else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); + else { isPacked = 0; pack = 0; } - else { - return -1; - } len = PySequence_Size(fields); if (len == -1) {