aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4executablecompilationunit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4executablecompilationunit.cpp')
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp78
1 files changed, 73 insertions, 5 deletions
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index c68f6a7cbf..492d1f4d03 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>
@@ -59,6 +60,20 @@
#include <QtCore/qstandardpaths.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qscopeguard.h>
+#include <QtCore/qcryptographichash.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
@@ -105,7 +120,7 @@ static QString toString(QV4::ReturnedValue v)
static void dumpConstantTable(const StaticValue *constants, uint count)
{
QDebug d = qDebug();
- d.nospace() << right;
+ d.nospace() << Qt::right;
for (uint i = 0; i < count; ++i) {
d << qSetFieldWidth(8) << i << qSetFieldWidth(0) << ": "
<< toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
@@ -308,7 +323,12 @@ void ExecutableCompilationUnit::unlink()
f->destroy();
runtimeFunctions.clear();
- CompiledData::CompilationUnit::unlink();
+ free(runtimeStrings);
+ runtimeStrings = nullptr;
+ delete [] runtimeRegularExpressions;
+ runtimeRegularExpressions = nullptr;
+ free(runtimeClasses);
+ runtimeClasses = nullptr;
}
void ExecutableCompilationUnit::markObjects(QV4::MarkStack *markStack)
@@ -673,7 +693,11 @@ bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorSt
return false;
}
- return CompilationUnit::saveToDisk(localCacheFilePath(unitUrl), errorString);
+ return CompiledData::SaveableUnitPointer(unitData()).saveToDisk<char>(
+ [this, &unitUrl, errorString](const char *data, quint32 size) {
+ return CompiledData::SaveableUnitPointer::writeDataToFile(localCacheFilePath(unitUrl), data,
+ size, errorString);
+ });
}
/*!
@@ -766,8 +790,8 @@ QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Bind
#if !QT_CONFIG(translation)
case Binding::Type_TranslationById:
case Binding::Type_Translation:
- return unit->stringAt(
- unit->data->translations()[binding->value.translationDataIndex].stringIndex);
+ return stringAt(
+ data->translations()[binding->value.translationDataIndex].stringIndex);
#else
case Binding::Type_TranslationById: {
const TranslationData &translation
@@ -804,6 +828,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