summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp22
-rw-r--r--src/corelib/plugin/qplugin.h15
-rw-r--r--src/corelib/plugin/qplugin_p.h4
-rw-r--r--src/tools/moc/generator.cpp21
-rw-r--r--tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp56
5 files changed, 75 insertions, 43 deletions
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 9f877ccda8..35c64180d4 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -69,11 +69,17 @@ static inline int metaDataSignatureLength()
static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QString *errMsg)
{
- if (Q_UNLIKELY(raw[-1] != '!')) {
- *errMsg = QStringLiteral("Invalid metadata signature");
+ // extract the keys not stored in CBOR
+ int qt_metadataVersion = quint8(raw[0]);
+ int qt_version = qFromBigEndian<quint16>(raw + 1);
+ int qt_archRequirements = quint8(raw[3]);
+ if (Q_UNLIKELY(raw[-1] != '!' || qt_metadataVersion != 0)) {
+ *errMsg = QStringLiteral("Invalid metadata version");
return QJsonDocument();
}
+ raw += 4;
+ size -= 4;
QByteArray ba = QByteArray::fromRawData(raw, int(size));
QCborParserError err;
QCborValue metadata = QCborValue::fromCbor(ba, &err);
@@ -88,8 +94,12 @@ static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QStri
return QJsonDocument();
}
- // convert the top-level map integer keys
QJsonObject o;
+ o.insert(QLatin1String("version"), qt_version << 8);
+ o.insert(QLatin1String("debug"), bool(qt_archRequirements & 1));
+ o.insert(QLatin1String("archreq"), qt_archRequirements);
+
+ // convert the top-level map integer keys
for (auto it : metadata.toMap()) {
QString key;
if (it.first.isInteger()) {
@@ -98,6 +108,12 @@ static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QStri
case int(IntKey): key = QStringLiteral(StringKey); break;
QT_PLUGIN_FOREACH_METADATA(CONVERT_TO_STRING)
#undef CONVERT_TO_STRING
+
+ case int(QtPluginMetaDataKeys::Requirements):
+ // special case: recreate the debug key
+ o.insert(QLatin1String("debug"), bool(it.second.toInteger() & 1));
+ key = QStringLiteral("archreq");
+ break;
}
} else {
key = it.first.toString();
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index 9922026f97..5aca22497a 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -55,6 +55,21 @@ QT_BEGIN_NAMESPACE
# endif
#endif
+inline constexpr unsigned char qPluginArchRequirements()
+{
+ return 0
+#ifndef QT_NO_DEBUG
+ | 1
+#endif
+#ifdef __AVX2__
+ | 2
+# ifdef __AVX512F__
+ | 4
+# endif
+#endif
+ ;
+}
+
typedef QObject *(*QtPluginInstanceFunction)();
typedef const char *(*QtPluginMetaDataFunction)();
diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h
index 99ee16a3e8..717129268b 100644
--- a/src/corelib/plugin/qplugin_p.h
+++ b/src/corelib/plugin/qplugin_p.h
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
enum class QtPluginMetaDataKeys {
QtVersion,
- Debug,
+ Requirements,
IID,
ClassName,
MetaData
@@ -66,8 +66,6 @@ enum class QtPluginMetaDataKeys {
// F(IntKey, StringKey, Description)
// Keep this list sorted in the order moc should output.
#define QT_PLUGIN_FOREACH_METADATA(F) \
- F(QtPluginMetaDataKeys::QtVersion, "version", "Qt version built against") \
- F(QtPluginMetaDataKeys::Debug, "debug", "Whether it is a debug build") \
F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data")
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index e5154b779b..e499d22618 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -1624,8 +1624,11 @@ void Generator::generatePluginMetaData()
return;
fputs("\nQT_PLUGIN_METADATA_SECTION\n"
- "static const unsigned char qt_pluginMetaData[] = {\n"
- " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',", out);
+ "static constexpr unsigned char qt_pluginMetaData[] = {\n"
+ " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',\n"
+ " // metadata version, Qt version, architectural requirements\n"
+ " 0, QT_VERSION_MAJOR, QT_VERSION_MINOR, qPluginArchRequirements(),", out);
+
CborDevice dev(out);
CborEncoder enc;
@@ -1634,20 +1637,6 @@ void Generator::generatePluginMetaData()
CborEncoder map;
cbor_encoder_create_map(&enc, &map, CborIndefiniteLength);
- dev.nextItem("\"version\"");
- cbor_encode_int(&map, int(QtPluginMetaDataKeys::QtVersion));
- cbor_encode_int(&map, QT_VERSION);
-
- fputs("\n#ifdef QT_NO_DEBUG", out);
- dev.nextItem("\"debug\" = false");
- cbor_encode_int(&map, int(QtPluginMetaDataKeys::Debug));
- cbor_encode_boolean(&map, false);
- fputs("\n#else", out);
- dev.nextItem("\"debug\" = true");
- cbor_encode_int(&map, int(QtPluginMetaDataKeys::Debug));
- cbor_encode_boolean(&map, true);
- fputs("\n#endif", out);
-
dev.nextItem("\"IID\"");
cbor_encode_int(&map, int(QtPluginMetaDataKeys::IID));
cbor_encode_text_string(&map, cdef->pluginData.iid.constData(), cdef->pluginData.iid.size());
diff --git a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
index 8a5c325041..a290c012df 100644
--- a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
+++ b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
@@ -31,6 +31,7 @@
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
+#include <qplugin.h>
#include <QPluginLoader>
#include <private/qplugin_p.h>
@@ -147,49 +148,62 @@ void tst_QPlugin::scanInvalidPlugin_data()
QTest::newRow("json-control") << (prefix + QJsonDocument(obj).toBinaryData()) << true << "";
}
- QTest::newRow("json-zeroes") << prefix << false << "";
+ QTest::newRow("json-zeroes") << prefix << false << " ";
prefix += "qbjs";
- QTest::newRow("bad-json-version0") << prefix << false << "";
- QTest::newRow("bad-json-version2") << (prefix + QByteArray("\2\0\0\0", 4)) << false << "";
+ QTest::newRow("bad-json-version0") << prefix << false << " ";
+ QTest::newRow("bad-json-version2") << (prefix + QByteArray("\2\0\0\0", 4)) << false << " ";
// valid qbjs version 1
prefix += QByteArray("\1\0\0\0");
// too large for the file (100 MB)
- QTest::newRow("bad-json-size-large1") << (prefix + QByteArray("\0\0\x40\x06")) << false << "";
+ QTest::newRow("bad-json-size-large1") << (prefix + QByteArray("\0\0\x40\x06")) << false << " ";
// too large for binary JSON (512 MB)
- QTest::newRow("bad-json-size-large2") << (prefix + QByteArray("\0\0\0\x20")) << false << "";
+ QTest::newRow("bad-json-size-large2") << (prefix + QByteArray("\0\0\0\x20")) << false << " ";
// could overflow
- QTest::newRow("bad-json-size-large3") << (prefix + "\xff\xff\xff\x7f") << false << "";
+ QTest::newRow("bad-json-size-large3") << (prefix + "\xff\xff\xff\x7f") << false << " ";
#endif
// CBOR metadata
- QByteArray cprefix = "QTMETADATA !";
+ QByteArray cprefix = "QTMETADATA !1234";
+ cprefix[12] = 0; // current version
+ cprefix[13] = QT_VERSION_MAJOR;
+ cprefix[14] = QT_VERSION_MINOR;
+ cprefix[15] = qPluginArchRequirements();
- {
+ QByteArray cborValid = [] {
QCborMap m;
m.insert(int(QtPluginMetaDataKeys::IID), QLatin1String("org.qt-project.tst_qplugin"));
m.insert(int(QtPluginMetaDataKeys::ClassName), QLatin1String("tst"));
- m.insert(int(QtPluginMetaDataKeys::QtVersion), int(QT_VERSION));
-#ifdef QT_NO_DEBUG
- m.insert(int(QtPluginMetaDataKeys::Debug), false);
-#else
- m.insert(int(QtPluginMetaDataKeys::Debug), true);
-#endif
m.insert(int(QtPluginMetaDataKeys::MetaData), QCborMap());
+ return QCborValue(m).toCbor();
+ }();
+ QTest::newRow("cbor-control") << (cprefix + cborValid) << true << "";
- QTest::newRow("cbor-control") << (cprefix + QCborValue(m).toCbor()) << true << "";
- }
+ cprefix[12] = 1;
+ QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false
+ << " Invalid metadata version";
+
+ cprefix[12] = 0;
+ cprefix[13] = QT_VERSION_MAJOR + 1;
+ QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false << "";
+
+ cprefix[13] = QT_VERSION_MAJOR - 1;
+ QTest::newRow("cbor-major-too-old") << (cprefix + cborValid) << false << "";
+
+ cprefix[13] = QT_VERSION_MAJOR;
+ cprefix[14] = QT_VERSION_MINOR + 1;
+ QTest::newRow("cbor-minor-too-new") << (cprefix + cborValid) << false << "";
QTest::newRow("cbor-invalid") << (cprefix + "\xff") << false
- << "Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
+ << " Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
QTest::newRow("cbor-not-map1") << (cprefix + "\x01") << false
- << "Unexpected metadata contents";
+ << " Unexpected metadata contents";
QTest::newRow("cbor-not-map2") << (cprefix + "\x81\x01") << false
- << "Unexpected metadata contents";
+ << " Unexpected metadata contents";
}
static const char invalidPluginSignature[] = "qplugin testfile";
@@ -246,10 +260,10 @@ void tst_QPlugin::scanInvalidPlugin()
// now try to load this
QFETCH(bool, loads);
QFETCH(QString, errMsg);
- if (!loads)
+ if (!errMsg.isEmpty())
QTest::ignoreMessage(QtWarningMsg,
"Found invalid metadata in lib " + QFile::encodeName(newName) +
- ": " + errMsg.toUtf8());
+ ":" + errMsg.toUtf8());
QPluginLoader loader(newName);
QCOMPARE(loader.load(), loads);
if (loads)