diff options
author | Warwick Allison <warwick.allison@nokia.com> | 2010-03-23 04:51:56 (GMT) |
---|---|---|
committer | Warwick Allison <warwick.allison@nokia.com> | 2010-03-23 04:51:56 (GMT) |
commit | 95aa8c8fc76e2309a629b05994a2677b0887140b (patch) | |
tree | 50d7318281610f24df5a9736906a9a6433aba7d8 | |
parent | 9a41034cf05ad4c149e3a98dc8e39f5f6ad05d28 (diff) | |
download | Qt-95aa8c8fc76e2309a629b05994a2677b0887140b.zip Qt-95aa8c8fc76e2309a629b05994a2677b0887140b.tar.gz Qt-95aa8c8fc76e2309a629b05994a2677b0887140b.tar.bz2 |
Basic Loader origin safety (for discussion).
7 files changed, 69 insertions, 2 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 745734e..3cbafd6 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -185,6 +185,9 @@ void QDeclarativeLoader::setSource(const QUrl &url) if (d->source == url) return; + if (!qmlContext(this)->isSafeOrigin(url)) + return; + d->clear(); d->source = url; diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 85896c4..ab3849a 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -361,6 +361,22 @@ QVariant QDeclarativeContext::contextProperty(const QString &name) const return value; } +bool QDeclarativeContext::isSafeOrigin(const QUrl &src) const +{ + if (src.isRelative()) + return true; + if (src.scheme()==QLatin1String("https")) + return true; + + QUrl base = baseUrl(); + if (src.host() == base.host() && src.port() == base.port()) // including files (with no host) + return true; + + qWarning() << src << "is not a safe origin from" << base; + + return false; +} + /*! Resolves the URL \a src relative to the URL of the containing component. diff --git a/src/declarative/qml/qdeclarativecontext.h b/src/declarative/qml/qdeclarativecontext.h index a349628..959af8b 100644 --- a/src/declarative/qml/qdeclarativecontext.h +++ b/src/declarative/qml/qdeclarativecontext.h @@ -85,6 +85,8 @@ public: void setBaseUrl(const QUrl &); QUrl baseUrl() const; + bool isSafeOrigin(const QUrl &src) const; + private: friend class QDeclarativeVME; friend class QDeclarativeEngine; diff --git a/tests/auto/declarative/qdeclarativeloader/data/differentorigin.qml b/tests/auto/declarative/qdeclarativeloader/data/differentorigin.qml new file mode 100644 index 0000000..e682d1c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/differentorigin.qml @@ -0,0 +1,3 @@ +import Qt 4.6 + +Loader { source: "http://evil.place/evil.qml" } diff --git a/tests/auto/declarative/qdeclarativeloader/data/sameorigin-load.qml b/tests/auto/declarative/qdeclarativeloader/data/sameorigin-load.qml new file mode 100644 index 0000000..e281246 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/sameorigin-load.qml @@ -0,0 +1,3 @@ +import Qt 4.6 + +Item { } diff --git a/tests/auto/declarative/qdeclarativeloader/data/sameorigin.qml b/tests/auto/declarative/qdeclarativeloader/data/sameorigin.qml new file mode 100644 index 0000000..e7f5a14 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/sameorigin.qml @@ -0,0 +1,3 @@ +import Qt 4.6 + +Loader { source: "sameorigin-load.qml" } diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index 2c20836..0deac3a 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -86,6 +86,8 @@ private slots: void noResizeGraphicsWidget(); void networkRequestUrl(); void failNetworkRequest(); + void networkSafety(); + void networkSafety_data(); // void networkComponent(); void deleteComponentCrash(); @@ -394,7 +396,7 @@ void tst_QDeclarativeLoader::networkRequestUrl() server.serveDirectory(SRCDIR "/data"); QDeclarativeComponent component(&engine); - component.setData(QByteArray("import Qt 4.6\nLoader { source: \"http://127.0.0.1:14445/Rect120x60.qml\" }"), TEST_FILE("")); + component.setData(QByteArray("import Qt 4.6\nLoader { source: \"http://127.0.0.1:14445/Rect120x60.qml\" }"), QUrl("http://127.0.0.1:14445/dummy.qml")); QDeclarativeLoader *loader = qobject_cast<QDeclarativeLoader*>(component.create()); QVERIFY(loader != 0); @@ -448,7 +450,7 @@ void tst_QDeclarativeLoader::failNetworkRequest() QTest::ignoreMessage(QtWarningMsg, "(:-1: Network error for URL http://127.0.0.1:14445/IDontExist.qml) "); QDeclarativeComponent component(&engine); - component.setData(QByteArray("import Qt 4.6\nLoader { source: \"http://127.0.0.1:14445/IDontExist.qml\" }"), TEST_FILE("")); + component.setData(QByteArray("import Qt 4.6\nLoader { source: \"http://127.0.0.1:14445/IDontExist.qml\" }"), QUrl("http://127.0.0.1:14445/dummy.qml")); QDeclarativeLoader *loader = qobject_cast<QDeclarativeLoader*>(component.create()); QVERIFY(loader != 0); @@ -483,6 +485,41 @@ void tst_QDeclarativeLoader::deleteComponentCrash() delete item; } +void tst_QDeclarativeLoader::networkSafety_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QString>("message"); + + QTest::newRow("same origin") << QUrl("http://127.0.0.1:14445/sameorigin.qml") << QString(); + QTest::newRow("different origin") << QUrl("http://127.0.0.1:14445/differentorigin.qml") << QString(" QUrl( \"http://evil.place/evil.qml\" ) is not a safe origin from QUrl( \"http://127.0.0.1:14445/differentorigin.qml\" ) "); +} + +void tst_QDeclarativeLoader::networkSafety() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/data"); + + QFETCH(QUrl, url); + QFETCH(QString, message); + + if (!message.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, message.toLatin1()); + + QDeclarativeComponent component(&engine, url); + TRY_WAIT(component.status() == QDeclarativeComponent::Ready); + QDeclarativeLoader *loader = qobject_cast<QDeclarativeLoader*>(component.create()); + QVERIFY(loader != 0); + + if (message.isEmpty()) { + TRY_WAIT(loader->status() == QDeclarativeLoader::Ready); + } else { + TRY_WAIT(loader->status() == QDeclarativeLoader::Null); + } + + delete loader; +} + QTEST_MAIN(tst_QDeclarativeLoader) #include "tst_qdeclarativeloader.moc" |