[PyQt] Crash with QMetaObject support
Giovanni Bajo
rasky at develer.com
Wed May 16 15:58:31 BST 2007
Hi Phil,
[fix at the end of the mail]
Using Qt 4.2.2, PyQt 4.2, SIP 4.6,
I get a segfault in QMetaObject::indexOfSlot()
(corelib\kernel\qmetaobject.cpp):
int QMetaObject::indexOfSlot(const char *slot) const
{
int i = -1;
const QMetaObject *m = this;
while (m && i < 0) {
for (i = priv(m->d.data)->methodCount-1; i >= 0; --i)
if ((m->d.data[priv(m->d.data)->methodData + 5*i + 4] &
MethodTypeMask) == MethodSlot
&& strcmp(slot, m->d.stringdata
+ m->d.data[priv(m->d.data)->methodData + 5*i])
== 0) {
i += m->methodOffset();
break;
}
m = m->d.superdata;
}
return i;
}
The crash is within the if condition, when it tries to access that
data[]. The problem is that the offset within data[] computed by the
expression:
priv(m->d.data)->methodData + 5*i + 4
is invalid. "slot" points to the string "deleteLater()" in memory. "i" is 1.
m->d.stringdata is:
0x0A488F40 50 79 51 74 50 72 6f 78 PyQtProx
0x0A488F48 79 00 00 41 42 4f 55 54 y..ABOUT
0x0A488F50 5f 54 4f 5f 53 48 4f 57 _TO_SHOW
0x0A488F58 28 29 00 00 00 00 00 00 ()......
0x0A488F60 0a 00 05 00 04 01 0c 00 ........
0x0A488F68 a0 3c e3 00 10 38 80 09 <ã..8.
0x0A488F70 a8 8e 48 0a 00 00 00 00 ¨H.....
0x0A488F78 b0 a1 42 0a 00 00 00 00 °¡B.....
0x0A488F80 00 00 00 00 00 00 00 00 ........
0x0A488F88 00 00 00 00 00 00 00 00 ........
(not sure how long the buffer is)
m->d.data is:
0x0A488FB8 01 00 00 00 00 00 00 00 ........
0x0A488FC0 00 00 00 00 00 00 00 00 ........
0x0A488FC8 02 00 00 00 0a 00 00 00 ........
0x0A488FD0 00 00 00 00 00 00 00 00 ........
0x0A488FD8 00 00 00 00 00 00 00 00 ........
0x0A488FE0 0b 00 00 00 0a 00 00 00 ........
0x0A488FE8 0a 00 00 00 0a 00 00 00 ........
0x0A488FF0 05 00 00 00 23 00 00 00 ....#...
0x0A488FF8 00 00 00 00 00 00 00 00 ........
0x0A489000 ?? ?? ?? ?? ?? ?? ?? ??
0x0A489008 ?? ?? ?? ?? ?? ?? ?? ??
(notice that 0xA489000 is not-allocated memory, which causes the segfault).
Some further watches:
priv(m->d.data)->className = 0x0
m->d.data[priv(m->d.data)->className] = "PyQtProxy"
priv(m->d.data)->methodCount = 0x2
priv(m->d.data)->propertyCount = 0x0
priv(m->d.data)->enumeratorCount = 0x0
priv(m->d.data)->methodData = 0xa
priv(m->d.data)->methodData + 5*0 + 4 = 0xe
m->d.data[priv(m->d.data)->methodData + 5*0 + 4] = 0x5 (MethodSignal |
AccessProtected)
m->d.data[priv(m->d.data)->methodData + 5*0] = 0xb
m->d.stringdata + 0xb = 0x0a488f4b "ABOUT_TO_SHOW()"
priv(m->d.data)->methodData + 5*1 + 4 = 0x13
m->d.data[priv(m->d.data)->methodData + 5*1 + 4] = SEGFAULT!
m->d.data[priv(m->d.data)->methodData + 5*1] = 0x23
m->d.stringdata + 0x23 = 0x0a488f63 ""
---------------------------------------------------------------
The problem appears to be in qobject.sip:
// Add the non-string data.
uint *data = new uint[16];
for (int d = 0; d < 16; ++d)
data[d] = staticMetaObject.d.data[d];
// Fix the changed values;
data[10] = sig_pos;
data[11] = args_pos;
data[14] = 0x05;
but staticMetaObject.d.data is:
static const uint slot_meta_data[] = {
// content:
1, // revision
0, // classname
0, 0, // classinfo
2, 10, // methods (number, offset in this array of first one)
0, 0, // properties
0, 0, // enums/sets
// signals: signature, parameters, type, tag, flags
11, 10, 10, 10, 0x05,
// slots: signature, parameters, type, tag, flags
35, 10, 10, 10, 0x0a,
0 // eod
};
which is larger than 16 bytes. My fix is simple:
// Add the non-string data.
uint *data = new uint[sizeof(slot_meta_data)];
for (int d = 0; d < sizeof(slot_meta_data); ++d)
data[d] = slot_meta_data[d];
and it appears to work.
--
Giovanni Bajo
More information about the PyQt
mailing list