summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2009-12-14 14:10:33 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2009-12-14 17:37:03 (GMT)
commit74bec871abb48baadf239fd12e77bb85924436a1 (patch)
tree711e6383e3d60dbfdd0c4ce2333d9be935bf157a /src/corelib/kernel
parenta72468e820c2922540737c053eef27d033c2e77b (diff)
downloadQt-74bec871abb48baadf239fd12e77bb85924436a1.zip
Qt-74bec871abb48baadf239fd12e77bb85924436a1.tar.gz
Qt-74bec871abb48baadf239fd12e77bb85924436a1.tar.bz2
Fix QMetaObject::connect and disconnect with "dynamic signals"
QML might pass index that are larger that the method cound. We must not call QMetaObjectPrivate::originalClone in that case as this would read invalid memory Reviewed-by: brad
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qmetaobject.cpp1
-rw-r--r--src/corelib/kernel/qobject.cpp43
2 files changed, 24 insertions, 20 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 6e6da19..72d6786 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -2648,6 +2648,7 @@ const char* QMetaClassInfo::value() const
*/
int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
{
+ Q_ASSERT(local_method_index < get(mobj)->methodCount);
int handle = get(mobj)->methodData + 5 * local_method_index;
while (mobj->d.data[handle + 4] & MethodCloned) {
Q_ASSERT(local_method_index > 0);
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 85915c2..4370ee0 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -2850,6 +2850,27 @@ void QObject::disconnectNotify(const char *)
{
}
+/* \internal
+ convert a signal index from the method range to the signal range
+ */
+static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_index)
+{
+ if (signal_index < 0)
+ return signal_index;
+ while (metaObject && metaObject->methodOffset() > signal_index)
+ metaObject = metaObject->superClass();
+
+ if (metaObject) {
+ int signalOffset, methodOffset;
+ computeOffsets(metaObject, &signalOffset, &methodOffset);
+ if (signal_index < metaObject->methodCount())
+ signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
+ else
+ signal_index = signal_index - methodOffset + signalOffset;
+ }
+ return signal_index;
+}
+
/*!\internal
\a types is a 0-terminated vector of meta types for queued
connections.
@@ -2860,16 +2881,7 @@ void QObject::disconnectNotify(const char *)
bool QMetaObject::connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index, int type, int *types)
{
- if (signal_index > 0) {
- const QMetaObject *mo = sender->metaObject();
- while (mo && mo->methodOffset() > signal_index)
- mo = mo->superClass();
- if (mo) {
- int signalOffset, methodOffset;
- computeOffsets(mo, &signalOffset, &methodOffset);
- signal_index = QMetaObjectPrivate::originalClone(mo, signal_index - methodOffset) + signalOffset;
- }
- }
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
return QMetaObjectPrivate::connect(sender, signal_index,
receiver, method_index, type, types);
}
@@ -2938,16 +2950,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
bool QMetaObject::disconnect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index)
{
- if (signal_index > 0) {
- const QMetaObject *mo = sender->metaObject();
- while (mo && mo->methodOffset() > signal_index)
- mo = mo->superClass();
- if (mo) {
- int signalOffset, methodOffset;
- computeOffsets(mo, &signalOffset, &methodOffset);
- signal_index = QMetaObjectPrivate::originalClone(mo, signal_index - methodOffset) + signalOffset;
- }
- }
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
return QMetaObjectPrivate::disconnect(sender, signal_index,
receiver, method_index);
}