diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-20.gh-issue-146102.1yR78A.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-20.gh-issue-146102.1yR78A.rst new file mode 100644 index 000000000000000..4a5e3e734d41fab --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-20.gh-issue-146102.1yR78A.rst @@ -0,0 +1 @@ +Fixed a use-after-free in _ensure_notshareableerror and an exception leak in _PyXI_UnwrapNotShareableError and a use-after-free in _get_xidata within the cross-interpreter data subsystem. diff --git a/Python/crossinterp.c b/Python/crossinterp.c index ed77c1be646e275..6541119b36eee83 100644 --- a/Python/crossinterp.c +++ b/Python/crossinterp.c @@ -491,24 +491,24 @@ _get_xidata(PyThreadState *tstate, Py_DECREF(obj); return -1; } - // Fall back to obj - Py_DECREF(obj); if (!_PyErr_Occurred(tstate)) { _set_xid_lookup_failure(tstate, obj, NULL, NULL); } + Py_DECREF(obj); return -1; } int res = getdata.basic != NULL ? getdata.basic(tstate, obj, xidata) : getdata.fallback(tstate, obj, fallback, xidata); - Py_DECREF(obj); if (res != 0) { PyObject *cause = _PyErr_GetRaisedException(tstate); assert(cause != NULL); _set_xid_lookup_failure(tstate, obj, NULL, cause); Py_XDECREF(cause); + Py_DECREF(obj); return -1; } + Py_DECREF(obj); // Fill in the blanks and validate the result. _PyXIData_INTERPID(xidata) = PyInterpreterState_GetID(interp); diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h index 54422ad2335cb62..3975d1d6dc2e083 100644 --- a/Python/crossinterp_data_lookup.h +++ b/Python/crossinterp_data_lookup.h @@ -100,6 +100,7 @@ _PyXI_UnwrapNotShareableError(PyThreadState * tstate, _PyXI_failure *failure) if (failure != NULL) { _PyXI_errcode code = _PyXI_ERR_NOT_SHAREABLE; if (_PyXI_InitFailure(failure, code, exc) < 0) { + _PyErr_SetRaisedException(tstate, exc); return -1; } } diff --git a/Python/crossinterp_exceptions.h b/Python/crossinterp_exceptions.h index 98411adc5eb3f6f..0d144ffdaf4f5b5 100644 --- a/Python/crossinterp_exceptions.h +++ b/Python/crossinterp_exceptions.h @@ -83,6 +83,7 @@ _ensure_notshareableerror(PyThreadState *tstate, // A NotShareableError instance is already set. assert(cause == NULL); _PyErr_SetRaisedException(tstate, ctx); + return; } } else {