From 398bd27967690f2c1a8cbf8d47a5613edd9cfb2a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 5 Dec 2018 16:44:14 +0200 Subject: [PATCH] bpo-32787: Better error handling in ctypes. (#3727) * bpo-31572: Get rid of PyObject_HasAttrString() in ctypes. * Fix error handling for _pack_. * Don't silence errors when look up in a dict. * Use _PyObject_LookupAttrId(). * More changes. --- Modules/_ctypes/_ctypes.c | 242 ++++++++++++++++++++++++------------ Modules/_ctypes/callbacks.c | 7 +- Modules/_ctypes/callproc.c | 27 ++-- Modules/_ctypes/cfield.c | 2 +- Modules/_ctypes/stgdict.c | 81 ++++++++---- 5 files changed, 247 insertions(+), 112 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 36ef5d9b67fc21..3debe3ace6958c 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,19 @@ 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 (_PyObject_SetAttrId((PyObject *)result, &PyId__fields_, fields) < 0) { + 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 +490,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 * @@ -693,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) @@ -726,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); @@ -961,6 +975,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 +995,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 +1024,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 +1053,7 @@ static PyObject * PyCPointerType_set_type(PyTypeObject *self, PyObject *type) { StgDictObject *dict; + _Py_IDENTIFIER(_type_); dict = PyType_stgdict((PyObject *)self); if (!dict) { @@ -1045,7 +1065,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; @@ -1386,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; @@ -1404,12 +1426,12 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) stgdict = NULL; type_attr = NULL; - length_attr = PyObject_GetAttrString((PyObject *)result, "_length_"); + if (_PyObject_LookupAttrId((PyObject *)result, &PyId__length_, &length_attr) < 0) { + goto error; + } if (!length_attr) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_SetString(PyExc_AttributeError, - "class must define a '_length_' attribute"); - } + PyErr_SetString(PyExc_AttributeError, + "class must define a '_length_' attribute"); goto error; } @@ -1437,7 +1459,9 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) goto error; } - 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"); @@ -1580,6 +1604,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) { @@ -1629,7 +1654,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); @@ -1644,6 +1671,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) { @@ -1693,7 +1721,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); @@ -1708,6 +1738,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; @@ -1829,7 +1860,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); @@ -1946,6 +1979,7 @@ PyCSimpleType_paramfunc(CDataObject *self) static PyObject * PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + _Py_IDENTIFIER(_type_); PyTypeObject *result; StgDictObject *stgdict; PyObject *proto; @@ -1960,13 +1994,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)) { @@ -2128,6 +2164,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; @@ -2171,7 +2208,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); @@ -2246,6 +2285,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; @@ -2270,22 +2310,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 @@ -2293,6 +2333,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; @@ -2301,26 +2345,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, @@ -2329,12 +2378,17 @@ make_funcptrtype_dict(StgDictObject *stgdict) } Py_INCREF(ob); stgdict->restype = ob; - stgdict->checker = PyObject_GetAttrString(ob, "_check_retval_"); - if (stgdict->checker == NULL) - PyErr_Clear(); + if (_PyObject_LookupAttrId(ob, &PyId__check_retval_, + &stgdict->checker) < 0) + { + return -1; + } + } + 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, @@ -2344,13 +2398,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 * @@ -3085,9 +3137,13 @@ PyCFuncPtr_get_errcheck(PyCFuncPtrObject *self, void *Py_UNUSED(ignored)) static int PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ignored)) { + _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)) { @@ -3095,11 +3151,14 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ign "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; } @@ -3526,9 +3585,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); @@ -3605,10 +3667,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); @@ -3685,7 +3753,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; @@ -3693,7 +3761,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; @@ -3773,7 +3841,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; } @@ -4136,6 +4204,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, @@ -4146,9 +4215,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); @@ -4164,13 +4237,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); @@ -4641,6 +4721,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 ad40ca1c524743..1185c9156ae992 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -146,7 +146,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, @@ -155,7 +155,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; @@ -171,6 +171,9 @@ _ctypes_get_errobj(int **pspace) return NULL; } } + else { + return NULL; + } *pspace = (int *)PyCapsule_GetPointer(errobj, CTYPES_CAPSULE_NAME_PYMEM); return errobj; } @@ -685,8 +688,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_' @@ -1685,11 +1691,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) @@ -1745,12 +1754,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; diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 25656ff878759c..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,13 +337,17 @@ 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; 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 +362,59 @@ 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 + if (_PyObject_LookupAttrId(type, &PyId__swappedbytes_, &tmp) < 0) { + return -1; + } + if (tmp) { + Py_DECREF(tmp); + big_endian = !PY_BIG_ENDIAN; + } + else { + big_endian = PY_BIG_ENDIAN; + } - use_broken_old_ctypes_semantics = \ - PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_"); + if (_PyObject_LookupAttrId(type, + &PyId__use_broken_old_ctypes_structure_semantics_, &tmp) < 0) + { + return -1; + } + if (tmp) { + Py_DECREF(tmp); + use_broken_old_ctypes_semantics = 1; + } + else { + use_broken_old_ctypes_semantics = 0; + } - isPacked = PyObject_GetAttrString(type, "_pack_"); - if (isPacked) { - pack = _PyLong_AsInt(isPacked); - if (pack < 0 || PyErr_Occurred()) { - Py_XDECREF(isPacked); - PyErr_SetString(PyExc_ValueError, - "_pack_ must be a non-negative integer"); + if (_PyObject_LookupAttrId(type, &PyId__pack_, &tmp) < 0) { + return -1; + } + if (tmp) { + isPacked = 1; + pack = _PyLong_AsInt(tmp); + Py_DECREF(tmp); + 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; } - Py_DECREF(isPacked); - } else - PyErr_Clear(); + } + else { + isPacked = 0; + pack = 0; + } - 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; }