[Python-checkins] bpo-32787: Better error handling in ctypes. (#3727)

Serhiy Storchaka webhook-mailer at python.org
Wed Dec 5 09:44:19 EST 2018


https://github.com/python/cpython/commit/398bd27967690f2c1a8cbf8d47a5613edd9cfb2a
commit: 398bd27967690f2c1a8cbf8d47a5613edd9cfb2a
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-12-05T16:44:14+02:00
summary:

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.

files:
M Modules/_ctypes/_ctypes.c
M Modules/_ctypes/callbacks.c
M Modules/_ctypes/callproc.c
M Modules/_ctypes/cfield.c
M Modules/_ctypes/stgdict.c

diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 36ef5d9b67fc..3debe3ace695 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 d579291b62fe..871bc4f49458 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 ad40ca1c5247..1185c9156ae9 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 e2b9aa8ed153..5f194e21550f 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 25656ff87875..3f8a0316616b 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;
     }
 



More information about the Python-checkins mailing list