summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-09-02 01:00:14 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-09-02 01:00:15 +0200
commitae868dfbdc7235fef9aeeac015f448d129d5f358 (patch)
tree303db0a06517b0ef916a3bca02acb184e34ef074 /src/corelib/plugin
parentfb63d912e7f68e149c63a10f7cc2e14a840cb8e0 (diff)
parent7bd79b3cffbbbece23867c5e111a3dd2ebcad016 (diff)
Merge remote-tracking branch 'origin/5.12' into dev
Diffstat (limited to 'src/corelib/plugin')
-rw-r--r--src/corelib/plugin/plugin.pri1
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp91
-rw-r--r--src/corelib/plugin/qfactoryloader_p.h3
-rw-r--r--src/corelib/plugin/qlibrary.cpp44
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp4
-rw-r--r--src/corelib/plugin/qplugin.h15
-rw-r--r--src/corelib/plugin/qplugin_p.h75
-rw-r--r--src/corelib/plugin/qpluginloader.cpp11
-rw-r--r--src/corelib/plugin/qsystemlibrary.cpp2
9 files changed, 211 insertions, 35 deletions
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri
index a0e0d76044..13153e8d0a 100644
--- a/src/corelib/plugin/plugin.pri
+++ b/src/corelib/plugin/plugin.pri
@@ -4,6 +4,7 @@ HEADERS += \
plugin/qfactoryinterface.h \
plugin/qpluginloader.h \
plugin/qplugin.h \
+ plugin/qplugin_p.h \
plugin/quuid.h \
plugin/qfactoryloader_p.h
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 0b35f41ca3..35c64180d4 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -47,9 +47,12 @@
#include <qdebug.h>
#include "qmutex.h"
#include "qplugin.h"
+#include "qplugin_p.h"
#include "qpluginloader.h"
#include "private/qobject_p.h"
#include "private/qcoreapplication_p.h"
+#include "qcbormap.h"
+#include "qcborvalue.h"
#include "qjsondocument.h"
#include "qjsonvalue.h"
#include "qjsonobject.h"
@@ -64,22 +67,86 @@ static inline int metaDataSignatureLength()
return sizeof("QTMETADATA ") - 1;
}
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize)
+static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QString *errMsg)
+{
+ // 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);
+
+ 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();
+ }
+
+ 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()) {
+ 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):
+ // special case: recreate the debug key
+ o.insert(QLatin1String("debug"), bool(it.second.toInteger() & 1));
+ key = QStringLiteral("archreq");
+ break;
+ }
+ } else {
+ key = it.first.toString();
+ }
+
+ if (!key.isEmpty())
+ o.insert(key, it.second.toJsonValue());
+ }
+ return QJsonDocument(o);
+}
+
+QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize, QString *errMsg)
{
raw += metaDataSignatureLength();
sectionSize -= metaDataSignatureLength();
- // the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
- uint size = qFromLittleEndian<uint>(raw + 8);
- // but the maximum size of binary JSON is 128 MB
- size = qMin(size, 128U * 1024 * 1024);
- // and it doesn't include the size of the header (8 bytes)
- size += 8;
- // finally, it can't be bigger than the file or section size
- size = qMin(sectionSize, qsizetype(size));
-
- QByteArray json(raw, size);
- return QJsonDocument::fromBinaryData(json);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ if (Q_UNLIKELY(raw[-1] == ' ')) {
+ // the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
+ uint size = qFromLittleEndian<uint>(raw + 8);
+ // but the maximum size of binary JSON is 128 MB
+ size = qMin(size, 128U * 1024 * 1024);
+ // and it doesn't include the size of the header (8 bytes)
+ size += 8;
+ // finally, it can't be bigger than the file or section size
+ size = qMin(sectionSize, qsizetype(size));
+
+ QByteArray json(raw, size);
+ return QJsonDocument::fromBinaryData(json);
+ }
+#endif
+
+ return jsonFromCborMetaData(raw, sectionSize, errMsg);
}
class QFactoryLoaderPrivate : public QObjectPrivate
diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h
index fe722999ae..7815ea0b5d 100644
--- a/src/corelib/plugin/qfactoryloader_p.h
+++ b/src/corelib/plugin/qfactoryloader_p.h
@@ -56,6 +56,7 @@
#include "QtCore/qobject.h"
#include "QtCore/qstringlist.h"
+#include "QtCore/qcborvalue.h"
#include "QtCore/qjsonobject.h"
#include "QtCore/qjsondocument.h"
#include "QtCore/qmap.h"
@@ -66,7 +67,7 @@
QT_BEGIN_NAMESPACE
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size);
+QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg);
class QFactoryLoaderPrivate;
class Q_CORE_EXPORT QFactoryLoader : public QObject
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 869ef6181f..aa63ed1a6b 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -268,7 +268,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
*/
bool hasMetaData = false;
qsizetype pos = 0;
- char pattern[] = "qTMETADATA ";
+ char pattern[] = "qTMETADATA ";
pattern[0] = 'Q'; // Ensure the pattern "QTMETADATA" is not found in this library should QPluginLoader ever encounter it.
const ulong plen = qstrlen(pattern);
#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
@@ -314,10 +314,14 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
bool ret = false;
- if (pos >= 0) {
- if (hasMetaData) {
- const char *data = filedata + pos;
- QJsonDocument doc = qJsonFromRawLibraryMetaData(data, qsizetype(fdlen));
+ if (pos >= 0 && hasMetaData) {
+ const char *data = filedata + pos;
+ QString errMsg;
+ QJsonDocument doc = qJsonFromRawLibraryMetaData(data, fdlen, &errMsg);
+ if (doc.isNull()) {
+ qWarning("Found invalid metadata in lib %s: %s",
+ qPrintable(library), qPrintable(errMsg));
+ } else {
lib->metaData = doc.object();
if (qt_debug_component())
qWarning("Found metadata in lib %s, metadata=\n%s\n",
@@ -679,20 +683,26 @@ bool QLibrary::isLibrary(const QString &fileName)
#endif
}
-typedef const char * (*QtPluginQueryVerificationDataFunction)();
-
-static bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv)
+static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
{
- const char *szData = 0;
- if (!pfn)
- return false;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ auto getMetaData = [](QFunctionPointer fptr) {
+ auto f = reinterpret_cast<const char * (*)()>(fptr);
+ return qMakePair<const char *, size_t>(f(), INT_MAX);
+ };
+#else
+ auto getMetaData = [](QFunctionPointer fptr) {
+ auto f = reinterpret_cast<QPair<const char *, size_t> (*)()>(fptr);
+ return f();
+ };
+#endif
- szData = pfn();
- if (!szData)
+ QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata");
+ if (!pfn)
return false;
- // the data is already loaded, so the size doesn't matter
- QJsonDocument doc = qJsonFromRawLibraryMetaData(szData, INT_MAX);
+ auto metaData = getMetaData(pfn);
+ QJsonDocument doc = qJsonFromRawLibraryMetaData(metaData.first, metaData.second, errMsg);
if (doc.isNull())
return false;
priv->metaData = doc.object();
@@ -735,9 +745,7 @@ void QLibraryPrivate::updatePluginState()
} else {
// library is already loaded (probably via QLibrary)
// simply get the target function and call it.
- QtPluginQueryVerificationDataFunction getMetaData = NULL;
- getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");
- success = qt_get_metadata(getMetaData, this);
+ success = qt_get_metadata(this, &errorString);
}
if (!success) {
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index 9368e53b3f..05a93d467e 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -97,10 +97,10 @@ bool QLibraryPrivate::load_sys()
for (const QString &attempt : qAsConst(attempts)) {
#ifndef Q_OS_WINRT
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
+ pHnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
#else // Q_OS_WINRT
QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt));
- pHnd = LoadPackagedLibrary((LPCWSTR)path.utf16(), 0);
+ pHnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
if (pHnd)
qualifiedFileName = attempt;
#endif // !Q_OS_WINRT
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index c8200afeeb..676b5047d6 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -56,6 +56,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)();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
typedef const char *(*QtPluginMetaDataFunction)();
diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h
new file mode 100644
index 0000000000..717129268b
--- /dev/null
+++ b/src/corelib/plugin/qplugin_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLUGIN_P_H
+#define QPLUGIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+enum class QtPluginMetaDataKeys {
+ QtVersion,
+ Requirements,
+ IID,
+ ClassName,
+ MetaData
+};
+
+// F(IntKey, StringKey, Description)
+// Keep this list sorted in the order moc should output.
+#define QT_PLUGIN_FOREACH_METADATA(F) \
+ F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
+ F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
+ F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data")
+
+QT_END_NAMESPACE
+
+#endif // QPLUGIN_P_H
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 83cbcd2b44..0f94bb6adf 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -475,10 +475,19 @@ QVector<QStaticPlugin> QPluginLoader::staticPlugins()
*/
QJsonObject QStaticPlugin::metaData() const
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// the data is already loaded, so this doesn't matter
qsizetype rawMetaDataSize = INT_MAX;
+ const char *ptr = rawMetaData();
+#else
+ auto ptr = static_cast<const char *>(rawMetaData);
+#endif
- return qJsonFromRawLibraryMetaData(rawMetaData(), rawMetaDataSize).object();
+ QString errMsg;
+ QJsonDocument doc = qJsonFromRawLibraryMetaData(ptr, rawMetaDataSize, &errMsg);
+ Q_ASSERT(doc.isObject());
+ Q_ASSERT(errMsg.isEmpty());
+ return doc.object();
}
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp
index 7c80fbbd42..1f8cef790c 100644
--- a/src/corelib/plugin/qsystemlibrary.cpp
+++ b/src/corelib/plugin/qsystemlibrary.cpp
@@ -121,7 +121,7 @@ HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirect
fullPathAttempt.append(QLatin1Char('\\'));
}
fullPathAttempt.append(fileName);
- HINSTANCE inst = ::LoadLibrary((const wchar_t *)fullPathAttempt.utf16());
+ HINSTANCE inst = ::LoadLibrary(reinterpret_cast<const wchar_t *>(fullPathAttempt.utf16()));
if (inst != 0)
return inst;
}