gh-112723: Call PyThreadState_Clear() from the correct interpreter (#112776)

The `PyThreadState_Clear()` function must only be called with the GIL
held and must be called from the same interpreter as the passed in
thread state. Otherwise, any Python objects on the thread state may be
destroyed using the wrong interpreter, leading to memory corruption.

This is also important for `Py_GIL_DISABLED` builds because free lists
will be associated with PyThreadStates and cleared in
`PyThreadState_Clear()`.

This fixes two places that called `PyThreadState_Clear()` from the wrong
interpreter and adds an assertion to `PyThreadState_Clear()`.
This commit is contained in:
Sam Gross
2023-12-12 19:20:21 -05:00
committed by GitHub
parent 8a4c1f3ff1
commit a3c031884d
6 changed files with 34 additions and 55 deletions

View File

@@ -1454,6 +1454,7 @@ void
PyThreadState_Clear(PyThreadState *tstate)
{
assert(tstate->_status.initialized && !tstate->_status.cleared);
assert(current_fast_get(&_PyRuntime)->interp == tstate->interp);
// XXX assert(!tstate->_status.bound || tstate->_status.unbound);
tstate->_status.finalizing = 1; // just in case
@@ -2150,7 +2151,7 @@ _PyGILState_Fini(PyInterpreterState *interp)
// XXX Drop this.
PyStatus
void
_PyGILState_SetTstate(PyThreadState *tstate)
{
/* must init with valid states */
@@ -2160,7 +2161,7 @@ _PyGILState_SetTstate(PyThreadState *tstate)
if (!_Py_IsMainInterpreter(tstate->interp)) {
/* Currently, PyGILState is shared by all interpreters. The main
* interpreter is responsible to initialize it. */
return _PyStatus_OK();
return;
}
#ifndef NDEBUG
@@ -2170,8 +2171,6 @@ _PyGILState_SetTstate(PyThreadState *tstate)
assert(gilstate_tss_get(runtime) == tstate);
assert(tstate->gilstate_counter == 1);
#endif
return _PyStatus_OK();
}
PyInterpreterState *