[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