Bug report
PoC
from concurrent import interpreters
interp = interpreters.create()
mv = memoryview(bytearray(b"A" * 64))
interp.prepare_main(mv=mv)
interp.exec("""
b = bytes(mv.obj) # 2nd buffer export: no INCREF -> premature free
churn = [object() for _ in range(2000)]
mv.release() # PyBuffer_Release decrefs freed wrapper
print("unreachable")
""")
print("done")
Output
$ python3 -X faulthandler main.py
Fatal Python error: Segmentation fault
Current thread 0x00007fd6126e6740 [python3.15] (most recent call first):
File "<script>", line 4 in <module>
Current thread's C stack trace (most recent call first):
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _Py_DumpStack+0x30 [0x4f0b80]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x59968b]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x5995de]
Binary file "/lib/x86_64-linux-gnu/libc.so.6", at +0x3c050 [0x7fd612425050]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at PyBuffer_Release+0x27 [0x1a27733]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1b32a4b]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a2d33f]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a72484]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at PyEval_EvalCode+0xa6 [0x1a72182]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x51b289]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1e9a943]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x51b592]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x51a959]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at PyObject_Vectorcall+0x4c [0x1a1c3a4]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _Py_VectorCallInstrumentation_StackRefSteal+0xca [0x1b23ade]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a406c2]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a72484]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at PyEval_EvalCode+0xa6 [0x1a72182]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1ac87bb]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1c7184d]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1c71767]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1c712c6]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1c6fc45]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at Py_RunMain+0x422 [0x1b8d062]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1b8cc1d]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1b8ca6e]
Binary file "/lib/x86_64-linux-gnu/libc.so.6", at +0x2724a [0x7fd61241024a]
Binary file "/lib/x86_64-linux-gnu/libc.so.6", at __libc_start_main+0x85 [0x7fd612410305]
Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _start+0x29 [0x1be5437]
Root Cause
Modules/_interpretersmodule.c:199-211: view->obj = op; at :207 with no incref, violating the buffer-protocol contract stated at Objects/memoryobject.c:64-66 ("all getbufferprocs return a new reference to view.obj"); the module compensates only for its single internal consumer (_memoryview_from_xid :237-263)
The wrapper escapes to Python as mv.obj; any second PyObject_GetBuffer on it (bytes(mv.obj), memoryview(mv.obj), any buffer-consuming extension) gets view->obj = op again without incref, that consumer's PyBuffer_Release drops the wrapper to 0 which leads to premature dealloc while the cross-interpreter memoryview still holds the dangling view->obj.
Versions affected
Python 3.14+
CPython versions tested on:
3.15
Operating systems tested on:
Linux
Bug report
PoC
Output
Root Cause
Modules/_interpretersmodule.c:199-211:view->obj = op;at :207 with no incref, violating the buffer-protocol contract stated atObjects/memoryobject.c:64-66("all getbufferprocs return a new reference to view.obj"); the module compensates only for its single internal consumer (_memoryview_from_xid:237-263)The wrapper escapes to Python as
mv.obj; any secondPyObject_GetBufferon it (bytes(mv.obj),memoryview(mv.obj), any buffer-consuming extension) getsview->obj = opagain without incref, that consumer'sPyBuffer_Releasedrops the wrapper to 0 which leads to premature dealloc while the cross-interpreter memoryview still holds the danglingview->obj.Versions affected
Python 3.14+
CPython versions tested on:
3.15
Operating systems tested on:
Linux