[PyQt] [BUG] Class name collision
Phil Thompson
phil at riverbankcomputing.com
Sat Dec 12 10:26:11 GMT 2015
On 9 Dec 2015, at 1:21 p.m., Vladimir Rutsky <rutsky.vladimir at gmail.com> wrote:
>
> If Python class name is the same as some Qt class name PyQt metacast
> machinery may try to access missing attribute of the class and
> generate AttributeError.
> This AttributeError is not explicitly catched and if Python
> interpreter is built with enabled assertions (e.g. in debug mode)
> Python interpreter aborts with failed assert.
>
> Here is an example that reproduces this bug (only in debug Python):
> https://gist.github.com/rutsky/0adfbb56a32b208ab28c
>
> from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout
>
> class QWindow(QWidget):
> def __init__(self, parent=None):
> super().__init__(parent)
> self.setLayout(QVBoxLayout())
> self.layout().parentWidget() # <-- uncaught exception is
> generated and asserted here
>
> qapp = QApplication([])
> qwin = QWindow()
> qwin.show()
> qapp.exec()
>
>
> Example generates following error:
>
> python: ../Objects/abstract.c:2050: PyObject_Call: Assertion `(result
> != ((void *)0) && !PyErr_Occurred()) || (result == ((void *)0) &&
> PyErr_Occurred())' failed.
> Aborted (core dumped)
>
>
> Exception is generated in this PyQt code of
> qpycore_qobject_qt_metacast() function
> (PyQt-gpl-5.5.1/qpy/QtCore/qpycore_qobject_helpers.cpp):
>
> for (SIP_SSIZE_T i = 0; i < PyTuple_GET_SIZE(mro); ++i)
> {
> PyTypeObject *pytype = (PyTypeObject *)PyTuple_GET_ITEM(mro, i);
>
> if (!PyObject_IsInstance((PyObject *)pytype, (PyObject
> *)&qpycore_pyqtWrapperType_Type))
> continue;
>
> const sipTypeDef *td = ((sipWrapperType *)pytype)->type;
>
> if (qstrcmp(pytype->tp_name, _clname) == 0)
> {
> // The generated type definitions represent the C++ (rather than
> // Python) hierachy. If the C++ hierachy doesn't match then the
> // super-type must be provided by a mixin.
> if (PyType_IsSubtype(base_pytype, pytype))
> *sipCpp = sipGetAddress(pySelf);
> else
> // ====================================
> // Attribute error is generated here, something like:
> // "AttributeError: 'QWindow' object has no attribute 'QWidget'"
> // ====================================
> *sipCpp = sipGetMixinAddress(pySelf, td);
>
> is_py_class = true;
> break;
> }
>
> While whole attribute access thing looks unstable to me (what if not
> only class name will collide, but also my class will have accessed
> attribute?), adding explicit check for AttributeError here fixes this
> issue. Attached patch workarounds (fixes?) this issue.
The underlying bug is actually in SIP - fixed in tonight's snapshot.
Thanks,
Phil
More information about the PyQt
mailing list