diff options
author | Pablo Galindo Salgado <Pablogsal@gmail.com> | 2022-03-07 12:23:11 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-07 12:23:11 (GMT) |
commit | 3b3be05a164da43f201e35b6dafbc840993a4d18 (patch) | |
tree | 4880ca6ce2434a95973e2e35c323074d932851c9 /Objects/object.c | |
parent | 5c06dba21b9767127f042b8a168703f06338c3f4 (diff) | |
download | cpython-3b3be05a164da43f201e35b6dafbc840993a4d18.zip cpython-3b3be05a164da43f201e35b6dafbc840993a4d18.tar.gz cpython-3b3be05a164da43f201e35b6dafbc840993a4d18.tar.bz2 |
bpo-46940: Don't override existing AttributeError suggestion information (GH-31710)
When an exception is created in a nested call to PyObject_GetAttr, any
external calls will override the context information of the
AttributeError that we have already placed in the most internal call.
This will cause the suggestions we create to nor work properly as the
attribute name and object that we will be using are the incorrect ones.
To avoid this, we need to check first if these attributes are already
set and bail out if that's the case.
Diffstat (limited to 'Objects/object.c')
-rw-r--r-- | Objects/object.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/Objects/object.c b/Objects/object.c index 38919ff..f029a72 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -875,19 +875,29 @@ static inline int set_attribute_error_context(PyObject* v, PyObject* name) { assert(PyErr_Occurred()); - // Intercept AttributeError exceptions and augment them to offer - // suggestions later. - if (PyErr_ExceptionMatches(PyExc_AttributeError)){ - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - PyErr_NormalizeException(&type, &value, &traceback); - if (PyErr_GivenExceptionMatches(value, PyExc_AttributeError) && - (PyObject_SetAttr(value, &_Py_ID(name), name) || - PyObject_SetAttr(value, &_Py_ID(obj), v))) { - return 1; - } - PyErr_Restore(type, value, traceback); + if (!PyErr_ExceptionMatches(PyExc_AttributeError)){ + return 0; + } + // Intercept AttributeError exceptions and augment them to offer suggestions later. + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + // Check if the normalized exception is indeed an AttributeError + if (!PyErr_GivenExceptionMatches(value, PyExc_AttributeError)) { + goto restore; + } + PyAttributeErrorObject* the_exc = (PyAttributeErrorObject*) value; + // Check if this exception was already augmented + if (the_exc->name || the_exc->obj) { + goto restore; + } + // Augment the exception with the name and object + if (PyObject_SetAttr(value, &_Py_ID(name), name) || + PyObject_SetAttr(value, &_Py_ID(obj), v)) { + return 1; } +restore: + PyErr_Restore(type, value, traceback); return 0; } |