[3.14] gh-146480: Override the exception in _PyErr_SetKeyError() (GH-146486) (#146511)

gh-146480: Override the exception in _PyErr_SetKeyError() (GH-146486)

If _PyErr_SetKeyError() is called with an exception set, it now
replaces the current exception with KeyError (as expected), instead
of setting a SystemError or failing with a fatal error (in debug
mode).
(cherry picked from commit d4153a9f76)

Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Miss Islington (bot) 2026-03-27 12:48:29 +01:00 committed by GitHub
parent cba54979df
commit d7e04e7b8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 4 deletions

View file

@ -247,13 +247,23 @@ PyErr_SetObject(PyObject *exception, PyObject *value)
_PyErr_SetObject(tstate, exception, value);
}
/* Set a key error with the specified argument, wrapping it in a
* tuple automatically so that tuple keys are not unpacked as the
* exception arguments. */
/* Set a key error with the specified argument. This function should be used to
* raise a KeyError with an argument instead of PyErr_SetObject(PyExc_KeyError,
* arg) which has a special behavior. PyErr_SetObject() unpacks arg if it's a
* tuple, and it uses arg instead of creating a new exception if arg is an
* exception.
*
* If an exception is already set, override the exception. */
void
_PyErr_SetKeyError(PyObject *arg)
{
PyThreadState *tstate = _PyThreadState_GET();
// PyObject_CallOneArg() must not be called with an exception set,
// otherwise _Py_CheckFunctionResult() can fail if the function returned
// a result with an excception set.
_PyErr_Clear(tstate);
PyObject *exc = PyObject_CallOneArg(PyExc_KeyError, arg);
if (!exc) {
/* caller will expect error to be set anyway */