aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthew Vogt <matthew.vogt@nokia.com>2012-07-06 09:53:03 +1000
committerQt by Nokia <qt-info@nokia.com>2012-07-09 04:01:19 +0200
commit19c0a31319148d4ac716f7cb3295891b5a3b20d9 (patch)
treeec01ac1d68d4888c58a4f3b4f547a287a4c7491d /src
parent49a3883e86b61d8facfeea9c43037d484cb50b92 (diff)
Do not permit excessive recursion in component creation
Limit recursion during component creation to prevent infinite recursion resulting in a crash. Recursion results from invoking createObject() in the Component.onCompleted handler. Task-number: QTBUG-25439 Change-Id: Ica2ba099d82b5747c938501af04e67f7ace8402e Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/qqmlcomponent.cpp28
-rw-r--r--src/qml/qml/qqmlcomponent_p.h4
2 files changed, 30 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 768e80f82f..5473290633 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -63,10 +63,15 @@
#include <QStack>
#include <QStringList>
+#include <QThreadStorage>
#include <QtCore/qdebug.h>
#include <qqmlinfo.h>
#include "qqmlmemoryprofiler_p.h"
+namespace {
+ QThreadStorage<int> creationDepth;
+}
+
QT_BEGIN_NAMESPACE
class QQmlComponentExtension : public QV8Engine::Deletable
@@ -772,7 +777,8 @@ QObject *QQmlComponent::create(QQmlContext *context)
context = d->engine->rootContext();
QObject *rv = beginCreate(context);
- completeCreate();
+ if (rv)
+ completeCreate();
return rv;
}
@@ -840,6 +846,16 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
return 0;
}
+ // Do not create infinite recursion in object creation
+ static const int maxCreationDepth = 10;
+ if (++creationDepth.localData() >= maxCreationDepth) {
+ qWarning("QQmlComponent: Component creation is recursing - aborting");
+ --creationDepth.localData();
+ return 0;
+ }
+ Q_ASSERT(creationDepth.localData() >= 1);
+ depthIncreased = true;
+
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
if (enginePriv->inProgressCreations == 0) {
@@ -864,6 +880,10 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
ddata->indestructible = true;
ddata->explicitIndestructibleSet = true;
ddata->rootObjectInCreation = false;
+ } else {
+ Q_ASSERT(creationDepth.localData() >= 1);
+ --creationDepth.localData();
+ depthIncreased = false;
}
if (enginePriv->isDebugging && rv) {
@@ -936,6 +956,12 @@ void QQmlComponentPrivate::completeCreate()
delete profiler;
profiler = 0;
}
+
+ if (depthIncreased) {
+ Q_ASSERT(creationDepth.localData() >= 1);
+ --creationDepth.localData();
+ depthIncreased = false;
+ }
}
QQmlComponentAttached::QQmlComponentAttached(QObject *parent)
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 9e220b5e95..f5589b9003 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -84,7 +84,8 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public
Q_DECLARE_PUBLIC(QQmlComponent)
public:
- QQmlComponentPrivate() : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), profiler(0) {}
+ QQmlComponentPrivate()
+ : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), profiler(0), depthIncreased(false) {}
void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
@@ -120,6 +121,7 @@ public:
QQmlEngine *engine;
QQmlGuardedContextData creationContext;
QQmlObjectCreatingProfiler *profiler;
+ bool depthIncreased;
void clear();