aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-06-14 12:09:35 +0200
committerUlf Hermann <ulf.hermann@qt.io>2019-06-14 19:08:51 +0200
commit84f8ceef3f3b1cf3f63d52d44a2ed8292aca68c3 (patch)
treeae405994ca98a3bc8ca18fe56d2c275fcbcac793 /src/qml/jsruntime
parentacbc9a3984a5c729c6731f73431aae6d802aa78a (diff)
Move the header checking into ExecutableCompilationUnit
We don't need to verify the header unless we want to execute the code. Change-Id: Ieac51c47faafcd7047228b4264aa7750ba3d8889 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4compilationunitmapper_unix.cpp4
-rw-r--r--src/qml/jsruntime/qv4compilationunitmapper_win.cpp4
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp58
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h3
4 files changed, 65 insertions, 4 deletions
diff --git a/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp b/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp
index 6768bc9596..a9ab2f5ccb 100644
--- a/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp
+++ b/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp
@@ -45,7 +45,7 @@
#include <QScopeGuard>
#include <QDateTime>
-#include "qv4compileddata_p.h"
+#include "qv4executablecompilationunit_p.h"
QT_BEGIN_NAMESPACE
@@ -73,7 +73,7 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
return nullptr;
}
- if (!header.verifyHeader(sourceTimeStamp, errorString))
+ if (!ExecutableCompilationUnit::verifyHeader(&header, sourceTimeStamp, errorString))
return nullptr;
// Data structure and qt version matched, so now we can access the rest of the file safely.
diff --git a/src/qml/jsruntime/qv4compilationunitmapper_win.cpp b/src/qml/jsruntime/qv4compilationunitmapper_win.cpp
index 779c1288fe..9e8babc5e6 100644
--- a/src/qml/jsruntime/qv4compilationunitmapper_win.cpp
+++ b/src/qml/jsruntime/qv4compilationunitmapper_win.cpp
@@ -39,7 +39,7 @@
#include "qv4compilationunitmapper_p.h"
-#include "qv4compileddata_p.h"
+#include "qv4executablecompilationunit_p.h"
#include <QScopeGuard>
#include <QFileInfo>
#include <QDateTime>
@@ -87,7 +87,7 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
return nullptr;
}
- if (!header.verifyHeader(sourceTimeStamp, errorString))
+ if (!ExecutableCompilationUnit::verifyHeader(&header, sourceTimeStamp, errorString))
return nullptr;
// Data structure and qt version matched, so now we can access the rest of the file safely.
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 58f6735008..7867dff769 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -51,6 +51,7 @@
#include <private/qqmlvaluetypewrapper_p.h>
#include <private/qv4module_p.h>
#include <private/qv4compilationunitmapper_p.h>
+#include <private/qml_compile_hash_p.h>
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlpropertymap.h>
@@ -60,6 +61,19 @@
#include <QtCore/qfileinfo.h>
#include <QtCore/qscopeguard.h>
+#if defined(QML_COMPILE_HASH)
+# ifdef Q_OS_LINUX
+// Place on a separate section on Linux so it's easier to check from outside
+// what the hash version is.
+__attribute__((section(".qml_compile_hash")))
+# endif
+const char qml_compile_hash[48 + 1] = QML_COMPILE_HASH;
+static_assert(sizeof(QV4::CompiledData::Unit::libraryVersionHash) >= QML_COMPILE_HASH_LENGTH + 1,
+ "Compile hash length exceeds reserved size in data structure. Please adjust and bump the format version");
+#else
+# error "QML_COMPILE_HASH must be defined for the build of QtDeclarative to ensure version checking for cache files"
+#endif
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -804,6 +818,50 @@ QString ExecutableCompilationUnit::bindingValueAsScriptString(
: bindingValueAsString(binding);
}
+bool ExecutableCompilationUnit::verifyHeader(
+ const CompiledData::Unit *unit, QDateTime expectedSourceTimeStamp, QString *errorString)
+{
+ if (strncmp(unit->magic, CompiledData::magic_str, sizeof(unit->magic))) {
+ *errorString = QStringLiteral("Magic bytes in the header do not match");
+ return false;
+ }
+
+ if (unit->version != quint32(QV4_DATA_STRUCTURE_VERSION)) {
+ *errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2")
+ .arg(unit->version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16);
+ return false;
+ }
+
+ if (unit->qtVersion != quint32(QT_VERSION)) {
+ *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2")
+ .arg(unit->qtVersion, 0, 16).arg(QT_VERSION, 0, 16);
+ return false;
+ }
+
+ if (unit->sourceTimeStamp) {
+ // Files from the resource system do not have any time stamps, so fall back to the application
+ // executable.
+ if (!expectedSourceTimeStamp.isValid())
+ expectedSourceTimeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified();
+
+ if (expectedSourceTimeStamp.isValid()
+ && expectedSourceTimeStamp.toMSecsSinceEpoch() != unit->sourceTimeStamp) {
+ *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ return false;
+ }
+ }
+
+#if defined(QML_COMPILE_HASH)
+ if (qstrcmp(qml_compile_hash, unit->libraryVersionHash) != 0) {
+ *errorString = QStringLiteral("QML library version mismatch. Expected compile hash does not match");
+ return false;
+ }
+#else
+#error "QML_COMPILE_HASH must be defined for the build of QtDeclarative to ensure version checking for cache files"
+#endif
+ return true;
+}
+
} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 4e3aadf28a..1823a3663c 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -251,6 +251,9 @@ public:
return constants[binding->value.constantValueIndex].doubleValue();
}
+ static bool verifyHeader(const CompiledData::Unit *unit, QDateTime expectedSourceTimeStamp,
+ QString *errorString);
+
protected:
quint32 totalStringCount() const
{ return data->stringTableSize; }