aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compileddata.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2016-07-21 16:30:57 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2016-07-23 05:18:59 +0000
commit4c1a51006e5936dc69e3373539787120092f6719 (patch)
treea8979a9e61604958bce581ffd38361b0265510c3 /src/qml/compiler/qv4compileddata.cpp
parent8a8b826cad197cf39e50f88521d0c40dc9c9344d (diff)
Improve robustness of qml disk caching
Perform various basic checks before proceeding to load an existing cache file, including the qt version, architecture, data structure version and others. Change-Id: Ie822b056e944ac120643aad260e97f62616688bf Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compileddata.cpp')
-rw-r--r--src/qml/compiler/qv4compileddata.cpp55
1 files changed, 50 insertions, 5 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 1bcd6892d2..965924262d 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -331,20 +331,56 @@ bool CompilationUnit::saveToDisk(QString *errorString)
return true;
}
-bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
+bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString)
{
if (!url.isLocalFile()) {
*errorString = QStringLiteral("File has to be a local file.");
return false;
}
- QScopedPointer<QFile> cacheFile(new QFile(url.toLocalFile() + QLatin1Char('c')));
+ const QString sourcePath = url.toLocalFile();
+ QScopedPointer<QFile> cacheFile(new QFile(sourcePath + QLatin1Char('c')));
if (!cacheFile->open(QIODevice::ReadOnly)) {
*errorString = cacheFile->errorString();
return false;
}
+ {
+ CompiledData::Unit header;
+ qint64 bytesRead = cacheFile->read(reinterpret_cast<char *>(&header), sizeof(header));
+
+ if (bytesRead != sizeof(header)) {
+ *errorString = QStringLiteral("File too small for the header fields");
+ return false;
+ }
+
+ if (strncmp(header.magic, CompiledData::magic_str, sizeof(header.magic))) {
+ *errorString = QStringLiteral("Magic bytes in the header do not match");
+ return false;
+ }
+
+ if (header.version != quint32(QV4_DATA_STRUCTURE_VERSION)) {
+ *errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2").arg(header.version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16);
+ return false;
+ }
+
+ if (header.qtVersion != quint32(QT_VERSION)) {
+ *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2").arg(header.qtVersion, 0, 16).arg(QT_VERSION, 0, 16);
+ return false;
+ }
+
+ {
+ QFileInfo sourceCode(sourcePath);
+ if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != header.sourceTimeStamp) {
+ *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ return false;
+ }
+ }
+
+ }
+ // Data structure and qt version matched, so now we can access the rest of the file safely.
+
uchar *cacheData = cacheFile->map(/*offset*/0, cacheFile->size());
if (!cacheData) {
*errorString = cacheFile->errorString();
@@ -354,13 +390,22 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
QScopedValueRollback<const Unit *> dataPtrChange(data, reinterpret_cast<const Unit *>(cacheData));
{
- QFileInfo sourceCode(url.toLocalFile());
- if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != data->sourceTimeStamp) {
- *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ const QString foundArchitecture = stringAt(data->architectureIndex);
+ const QString expectedArchitecture = QSysInfo::buildAbi();
+ if (foundArchitecture != expectedArchitecture) {
+ *errorString = QString::fromUtf8("Architecture mismatch. Found %1 expected %2").arg(foundArchitecture).arg(expectedArchitecture);
return false;
}
}
+ {
+ const QString foundCodeGenerator = stringAt(data->codeGeneratorIndex);
+ const QString expectedCodeGenerator = iselFactory->codeGeneratorName;
+ if (foundCodeGenerator != expectedCodeGenerator) {
+ *errorString = QString::fromUtf8("Code generator mismatch. Found code generated by %1 but expected %2").arg(foundCodeGenerator).arg(expectedCodeGenerator);
+ return false;
+ }
+ }
if (!memoryMapCode(errorString))
return false;