diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/plugin/qfactoryloader.cpp | 92 | ||||
-rw-r--r-- | src/corelib/plugin/qfactoryloader_p.h | 38 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary.cpp | 21 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_p.h | 10 | ||||
-rw-r--r-- | src/corelib/plugin/qplugin_p.h | 10 | ||||
-rw-r--r-- | src/corelib/plugin/qpluginloader.cpp | 17 |
6 files changed, 110 insertions, 78 deletions
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 02c9cafbed..824bf60f7d 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -46,8 +46,12 @@ #include "private/qcoreapplication_p.h" #include "private/qduplicatetracker_p.h" #include "private/qobject_p.h" +#include "qcborarray.h" #include "qcbormap.h" #include "qcborvalue.h" +#include "qcborvalue.h" +#include "qdir.h" +#include "qfileinfo.h" #include "qjsonarray.h" #include "qjsondocument.h" #include "qjsonobject.h" @@ -57,63 +61,61 @@ #include "qplugin.h" #include "qplugin_p.h" #include "qpluginloader.h" -#include <qdebug.h> -#include <qdir.h> + +#if QT_CONFIG(library) +# include "qlibrary_p.h" +#endif #include <qtcore_tracepoints_p.h> QT_BEGIN_NAMESPACE -QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg) +bool QPluginParsedMetaData::parse(QByteArrayView raw) { - // extract the keys not stored in CBOR QPluginMetaData::Header header; - Q_ASSERT(size >= qsizetype(sizeof(header))); - memcpy(&header, raw, sizeof(header)); - if (Q_UNLIKELY(header.version > QPluginMetaData::CurrentMetaDataVersion)) { - *errMsg = QStringLiteral("Invalid metadata version"); - return QJsonDocument(); - } - - raw += sizeof(header); - size -= sizeof(header); - QByteArray ba = QByteArray::fromRawData(raw, int(size)); + Q_ASSERT(raw.size() >= qsizetype(sizeof(header))); + memcpy(&header, raw.data(), sizeof(header)); + if (Q_UNLIKELY(header.version > QPluginMetaData::CurrentMetaDataVersion)) + return setError(QFactoryLoader::tr("Invalid metadata version")); + + // use fromRawData to keep QCborStreamReader from copying + raw = raw.sliced(sizeof(header)); + QByteArray ba = QByteArray::fromRawData(raw.data(), raw.size()); QCborParserError err; QCborValue metadata = QCborValue::fromCbor(ba, &err); - if (err.error != QCborError::NoError) { - *errMsg = QLatin1String("Metadata parsing error: ") + err.error.toString(); - return QJsonDocument(); - } - - if (!metadata.isMap()) { - *errMsg = QStringLiteral("Unexpected metadata contents"); - return QJsonDocument(); - } + if (err.error != QCborError::NoError) + return setError(QFactoryLoader::tr("Metadata parsing error: %1").arg(err.error.toString())); + if (!metadata.isMap()) + return setError(QFactoryLoader::tr("Unexpected metadata contents")); + QCborMap map = metadata.toMap(); + metadata = {}; DecodedArchRequirements archReq = header.version == 0 ? decodeVersion0ArchRequirements(header.plugin_arch_requirements) : decodeVersion1ArchRequirements(header.plugin_arch_requirements); - QJsonObject o; - o.insert(QLatin1String("version"), - QT_VERSION_CHECK(header.qt_major_version, header.qt_minor_version, 0)); - o.insert(QLatin1String("debug"), archReq.isDebug); - o.insert(QLatin1String("archlevel"), archReq.level); + // insert the keys not stored in the top-level CBOR map + map[int(QtPluginMetaDataKeys::QtVersion)] = + QT_VERSION_CHECK(header.qt_major_version, header.qt_minor_version, 0); + map[int(QtPluginMetaDataKeys::IsDebug)] = archReq.isDebug; + map[int(QtPluginMetaDataKeys::Requirements)] = archReq.level; + + data = std::move(map); + return true; +} - // convert the top-level map integer keys - for (auto it : metadata.toMap()) { +QJsonObject QPluginParsedMetaData::toJson() const +{ + // convert from the internal CBOR representation to an external JSON one + QJsonObject o; + for (auto it : data.toMap()) { QString key; if (it.first.isInteger()) { switch (it.first.toInteger()) { #define CONVERT_TO_STRING(IntKey, StringKey, Description) \ case int(IntKey): key = QStringLiteral(StringKey); break; QT_PLUGIN_FOREACH_METADATA(CONVERT_TO_STRING) -#undef CONVERT_TO_STRING - - case int(QtPluginMetaDataKeys::Requirements): - // ignore, handled above - break; } } else { key = it.first.toString(); @@ -122,7 +124,7 @@ QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QStri if (!key.isEmpty()) o.insert(key, it.second.toJsonValue()); } - return QJsonDocument(o); + return o; } class QFactoryLoaderPrivate : public QObjectPrivate @@ -227,12 +229,12 @@ void QFactoryLoader::update() QStringList keys; bool metaDataOk = false; - QString iid = library->metaData.value(QLatin1String("IID")).toString(); + QString iid = library->metaData.value(QtPluginMetaDataKeys::IID).toString(); if (iid == QLatin1String(d->iid.constData(), d->iid.size())) { - QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject(); + QCborMap object = library->metaData.value(QtPluginMetaDataKeys::MetaData).toMap(); metaDataOk = true; - QJsonArray k = object.value(QLatin1String("Keys")).toArray(); + QCborArray k = object.value(QLatin1String("Keys")).toArray(); for (int i = 0; i < k.size(); ++i) keys += d->cs ? k.at(i).toString() : k.at(i).toString().toLower(); } @@ -251,14 +253,14 @@ void QFactoryLoader::update() // library was built with a future Qt version, // whereas the new one has a Qt version that fits // better + constexpr int QtVersionNoPatch = QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, 0); const QString &key = keys.at(k); QLibraryPrivate *previous = d->keyMap.value(key); int prev_qt_version = 0; - if (previous) { - prev_qt_version = (int)previous->metaData.value(QLatin1String("version")).toDouble(); - } - int qt_version = (int)library->metaData.value(QLatin1String("version")).toDouble(); - if (!previous || (prev_qt_version > QT_VERSION && qt_version <= QT_VERSION)) { + if (previous) + prev_qt_version = int(previous->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger()); + int qt_version = int(library->metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger()); + if (!previous || (prev_qt_version > QtVersionNoPatch && qt_version <= QtVersionNoPatch)) { d->keyMap[key] = library; ++keyUsageCount; } @@ -339,7 +341,7 @@ QList<QJsonObject> QFactoryLoader::metaData() const #if QT_CONFIG(library) QMutexLocker locker(&d->mutex); for (int i = 0; i < d->libraryList.size(); ++i) - metaData.append(d->libraryList.at(i)->metaData); + metaData.append(d->libraryList.at(i)->metaData.toJson()); #endif const auto staticPlugins = QPluginLoader::staticPlugins(); diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h index 0ad62cc525..b7536d0349 100644 --- a/src/corelib/plugin/qfactoryloader_p.h +++ b/src/corelib/plugin/qfactoryloader_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2021 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -54,19 +55,44 @@ #include "QtCore/qglobal.h" #ifndef QT_NO_QOBJECT +#include "QtCore/private/qplugin_p.h" +#include "QtCore/qcbormap.h" +#include "QtCore/qcborvalue.h" #include "QtCore/qmap.h" #include "QtCore/qobject.h" - -#if QT_CONFIG(library) -# include "qlibrary_p.h" -#endif +#include "QtCore/qplugin.h" QT_BEGIN_NAMESPACE class QJsonDocument; class QJsonObject; +class QLibraryPrivate; + +class QPluginParsedMetaData +{ + QCborValue data; + bool setError(const QString &errorString) Q_DECL_COLD_FUNCTION + { + data = errorString; + return false; + } +public: + QPluginParsedMetaData() = default; + QPluginParsedMetaData(QByteArrayView input) { parse(input); } + + bool isError() const { return !data.isMap(); } + QString errorString() const { return data.toString(); } + + bool parse(QByteArrayView input); + bool parse(QPluginMetaData metaData) + { return parse(QByteArrayView(reinterpret_cast<const char *>(metaData.data), metaData.size)); } -QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg); + QJsonObject toJson() const; + + // if data is not a map, toMap() returns empty, so shall these functions + QCborMap toCbor() const { return data.toMap(); } + QCborValue value(QtPluginMetaDataKeys k) const { return toCbor()[int(k)]; } +}; class QFactoryLoaderPrivate; class Q_CORE_EXPORT QFactoryLoader : public QObject diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 432b232d27..4eea6f0002 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -270,13 +270,13 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib) QString errMsg = library; QLibraryScanResult r = qt_find_pattern(filedata, fdlen, &errMsg); if (r.length) { - QJsonDocument doc = qJsonFromRawLibraryMetaData(filedata + r.pos, r.length, &errMsg); - if (doc.isNull()) { + if (!lib->metaData.parse(QByteArrayView(filedata + r.pos, r.length))) { + errMsg = lib->metaData.errorString(); qWarning("Found invalid metadata in lib %ls: %ls", qUtf16Printable(library), qUtf16Printable(errMsg)); } else { - lib->metaData = doc.object(); if (qt_debug_component()) { + QJsonDocument doc(lib->metaData.toJson()); qWarning("Found metadata in lib %s, metadata=\n%s\n", library.toLocal8Bit().constData(), doc.toJson().constData()); } @@ -711,13 +711,10 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg) if (metaData.size < sizeof(QPluginMetaData::Header)) return error(QLibrary::tr("metadata too small")); - QJsonDocument doc = qJsonFromRawLibraryMetaData(reinterpret_cast<const char *>(metaData.data), - metaData.size, errMsg); - if (doc.isNull()) - return false; // error message already set - - priv->metaData = doc.object(); - return true; + if (priv->metaData.parse(metaData)) + return true; + *errMsg = priv->metaData.errorString(); + return false; } bool QLibraryPrivate::isPlugin() @@ -773,8 +770,8 @@ void QLibraryPrivate::updatePluginState() pluginState = IsNotAPlugin; // be pessimistic - uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble(); - bool debug = metaData.value(QLatin1String("debug")).toBool(); + uint qt_version = uint(metaData.value(QtPluginMetaDataKeys::QtVersion).toInteger()); + bool debug = metaData.value(QtPluginMetaDataKeys::IsDebug).toBool(); if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) { if (qt_debug_component()) { qWarning("In %s:\n" diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index b42816a469..3c43d79e25 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -52,9 +52,9 @@ // We mean it. // -#include <QtCore/private/qglobal_p.h> - #include "QtCore/qlibrary.h" + +#include "QtCore/private/qfactoryloader_p.h" #include "QtCore/qmutex.h" #include "QtCore/qplugin.h" #include "QtCore/qpointer.h" @@ -111,7 +111,7 @@ public: // the mutex protects the fields below QMutex mutex; QPointer<QObject> inst; // used by QFactoryLoader - QJsonObject metaData; + QPluginParsedMetaData metaData; QString errorString; QString qualifiedFileName; diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h index 80ee02e761..026992ba97 100644 --- a/src/corelib/plugin/qplugin_p.h +++ b/src/corelib/plugin/qplugin_p.h @@ -61,7 +61,8 @@ enum class QtPluginMetaDataKeys { IID, ClassName, MetaData, - URI + URI, + IsDebug, }; // F(IntKey, StringKey, Description) @@ -70,7 +71,12 @@ enum class QtPluginMetaDataKeys { F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \ F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \ F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data") \ - F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI") + F(QtPluginMetaDataKeys::URI, "URI", "Plugin URI") \ + /* not output by moc in CBOR */ \ + F(QtPluginMetaDataKeys::QtVersion, "version", "Qt version") \ + F(QtPluginMetaDataKeys::Requirements, "archlevel", "Architectural level") \ + F(QtPluginMetaDataKeys::IsDebug, "debug", "Debug-mode plugin") \ + /**/ namespace { struct DecodedArchRequirements diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 9afdf0e537..eca85eb82e 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -47,6 +47,10 @@ #include "qfileinfo.h" #include "qjsondocument.h" +#if QT_CONFIG(library) +# include "qlibrary_p.h" +#endif + QT_BEGIN_NAMESPACE #if QT_CONFIG(library) @@ -185,7 +189,7 @@ QJsonObject QPluginLoader::metaData() const { if (!d) return QJsonObject(); - return d->metaData; + return d->metaData.toJson(); } /*! @@ -477,13 +481,10 @@ QList<QStaticPlugin> QPluginLoader::staticPlugins() */ QJsonObject QStaticPlugin::metaData() const { - auto ptr = static_cast<const char *>(rawMetaData); - - QString errMsg; - QJsonDocument doc = qJsonFromRawLibraryMetaData(ptr, rawMetaDataSize, &errMsg); - Q_ASSERT(doc.isObject()); - Q_ASSERT(errMsg.isEmpty()); - return doc.object(); + QByteArrayView data(static_cast<const char *>(rawMetaData), rawMetaDataSize); + QPluginParsedMetaData parsed(data); + Q_ASSERT(!parsed.isError()); + return parsed.toJson(); } QT_END_NAMESPACE |