bpo-40887: Don't use finalized free lists (GH-20700)

In debug mode, ensure that free lists are no longer used after being
finalized. Set numfree to -1 in finalization functions
(eg. _PyList_Fini()), and then check that numfree is not equal to -1
before using a free list (e.g list_dealloc()).
This commit is contained in:
Victor Stinner 2020-06-08 02:14:47 +02:00 committed by GitHub
parent c96a61e816
commit bcb198385d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 3 deletions

View file

@ -111,6 +111,10 @@ void
_PyList_Fini(PyThreadState *tstate)
{
_PyList_ClearFreeList(tstate);
#ifdef Py_DEBUG
struct _Py_list_state *state = &tstate->interp->list;
state->numfree = -1;
#endif
}
/* Print summary info about the state of the optimized allocator */
@ -135,6 +139,10 @@ PyList_New(Py_ssize_t size)
PyInterpreterState *interp = _PyInterpreterState_GET();
struct _Py_list_state *state = &interp->list;
PyListObject *op;
#ifdef Py_DEBUG
// PyList_New() must not be called after _PyList_Fini()
assert(state->numfree != -1);
#endif
if (state->numfree) {
state->numfree--;
op = state->free_list[state->numfree];
@ -330,6 +338,10 @@ list_dealloc(PyListObject *op)
}
PyInterpreterState *interp = _PyInterpreterState_GET();
struct _Py_list_state *state = &interp->list;
#ifdef Py_DEBUG
// list_dealloc() must not be called after _PyList_Fini()
assert(state->numfree != -1);
#endif
if (state->numfree < PyList_MAXFREELIST && PyList_CheckExact(op)) {
state->free_list[state->numfree++] = op;
}