Python 3.13 refcounting related memory corruption
Florian Bruhin
me at the-compiler.org
Tue May 28 13:34:05 BST 2024
Hey,
When running the qutebrowser testsuite with Python 3.13, I get a
segfault pointing to a memory corruption inside Python - including funny
exceptions such as:
TypeError: replace() argument 2 must be str, not +
when doing
value = value.replace('default_family', self.default_family)
and/or assertions about PyUnicode_KIND returning an invalid value.
I've reported it here:
https://github.com/python/cpython/issues/119462
and bisected it to a change in CPython, "Limit the number of versions
that a single class can use.":
https://github.com/python/cpython/pull/114900
Unfortunately I've not been able to extract a minimal example by any
means. The best I could get is getting it down to running 11 test files
in qutebrowser, with almost 2000 test cases. If I remove any of those
files, the bug doesn't trigger anymore.
I've now run it through valgrind/ASan, which report that a value
allocated by PyQt:
#0 0x5f1017de70a9 in malloc (/home/florian/proj/cpython/python+0x32f0a9) (BuildId: 472839294c0413d2f8beb5aa8c1f9ae1822dc88b)
#1 0x5f10184cd6c8 in tracemalloc_alloc /home/florian/proj/cpython/Python/tracemalloc.c:536:15
#2 0x5f10184cdc4d in tracemalloc_alloc_gil /home/florian/proj/cpython/Python/tracemalloc.c:640:11
#3 0x5f1018192780 in PyUnicode_New /home/florian/proj/cpython/Objects/unicodeobject.c:1238:24
#4 0x744327ffacf2 in sip_api_unicode_new /tmp/pip-install-y87d3n5v/pyqt6-sip_626af1e47840447c9f7c098c3c07b101/sip_core.c:11388:16
#5 0x744308e15146 in qpycore_PyObject_FromQString(QString const&) (/home/florian/proj/qutebrowser/git/.venv-py313dev/lib/python3.13/site-packages/PyQt6/QtCore.abi3.so+0x215146) (BuildId: 74342f967c05e7e19c5fd152ab11397679a17e61)
gets freed by Python:
#0 0x5f1017de6072 in free.part.0 asan_malloc_linux.cpp.o
#1 0x5f10184c84d7 in tracemalloc_free /home/florian/proj/cpython/Python/tracemalloc.c:614:5
#2 0x5f10180e82c7 in _Py_Dealloc /home/florian/proj/cpython/Objects/object.c:2875:5
#3 0x5f1018098ac3 in Py_DECREF /home/florian/proj/cpython/./Include/object.h:922:9
#4 0x5f1018098ac3 in Py_XDECREF /home/florian/proj/cpython/./Include/object.h:1030:9
#5 0x5f1018098ac3 in insertdict /home/florian/proj/cpython/Objects/dictobject.c:1311:5
#6 0x5f10180b135a in _PyObjectDict_SetItem /home/florian/proj/cpython/Objects/dictobject.c
#7 0x5f10180e5490 in _PyObject_GenericSetAttrWithDict /home/florian/proj/cpython/Objects/object.c:1730:19
#8 0x5f101814f877 in type_setattro /home/florian/proj/cpython/Objects/typeobject.c:4981:11
#9 0x5f10180e20ac in PyObject_SetAttr /home/florian/proj/cpython/Objects/object.c:1306:15
but then accessed by Python again:
#0 0x5f101832396c in Py_INCREF /home/florian/proj/cpython/./Include/object.h:812:30
#1 0x5f101832396c in _Py_NewRef /home/florian/proj/cpython/./Include/object.h:1046:5
#2 0x5f101832396c in _PyEval_EvalFrameDefault /home/florian/proj/cpython/Python/generated_cases.c.h:3795:24
#3 0x5f1017fe5a62 in _PyObject_VectorcallTstate /home/florian/proj/cpython/./Include/internal/pycore_call.h:168:11
#4 0x5f1018159a41 in call_attribute /home/florian/proj/cpython/Objects/typeobject.c:8874:15
#5 0x5f1018159a41 in _Py_slot_tp_getattr_hook /home/florian/proj/cpython/Objects/typeobject.c:8924:19
#6 0x5f10180e16a7 in PyObject_GetAttr /home/florian/proj/cpython/Objects/object.c:1153:18
#7 0x5f10182cdb21 in builtin_getattr /home/florian/proj/cpython/Python/bltinmodule.c:1179:18
#8 0x5f1018303e87 in _PyEval_EvalFrameDefault /home/florian/proj/cpython/Python/generated_cases.c.h:1072:19
#9 0x5f101803861c in _PyEval_EvalFrame /home/florian/proj/cpython/./Include/internal/pycore_ceval.h:115:16
#10 0x5f101803861c in gen_send_ex2 /home/florian/proj/cpython/Objects/genobject.c:228:24
#11 0x5f101803419a in gen_iternext /home/florian/proj/cpython/Objects/genobject.c:586:9
#12 0x5f1018061d35 in list_extend_iter /home/florian/proj/cpython/Objects/listobject.c:985:26
#13 0x5f1018061d35 in list_extend /home/florian/proj/cpython/Objects/listobject.c:1042:16
#14 0x5f1018061628 in _PyList_Extend /home/florian/proj/cpython/Objects/listobject.c:1050:9
#15 0x5f1017f9a856 in PySequence_List /home/florian/proj/cpython/Objects/abstract.c:2135:10
#16 0x5f1017f9aaca in PySequence_Fast /home/florian/proj/cpython/Objects/abstract.c:2166:9
#17 0x5f10181cb7ce in PyUnicode_Join /home/florian/proj/cpython/Objects/unicodeobject.c:9569:12
I'm assuming this is a CPython bug, given that I have it bisected to
that commit - but it's unclear to me why/how PyQt is involved here.
Is this anything where PyQt could possibly be to blame for some sort of
refcounting issue? Is there a better way to debug those rather than
ASan?
Thanks,
Florian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20240528/f07c3c07/attachment.sig>
More information about the PyQt
mailing list