[New-bugs-announce] [issue39358] test_code.CoExtra leads to double-free when ce_size >1
Sergei Lebedev
report at bugs.python.org
Thu Jan 16 06:58:29 EST 2020
New submission from Sergei Lebedev <slebedev at google.com>:
tl;dr Passing a Python function as a freefunc to _PyEval_RequestCodeExtraIndex leads to double-free. In general, I think that freefunc should not be allowed to call other Python functions.
---
test_code.CoExtra registers a new co_extra slot with a ctypes-wrapped freefunc
# All defined in globals().
LAST_FREED = None
def myfree(ptr):
global LAST_FREED
LAST_FREED = ptr
FREE_FUNC = freefunc(myfree)
FREE_INDEX = RequestCodeExtraIndex(FREE_FUNC)
Imagine that we have registered another co_extra slot FOO_INDEX of type Foo and a freefunc FreeFoo. Furthermore, assume that
* FOO_INDEX < FREE_INDEX
* FOO_INDEX is set on any executed code object including myfree.
Consider what happens when we collect the globals() of the test_code module. myfree is referenced by globals() and FREE_FUNC. If FREE_FUNC is DECREF'd first, then by the time we get to myfree it has a refcount of 1 and DECREF'ing it leads to a code_dealloc call. Recall that the code object corresponding to myfree has two co_extra slots:
* FOO_INDEX pointing to some Foo*, and
* FREE_INDEX with a value of NULL.
So, code_dealloc will first call FreeFoo (because FOO_INDEX < FREE_INDEX) and then the ctypes wrapper of myfree. The following sequence of calls looks roughly like this
_CallPythonObject
...
PyEval_EvalCodeEx
_PyEval_EvalCodeWithName
frame_dealloc
code_dealloc # !
The argument of the last code_dealloc call is *the same* myfree code object (!). This means that code_dealloc will attempt to call FreeFoo on an already free'd pointer leading to a crash.
----------
components: Tests
messages: 360117
nosy: slebedev
priority: normal
severity: normal
status: open
title: test_code.CoExtra leads to double-free when ce_size >1
type: crash
versions: Python 3.6, Python 3.7, Python 3.8, Python 3.9
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue39358>
_______________________________________
More information about the New-bugs-announce
mailing list