mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
bpo-37994: Fix silencing all errors if an attribute lookup fails. (GH-15630)
Only AttributeError should be silenced.
This commit is contained in:
parent
f02ea6225b
commit
41c57b3353
14 changed files with 134 additions and 127 deletions
|
|
@ -1551,17 +1551,10 @@ tail_contains(PyObject *tuple, int whence, PyObject *o)
|
|||
static PyObject *
|
||||
class_name(PyObject *cls)
|
||||
{
|
||||
PyObject *name = _PyObject_GetAttrId(cls, &PyId___name__);
|
||||
if (name == NULL) {
|
||||
PyErr_Clear();
|
||||
PyObject *name;
|
||||
if (_PyObject_LookupAttrId(cls, &PyId___name__, &name) == 0) {
|
||||
name = PyObject_Repr(cls);
|
||||
}
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
if (!PyUnicode_Check(name)) {
|
||||
Py_DECREF(name);
|
||||
return NULL;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
|
@ -1579,13 +1572,15 @@ check_duplicates(PyObject *tuple)
|
|||
if (PyTuple_GET_ITEM(tuple, j) == o) {
|
||||
o = class_name(o);
|
||||
if (o != NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"duplicate base class %U",
|
||||
o);
|
||||
if (PyUnicode_Check(o)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"duplicate base class %U", o);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"duplicate base class");
|
||||
}
|
||||
Py_DECREF(o);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"duplicate base class");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1629,13 +1624,20 @@ consistent method resolution\norder (MRO) for bases");
|
|||
i = 0;
|
||||
while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) {
|
||||
PyObject *name = class_name(k);
|
||||
const char *name_str;
|
||||
const char *name_str = NULL;
|
||||
if (name != NULL) {
|
||||
name_str = PyUnicode_AsUTF8(name);
|
||||
if (name_str == NULL)
|
||||
if (PyUnicode_Check(name)) {
|
||||
name_str = PyUnicode_AsUTF8(name);
|
||||
}
|
||||
else {
|
||||
name_str = "?";
|
||||
} else
|
||||
name_str = "?";
|
||||
}
|
||||
}
|
||||
if (name_str == NULL) {
|
||||
Py_XDECREF(name);
|
||||
Py_DECREF(set);
|
||||
return;
|
||||
}
|
||||
off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s", name_str);
|
||||
Py_XDECREF(name);
|
||||
if (--n && (size_t)(off+1) < sizeof(buf)) {
|
||||
|
|
@ -3422,10 +3424,10 @@ merge_class_dict(PyObject *dict, PyObject *aclass)
|
|||
assert(aclass);
|
||||
|
||||
/* Merge in the type's dict (if any). */
|
||||
classdict = _PyObject_GetAttrId(aclass, &PyId___dict__);
|
||||
if (classdict == NULL)
|
||||
PyErr_Clear();
|
||||
else {
|
||||
if (_PyObject_LookupAttrId(aclass, &PyId___dict__, &classdict) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (classdict != NULL) {
|
||||
int status = PyDict_Update(dict, classdict);
|
||||
Py_DECREF(classdict);
|
||||
if (status < 0)
|
||||
|
|
@ -3433,15 +3435,17 @@ merge_class_dict(PyObject *dict, PyObject *aclass)
|
|||
}
|
||||
|
||||
/* Recursively merge in the base types' (if any) dicts. */
|
||||
bases = _PyObject_GetAttrId(aclass, &PyId___bases__);
|
||||
if (bases == NULL)
|
||||
PyErr_Clear();
|
||||
else {
|
||||
if (_PyObject_LookupAttrId(aclass, &PyId___bases__, &bases) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (bases != NULL) {
|
||||
/* We have no guarantee that bases is a real tuple */
|
||||
Py_ssize_t i, n;
|
||||
n = PySequence_Size(bases); /* This better be right */
|
||||
if (n < 0)
|
||||
PyErr_Clear();
|
||||
if (n < 0) {
|
||||
Py_DECREF(bases);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < n; i++) {
|
||||
int status;
|
||||
|
|
@ -4730,9 +4734,10 @@ object___dir___impl(PyObject *self)
|
|||
PyObject *itsclass = NULL;
|
||||
|
||||
/* Get __dict__ (which may or may not be a real dict...) */
|
||||
dict = _PyObject_GetAttrId(self, &PyId___dict__);
|
||||
if (_PyObject_LookupAttrId(self, &PyId___dict__, &dict) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (dict == NULL) {
|
||||
PyErr_Clear();
|
||||
dict = PyDict_New();
|
||||
}
|
||||
else if (!PyDict_Check(dict)) {
|
||||
|
|
@ -4750,12 +4755,12 @@ object___dir___impl(PyObject *self)
|
|||
goto error;
|
||||
|
||||
/* Merge in attrs reachable from its class. */
|
||||
itsclass = _PyObject_GetAttrId(self, &PyId___class__);
|
||||
if (itsclass == NULL)
|
||||
/* XXX(tomer): Perhaps fall back to obj->ob_type if no
|
||||
__class__ exists? */
|
||||
PyErr_Clear();
|
||||
else if (merge_class_dict(dict, itsclass) != 0)
|
||||
if (_PyObject_LookupAttrId(self, &PyId___class__, &itsclass) < 0) {
|
||||
goto error;
|
||||
}
|
||||
/* XXX(tomer): Perhaps fall back to obj->ob_type if no
|
||||
__class__ exists? */
|
||||
if (itsclass != NULL && merge_class_dict(dict, itsclass) < 0)
|
||||
goto error;
|
||||
|
||||
result = PyDict_Keys(dict);
|
||||
|
|
@ -6111,16 +6116,19 @@ method_is_overloaded(PyObject *left, PyObject *right, struct _Py_Identifier *nam
|
|||
PyObject *a, *b;
|
||||
int ok;
|
||||
|
||||
b = _PyObject_GetAttrId((PyObject *)(Py_TYPE(right)), name);
|
||||
if (_PyObject_LookupAttrId((PyObject *)(Py_TYPE(right)), name, &b) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (b == NULL) {
|
||||
PyErr_Clear();
|
||||
/* If right doesn't have it, it's not overloaded */
|
||||
return 0;
|
||||
}
|
||||
|
||||
a = _PyObject_GetAttrId((PyObject *)(Py_TYPE(left)), name);
|
||||
if (_PyObject_LookupAttrId((PyObject *)(Py_TYPE(left)), name, &a) < 0) {
|
||||
Py_DECREF(b);
|
||||
return -1;
|
||||
}
|
||||
if (a == NULL) {
|
||||
PyErr_Clear();
|
||||
Py_DECREF(b);
|
||||
/* If right has it but left doesn't, it's overloaded */
|
||||
return 1;
|
||||
|
|
@ -6129,11 +6137,6 @@ method_is_overloaded(PyObject *left, PyObject *right, struct _Py_Identifier *nam
|
|||
ok = PyObject_RichCompareBool(a, b, Py_NE);
|
||||
Py_DECREF(a);
|
||||
Py_DECREF(b);
|
||||
if (ok < 0) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
@ -6151,16 +6154,20 @@ FUNCNAME(PyObject *self, PyObject *other) \
|
|||
if (Py_TYPE(self)->tp_as_number != NULL && \
|
||||
Py_TYPE(self)->tp_as_number->SLOTNAME == TESTFUNC) { \
|
||||
PyObject *r; \
|
||||
if (do_other && \
|
||||
PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self)) && \
|
||||
method_is_overloaded(self, other, &rop_id)) { \
|
||||
stack[0] = other; \
|
||||
stack[1] = self; \
|
||||
r = vectorcall_maybe(&rop_id, stack, 2); \
|
||||
if (r != Py_NotImplemented) \
|
||||
return r; \
|
||||
Py_DECREF(r); \
|
||||
do_other = 0; \
|
||||
if (do_other && PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) { \
|
||||
int ok = method_is_overloaded(self, other, &rop_id); \
|
||||
if (ok < 0) { \
|
||||
return NULL; \
|
||||
} \
|
||||
if (ok) { \
|
||||
stack[0] = other; \
|
||||
stack[1] = self; \
|
||||
r = vectorcall_maybe(&rop_id, stack, 2); \
|
||||
if (r != Py_NotImplemented) \
|
||||
return r; \
|
||||
Py_DECREF(r); \
|
||||
do_other = 0; \
|
||||
} \
|
||||
} \
|
||||
stack[0] = self; \
|
||||
stack[1] = other; \
|
||||
|
|
@ -7753,7 +7760,9 @@ supercheck(PyTypeObject *type, PyObject *obj)
|
|||
/* Try the slow way */
|
||||
PyObject *class_attr;
|
||||
|
||||
class_attr = _PyObject_GetAttrId(obj, &PyId___class__);
|
||||
if (_PyObject_LookupAttrId(obj, &PyId___class__, &class_attr) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (class_attr != NULL &&
|
||||
PyType_Check(class_attr) &&
|
||||
(PyTypeObject *)class_attr != Py_TYPE(obj))
|
||||
|
|
@ -7763,11 +7772,7 @@ supercheck(PyTypeObject *type, PyObject *obj)
|
|||
if (ok)
|
||||
return (PyTypeObject *)class_attr;
|
||||
}
|
||||
|
||||
if (class_attr == NULL)
|
||||
PyErr_Clear();
|
||||
else
|
||||
Py_DECREF(class_attr);
|
||||
Py_XDECREF(class_attr);
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue