aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-01-15 16:43:31 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-01-23 12:03:40 +0100
commiteb54a004799e39c8e06449c4851a988f273cd0db (patch)
tree50a5f119b1bb7daef9dfdb159024b056b9c58e75
parent19ba561ff1329a9df7fb52e3815b5daa7e8613a4 (diff)
QtQml: Move header verification into CompiledData::Unit
There is nothing that makes it depend on ExecutableCompilationUnit. Change-Id: I482dfc0177530f748bb90e5373c64ca5558d8629 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/common/qv4compileddata.cpp66
-rw-r--r--src/qml/common/qv4compileddata_p.h2
-rw-r--r--src/qml/jsruntime/qv4compilationunitmapper.cpp3
-rw-r--r--src/qml/jsruntime/qv4compilationunitmapper_unix.cpp13
-rw-r--r--src/qml/jsruntime/qv4compilationunitmapper_win.cpp12
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp66
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h3
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2
8 files changed, 84 insertions, 83 deletions
diff --git a/src/qml/common/qv4compileddata.cpp b/src/qml/common/qv4compileddata.cpp
index 621a3c0326..9dee91f713 100644
--- a/src/qml/common/qv4compileddata.cpp
+++ b/src/qml/common/qv4compileddata.cpp
@@ -4,6 +4,7 @@
#include "qv4compileddata_p.h"
#include <private/inlinecomponentutils_p.h>
+#include <private/qml_compile_hash_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qqmltypenamecache_p.h>
#include <private/qv4resolvedtypereference_p.h>
@@ -14,11 +15,76 @@
#include <QtCore/qscopeguard.h>
#include <QtCore/qstandardpaths.h>
+static_assert(QV4::CompiledData::QmlCompileHashSpace > QML_COMPILE_HASH_LENGTH);
+
+#if defined(QML_COMPILE_HASH) && defined(QML_COMPILE_HASH_LENGTH) && QML_COMPILE_HASH_LENGTH > 0
+# 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[QV4::CompiledData::QmlCompileHashSpace] = QML_COMPILE_HASH;
+static_assert(sizeof(QV4::CompiledData::Unit::libraryVersionHash) > QML_COMPILE_HASH_LENGTH,
+ "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 {
namespace CompiledData {
+
+bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const
+{
+ if (strncmp(magic, CompiledData::magic_str, sizeof(magic))) {
+ *errorString = QStringLiteral("Magic bytes in the header do not match");
+ return false;
+ }
+
+ if (version != quint32(QV4_DATA_STRUCTURE_VERSION)) {
+ *errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2")
+ .arg(version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16);
+ return false;
+ }
+
+ if (qtVersion != quint32(QT_VERSION)) {
+ *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2")
+ .arg(qtVersion, 0, 16).arg(QT_VERSION, 0, 16);
+ return false;
+ }
+
+ if (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() != sourceTimeStamp) {
+ *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ return false;
+ }
+ }
+
+#if defined(QML_COMPILE_HASH) && defined(QML_COMPILE_HASH_LENGTH) && QML_COMPILE_HASH_LENGTH > 0
+ if (qstrncmp(qml_compile_hash, libraryVersionHash, QML_COMPILE_HASH_LENGTH) != 0) {
+ *errorString = QStringLiteral("QML compile hashes don't match. Found %1 expected %2")
+ .arg(QString::fromLatin1(
+ QByteArray(libraryVersionHash, QML_COMPILE_HASH_LENGTH)
+ .toPercentEncoding()),
+ QString::fromLatin1(
+ QByteArray(qml_compile_hash, QML_COMPILE_HASH_LENGTH)
+ .toPercentEncoding()));
+ 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;
+}
+
/*!
\internal
This function creates a temporary key vector and sorts it to guarantuee a stable
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index 8fe6c8c87b..55e73bba7d 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -1371,6 +1371,8 @@ struct Unit
const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
+
+ bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
};
static_assert(sizeof(Unit) == 248, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
diff --git a/src/qml/jsruntime/qv4compilationunitmapper.cpp b/src/qml/jsruntime/qv4compilationunitmapper.cpp
index f1c3476d40..e9915c7d26 100644
--- a/src/qml/jsruntime/qv4compilationunitmapper.cpp
+++ b/src/qml/jsruntime/qv4compilationunitmapper.cpp
@@ -4,7 +4,6 @@
#include "qv4compilationunitmapper_p.h"
#include <private/qv4compileddata_p.h>
-#include <private/qv4executablecompilationunit_p.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmutex.h>
@@ -55,7 +54,7 @@ CompiledData::Unit *CompilationUnitMapper::get(
CompilationUnitMapper mapper = cache.get(cacheFilePath);
if (mapper.dataPtr) {
auto *unit = reinterpret_cast<CompiledData::Unit *>(mapper.dataPtr);
- if (ExecutableCompilationUnit::verifyHeader(unit, sourceTimeStamp, errorString)) {
+ if (unit->verifyHeader(sourceTimeStamp, errorString)) {
*this = mapper;
return unit;
}
diff --git a/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp b/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp
index 7b8178fe84..204e222121 100644
--- a/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp
+++ b/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp
@@ -3,13 +3,14 @@
#include "qv4compilationunitmapper_p.h"
-#include <sys/mman.h>
-#include <functional>
#include <private/qcore_unix_p.h>
-#include <QScopeGuard>
-#include <QDateTime>
+#include <private/qv4compileddata_p.h>
+
+#include <QtCore/qscopeguard.h>
+#include <QtCore/qdatetime.h>
-#include "qv4executablecompilationunit_p.h"
+#include <functional>
+#include <sys/mman.h>
QT_BEGIN_NAMESPACE
@@ -37,7 +38,7 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
return nullptr;
}
- if (!ExecutableCompilationUnit::verifyHeader(&header, sourceTimeStamp, errorString))
+ if (!header.verifyHeader(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 9ac4085453..73096207b4 100644
--- a/src/qml/jsruntime/qv4compilationunitmapper_win.cpp
+++ b/src/qml/jsruntime/qv4compilationunitmapper_win.cpp
@@ -3,10 +3,12 @@
#include "qv4compilationunitmapper_p.h"
-#include "qv4executablecompilationunit_p.h"
-#include <QScopeGuard>
-#include <QFileInfo>
-#include <QDateTime>
+#include <private/qv4compileddata_p.h>
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qscopeguard.h>
+
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
@@ -45,7 +47,7 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co
return nullptr;
}
- if (!ExecutableCompilationUnit::verifyHeader(&header, sourceTimeStamp, errorString))
+ if (!header.verifyHeader(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 812a3a5607..dfcdb8079c 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -17,7 +17,6 @@
#include <private/qqmlscriptdata_p.h>
#include <private/qv4module_p.h>
#include <private/qv4compilationunitmapper_p.h>
-#include <private/qml_compile_hash_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qv4resolvedtypereference_p.h>
#include <private/qv4objectiterator_p.h>
@@ -27,21 +26,6 @@
#include <QtCore/qfileinfo.h>
#include <QtCore/qcryptographichash.h>
-static_assert(QV4::CompiledData::QmlCompileHashSpace > QML_COMPILE_HASH_LENGTH);
-
-#if defined(QML_COMPILE_HASH) && defined(QML_COMPILE_HASH_LENGTH) && QML_COMPILE_HASH_LENGTH > 0
-# 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[QV4::CompiledData::QmlCompileHashSpace] = QML_COMPILE_HASH;
-static_assert(sizeof(QV4::CompiledData::Unit::libraryVersionHash) > QML_COMPILE_HASH_LENGTH,
- "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 {
@@ -714,56 +698,6 @@ QString ExecutableCompilationUnit::translateFrom(TranslationDataIndex index) con
#endif
}
-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) && defined(QML_COMPILE_HASH_LENGTH) && QML_COMPILE_HASH_LENGTH > 0
- if (qstrncmp(qml_compile_hash, unit->libraryVersionHash, QML_COMPILE_HASH_LENGTH) != 0) {
- *errorString = QStringLiteral("QML compile hashes don't match. Found %1 expected %2")
- .arg(QString::fromLatin1(
- QByteArray(unit->libraryVersionHash, QML_COMPILE_HASH_LENGTH)
- .toPercentEncoding()),
- QString::fromLatin1(
- QByteArray(qml_compile_hash, QML_COMPILE_HASH_LENGTH)
- .toPercentEncoding()));
- 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 58d252c36c..48ebee6fca 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -186,9 +186,6 @@ public:
QString translateFrom(TranslationDataIndex index) const;
- static bool verifyHeader(const CompiledData::Unit *unit, QDateTime expectedSourceTimeStamp,
- QString *errorString);
-
Heap::Module *module() const { return m_module; }
void setModule(Heap::Module *module) { m_module = module; }
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 0b6ea5c977..66f77edb39 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1709,7 +1709,7 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(
for (const auto lookup : std::as_const(data->lookupCachedQmlUnit)) {
if (const QQmlPrivate::CachedQmlUnit *unit = lookup(uri)) {
QString error;
- if (!QV4::ExecutableCompilationUnit::verifyHeader(unit->qmlData, QDateTime(), &error)) {
+ if (!unit->qmlData->verifyHeader(QDateTime(), &error)) {
qCDebug(DBG_DISK_CACHE) << "Error loading pre-compiled file " << uri << ":" << error;
if (status)
*status = CachedUnitLookupError::VersionMismatch;