diff options
author | Victor Stinner <vstinner@python.org> | 2020-06-08 00:14:47 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-08 00:14:47 (GMT) |
commit | bcb198385dee469d630a184182df9dc1463e2c47 (patch) | |
tree | 193bc5c3584732b506223a34f3215a03fd1be408 /Objects/genobject.c | |
parent | c96a61e8163c2d25ed4ac77cf96201fd0bdb945c (diff) | |
download | cpython-bcb198385dee469d630a184182df9dc1463e2c47.zip cpython-bcb198385dee469d630a184182df9dc1463e2c47.tar.gz cpython-bcb198385dee469d630a184182df9dc1463e2c47.tar.bz2 |
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()).
Diffstat (limited to 'Objects/genobject.c')
-rw-r--r-- | Objects/genobject.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/Objects/genobject.c b/Objects/genobject.c index f7dbfd7..4207d532 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1430,6 +1430,11 @@ void _PyAsyncGen_Fini(PyThreadState *tstate) { _PyAsyncGen_ClearFreeLists(tstate); +#ifdef Py_DEBUG + struct _Py_async_gen_state *state = &tstate->interp->async_gen; + state->value_numfree = -1; + state->asend_numfree = -1; +#endif } @@ -1474,6 +1479,10 @@ async_gen_asend_dealloc(PyAsyncGenASend *o) Py_CLEAR(o->ags_sendval); PyInterpreterState *interp = _PyInterpreterState_GET(); struct _Py_async_gen_state *state = &interp->async_gen; +#ifdef Py_DEBUG + // async_gen_asend_dealloc() must not be called after _PyAsyncGen_Fini() + assert(state->asend_numfree != -1); +#endif if (state->asend_numfree < _PyAsyncGen_MAXFREELIST) { assert(PyAsyncGenASend_CheckExact(o)); state->asend_freelist[state->asend_numfree++] = o; @@ -1632,6 +1641,10 @@ async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval) PyAsyncGenASend *o; PyInterpreterState *interp = _PyInterpreterState_GET(); struct _Py_async_gen_state *state = &interp->async_gen; +#ifdef Py_DEBUG + // async_gen_asend_new() must not be called after _PyAsyncGen_Fini() + assert(state->asend_numfree != -1); +#endif if (state->asend_numfree) { state->asend_numfree--; o = state->asend_freelist[state->asend_numfree]; @@ -1667,6 +1680,10 @@ async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o) Py_CLEAR(o->agw_val); PyInterpreterState *interp = _PyInterpreterState_GET(); struct _Py_async_gen_state *state = &interp->async_gen; +#ifdef Py_DEBUG + // async_gen_wrapped_val_dealloc() must not be called after _PyAsyncGen_Fini() + assert(state->value_numfree != -1); +#endif if (state->value_numfree < _PyAsyncGen_MAXFREELIST) { assert(_PyAsyncGenWrappedValue_CheckExact(o)); state->value_freelist[state->value_numfree++] = o; @@ -1737,6 +1754,10 @@ _PyAsyncGenValueWrapperNew(PyObject *val) PyInterpreterState *interp = _PyInterpreterState_GET(); struct _Py_async_gen_state *state = &interp->async_gen; +#ifdef Py_DEBUG + // _PyAsyncGenValueWrapperNew() must not be called after _PyAsyncGen_Fini() + assert(state->value_numfree != -1); +#endif if (state->value_numfree) { state->value_numfree--; o = state->value_freelist[state->value_numfree]; |