aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2012-09-27 16:56:03 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-09-28 13:26:16 +0200
commit5bd0e08063fcacba0c2b63528712968c7d74e7f9 (patch)
treec430c6b783922fd310ec510fef08fc075c891f7f
parentb68fb568d8287e9a0c45a0dc0187398995313969 (diff)
Fix a crash in QQmlPropertyCache::findProperty
When the top type of a QML component is a C++ type registered with qmlRegisterExtendedType, its QObjectPrivate::metaObject is already a QQmlProxyMetaObject that gets chained as the parent of the QQmlVMEMetaObject of the component. When QQmlPropertyCache::findProperty iterates over the parents chain of a child item, our QQmlProxyMetaObject eventually gets static_casted to QQmlVMEMetaObject and causes a crash. This patch implements a poor man's dynamic_cast in QQmlVMEMetaObject::parentVMEMetaObject to fix the crash. Other casts of parent.asT1() are changed to use parentVMEMetaObject as well even though in those cases the static_cast is guaranteed by the context. Task-number: QTBUG-27334 Change-Id: I5982fc273ccf466960ce54974cff5662e6ab605a Reviewed-by: Matthew Vogt <mattvogt2@gmail.com> Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp52
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h2
2 files changed, 29 insertions, 25 deletions
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 37d72f16b3..14d25b6a5e 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -559,8 +559,12 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
{
QObjectPrivate *op = QObjectPrivate::get(obj);
- if (op->metaObject) parent = op->metaObject;
- else parent = obj->metaObject();
+ if (op->metaObject) {
+ parent = op->metaObject;
+ // Use the extra flag in QBiPointer to know if we can safely cast parent.asT1() to QQmlVMEMetaObject*
+ parent.setFlagValue(QQmlData::get(obj)->hasVMEMetaObject);
+ } else
+ parent = obj->metaObject();
op->metaObject = this;
QQmlData::get(obj)->hasVMEMetaObject = true;
@@ -1154,8 +1158,8 @@ void QQmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QQmlPrope
quint16 QQmlVMEMetaObject::vmeMethodLineNumber(int index)
{
if (index < methodOffset()) {
- Q_ASSERT(parent.isT1());
- return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeMethodLineNumber(index);
+ Q_ASSERT(parentVMEMetaObject());
+ return parentVMEMetaObject()->vmeMethodLineNumber(index);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
@@ -1170,8 +1174,8 @@ quint16 QQmlVMEMetaObject::vmeMethodLineNumber(int index)
v8::Handle<v8::Function> QQmlVMEMetaObject::vmeMethod(int index)
{
if (index < methodOffset()) {
- Q_ASSERT(parent.isT1());
- return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeMethod(index);
+ Q_ASSERT(parentVMEMetaObject());
+ return parentVMEMetaObject()->vmeMethod(index);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
@@ -1182,8 +1186,8 @@ v8::Handle<v8::Function> QQmlVMEMetaObject::vmeMethod(int index)
void QQmlVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Function> value)
{
if (index < methodOffset()) {
- Q_ASSERT(parent.isT1());
- return static_cast<QQmlVMEMetaObject *>(parent.asT1())->setVmeMethod(index, value);
+ Q_ASSERT(parentVMEMetaObject());
+ return parentVMEMetaObject()->setVmeMethod(index, value);
}
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
@@ -1200,8 +1204,8 @@ void QQmlVMEMetaObject::setVmeMethod(int index, v8::Persistent<v8::Function> val
v8::Handle<v8::Value> QQmlVMEMetaObject::vmeProperty(int index)
{
if (index < propOffset()) {
- Q_ASSERT(parent.isT1());
- return static_cast<QQmlVMEMetaObject *>(parent.asT1())->vmeProperty(index);
+ Q_ASSERT(parentVMEMetaObject());
+ return parentVMEMetaObject()->vmeProperty(index);
}
return readVarProperty(index - propOffset());
}
@@ -1209,8 +1213,8 @@ v8::Handle<v8::Value> QQmlVMEMetaObject::vmeProperty(int index)
void QQmlVMEMetaObject::setVMEProperty(int index, v8::Handle<v8::Value> v)
{
if (index < propOffset()) {
- Q_ASSERT(parent.isT1());
- static_cast<QQmlVMEMetaObject *>(parent.asT1())->setVMEProperty(index, v);
+ Q_ASSERT(parentVMEMetaObject());
+ parentVMEMetaObject()->setVMEProperty(index, v);
return;
}
return writeVarProperty(index - propOffset(), v);
@@ -1351,20 +1355,20 @@ void QQmlVMEMetaObject::activate(QObject *object, int index, void **args)
QQmlVMEMetaObject *QQmlVMEMetaObject::getForProperty(QObject *o, int coreIndex)
{
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
- while (vme->propOffset() > coreIndex) {
- Q_ASSERT(vme->parent.isT1());
- vme = static_cast<QQmlVMEMetaObject *>(vme->parent.asT1());
- }
+ while (vme && vme->propOffset() > coreIndex)
+ vme = vme->parentVMEMetaObject();
+
+ Q_ASSERT(vme);
return vme;
}
QQmlVMEMetaObject *QQmlVMEMetaObject::getForMethod(QObject *o, int coreIndex)
{
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
- while (vme->methodOffset() > coreIndex) {
- Q_ASSERT(vme->parent.isT1());
- vme = static_cast<QQmlVMEMetaObject *>(vme->parent.asT1());
- }
+ while (vme && vme->methodOffset() > coreIndex)
+ vme = vme->parentVMEMetaObject();
+
+ Q_ASSERT(vme);
return vme;
}
@@ -1375,10 +1379,10 @@ QQmlVMEMetaObject *QQmlVMEMetaObject::getForMethod(QObject *o, int coreIndex)
QQmlVMEMetaObject *QQmlVMEMetaObject::getForSignal(QObject *o, int coreIndex)
{
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
- while (vme->signalOffset() > coreIndex) {
- Q_ASSERT(vme->parent.isT1());
- vme = static_cast<QQmlVMEMetaObject *>(vme->parent.asT1());
- }
+ while (vme && vme->signalOffset() > coreIndex)
+ vme = vme->parentVMEMetaObject();
+
+ Q_ASSERT(vme);
return vme;
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 8329e3ce16..c858370d27 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -287,7 +287,7 @@ int QQmlVMEMetaObject::signalCount() const
QQmlVMEMetaObject *QQmlVMEMetaObject::parentVMEMetaObject() const
{
- if (parent.isT1())
+ if (parent.isT1() && parent.flag())
return static_cast<QQmlVMEMetaObject *>(parent.asT1());
return 0;