diff options
Diffstat (limited to 'src/qml/jsruntime/qv4executablecompilationunit.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit.cpp | 78 |
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 |