From 11c3096c5a3ed04bd5256217127aaa8547daeecb Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 23 Jun 2023 20:10:32 +0300 Subject: [PATCH] [3.11] gh-106033: Get rid of new occurrences of PyDict_GetItem and PyObject_HasAttr (GH-106034) These functions are broken by design because they discard any exceptions raised inside, including MemoryError and KeyboardInterrupt. They should not be used in new code.. (cherry picked from commit 1d33d5378058671bfabb6f4d4b5bfd4726973ff9) Co-authored-by: Serhiy Storchaka --- Modules/_hashopenssl.c | 13 +++++++------ Objects/exceptions.c | 31 +++++++++++++++---------------- Python/pythonrun.c | 12 +++++------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 4123c0c6907bc1..57d64bd80c9727 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -384,14 +384,15 @@ py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type } else { _hashlibstate *state = get_hashlib_state(module); // borrowed ref - name_obj = PyDict_GetItem(state->constructs, digestmod); + name_obj = PyDict_GetItemWithError(state->constructs, digestmod); } if (name_obj == NULL) { - _hashlibstate *state = get_hashlib_state(module); - PyErr_Clear(); - PyErr_Format( - state->unsupported_digestmod_error, - "Unsupported digestmod %R", digestmod); + if (!PyErr_Occurred()) { + _hashlibstate *state = get_hashlib_state(module); + PyErr_Format( + state->unsupported_digestmod_error, + "Unsupported digestmod %R", digestmod); + } return NULL; } diff --git a/Objects/exceptions.c b/Objects/exceptions.c index a95b75205b8749..86cabbf3f17f7a 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -210,22 +210,21 @@ BaseException_add_note(PyObject *self, PyObject *note) return NULL; } - if (!PyObject_HasAttr(self, &_Py_ID(__notes__))) { - PyObject *new_notes = PyList_New(0); - if (new_notes == NULL) { + PyObject *notes; + if (_PyObject_LookupAttr(self, &_Py_ID(__notes__), ¬es) < 0) { + return NULL; + } + if (notes == NULL) { + notes = PyList_New(0); + if (notes == NULL) { return NULL; } - if (PyObject_SetAttr(self, &_Py_ID(__notes__), new_notes) < 0) { - Py_DECREF(new_notes); + if (PyObject_SetAttr(self, &_Py_ID(__notes__), notes) < 0) { + Py_DECREF(notes); return NULL; } - Py_DECREF(new_notes); } - PyObject *notes = PyObject_GetAttr(self, &_Py_ID(__notes__)); - if (notes == NULL) { - return NULL; - } - if (!PyList_Check(notes)) { + else if (!PyList_Check(notes)) { Py_DECREF(notes); PyErr_SetString(PyExc_TypeError, "Cannot add note: __notes__ is not a list"); return NULL; @@ -943,11 +942,11 @@ exceptiongroup_subset( PyException_SetContext(eg, PyException_GetContext(orig)); PyException_SetCause(eg, PyException_GetCause(orig)); - if (PyObject_HasAttr(orig, &_Py_ID(__notes__))) { - PyObject *notes = PyObject_GetAttr(orig, &_Py_ID(__notes__)); - if (notes == NULL) { - goto error; - } + PyObject *notes; + if (_PyObject_LookupAttr(orig, &_Py_ID(__notes__), ¬es) < 0) { + goto error; + } + if (notes) { if (PySequence_Check(notes)) { /* Make a copy so the parts have independent notes lists. */ PyObject *notes_copy = PySequence_List(notes); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index efa22b07256c82..03e366a8d095dd 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1138,15 +1138,13 @@ print_exception_notes(struct exception_print_context *ctx, PyObject *value) return 0; } - if (!PyObject_HasAttr(value, &_Py_ID(__notes__))) { - return 0; - } - PyObject *notes = PyObject_GetAttr(value, &_Py_ID(__notes__)); - if (notes == NULL) { - return -1; + PyObject *notes; + int res = _PyObject_LookupAttr(value, &_Py_ID(__notes__), ¬es); + if (res <= 0) { + return res; } if (!PySequence_Check(notes)) { - int res = 0; + res = 0; if (write_indented_margin(ctx, f) < 0) { res = -1; }