diff options
-rw-r--r-- | src/corelib/plugin/plugin.pri | 6 | ||||
-rw-r--r-- | src/corelib/plugin/qelfparser_p.cpp | 234 | ||||
-rw-r--r-- | src/corelib/plugin/qelfparser_p.h | 103 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary.cpp | 28 | ||||
-rw-r--r-- | tests/auto/qpluginloader/elftest/.gitattributes | 10 | ||||
-rwxr-xr-x | tests/auto/qpluginloader/elftest/corrupt1.elf64.so | bin | 239745 -> 0 bytes | |||
-rwxr-xr-x | tests/auto/qpluginloader/elftest/corrupt2.elf64.so | bin | 240097 -> 0 bytes | |||
-rwxr-xr-x | tests/auto/qpluginloader/elftest/corrupt3.elf64.so | bin | 240097 -> 0 bytes | |||
-rw-r--r-- | tests/auto/qpluginloader/elftest/debugobj.so | bin | 507232 -> 0 bytes | |||
-rw-r--r-- | tests/auto/qpluginloader/elftest/garbage1.so | 4 | ||||
-rw-r--r-- | tests/auto/qpluginloader/elftest/garbage2.so | 1 | ||||
-rw-r--r-- | tests/auto/qpluginloader/elftest/garbage3.so | 1 | ||||
-rw-r--r-- | tests/auto/qpluginloader/elftest/garbage4.so | 1 | ||||
-rw-r--r-- | tests/auto/qpluginloader/elftest/garbage5.so | 2 | ||||
-rw-r--r-- | tests/auto/qpluginloader/tst_qpluginloader.cpp | 81 |
15 files changed, 7 insertions, 464 deletions
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri index 2e7db5d..2e986ec 100644 --- a/src/corelib/plugin/plugin.pri +++ b/src/corelib/plugin/plugin.pri @@ -7,15 +7,13 @@ HEADERS += \ plugin/qlibrary_p.h \ plugin/qplugin.h \ plugin/quuid.h \ - plugin/qfactoryloader_p.h \ - plugin/qelfparser_p.h + plugin/qfactoryloader_p.h SOURCES += \ plugin/qpluginloader.cpp \ plugin/qfactoryloader.cpp \ plugin/quuid.cpp \ - plugin/qlibrary.cpp \ - plugin/qelfparser_p.cpp + plugin/qlibrary.cpp win32 { SOURCES += plugin/qlibrary_win.cpp diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp deleted file mode 100644 index 97008fd..0000000 --- a/src/corelib/plugin/qelfparser_p.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qlibrary_p.h" -#include "qelfparser_p.h" -#include <qdebug.h> - -QT_BEGIN_NAMESPACE - -// #define QELFPARSER_DEBUG 1 - -const char *QElfParser::parseSectionHeader(const char *data, ElfSectionHeader *sh) -{ - sh->name = read<qelfword_t>(data); - data += sizeof(qelfword_t); // sh_name - sh->type = read<qelfword_t>(data); - data += sizeof(qelfword_t) // sh_type - + sizeof(qelfaddr_t) // sh_flags - + sizeof(qelfaddr_t); // sh_addr - sh->offset = read<qelfoff_t>(data); - data += sizeof(qelfoff_t); // sh_offset - sh->size = read<qelfword_t>(data); - data += sizeof(qelfword_t); // sh_size - return data; -} - -int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen) -{ -#if defined(QELFPARSER_DEBUG) - qDebug() << "QElfParser::parse " << library; -#endif - - if (fdlen < 64){ - if (lib) - lib->errorString = QLibrary::tr("'%1' is not an ELF object (%2)").arg(library).arg(QLatin1String("file too small")); - return NotElf; - } - const char *data = dataStart; - if (qstrncmp(data, "\177ELF", 4) != 0) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is not an ELF object").arg(library); - return NotElf; - } - // 32 or 64 bit - if (data[4] != 1 && data[4] != 2) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd cpu architecture")); - return Corrupt; - } - m_bits = (data[4] << 5); - - /* If you remove this check, to read ELF objects of a different arch, please make sure you modify the typedefs - to match the _plugin_ architecture. - */ - if ((sizeof(void*) == 4 && m_bits != 32) || (sizeof(void*) == 8 && m_bits != 64)) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("wrong cpu architecture")); - return Corrupt; - } - // endian - if (data[5] == 0) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd endianess")); - return Corrupt; - } - m_endian = (data[5] == 1 ? ElfLittleEndian : ElfBigEndian); - - data += 16 // e_ident - + sizeof(qelfhalf_t) // e_type - + sizeof(qelfhalf_t) // e_machine - + sizeof(qelfword_t) // e_version - + sizeof(qelfaddr_t) // e_entry - + sizeof(qelfoff_t); // e_phoff - - qelfoff_t e_shoff = read<qelfoff_t> (data); - data += sizeof(qelfoff_t) // e_shoff - + sizeof(qelfword_t); // e_flags - - qelfhalf_t e_shsize = read<qelfhalf_t> (data); - - if (e_shsize > fdlen) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shsize")); - return Corrupt; - } - - data += sizeof(qelfhalf_t) // e_ehsize - + sizeof(qelfhalf_t) // e_phentsize - + sizeof(qelfhalf_t); // e_phnum - - qelfhalf_t e_shentsize = read<qelfhalf_t> (data); - - if (e_shentsize % 8){ - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shentsize")); - return Corrupt; - } - data += sizeof(qelfhalf_t); // e_shentsize - qelfhalf_t e_shnum = read<qelfhalf_t> (data); - data += sizeof(qelfhalf_t); // e_shnum - qelfhalf_t e_shtrndx = read<qelfhalf_t> (data); - data += sizeof(qelfhalf_t); // e_shtrndx - - if ((e_shnum * e_shentsize) > fdlen) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) - .arg(QLatin1String("announced %2 sections, each %3 bytes, exceed file size")) - .arg(e_shnum).arg(e_shentsize); - return Corrupt; - } - -#if defined(QELFPARSER_DEBUG) - qDebug() << e_shnum << "sections starting at " << ("0x" + QByteArray::number(e_shoff, 16)).data() << "each" << e_shentsize << "bytes"; -#endif - - ElfSectionHeader strtab; - qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); - - if ((soff + e_shentsize) > fdlen || soff % 8 || soff == 0) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) - .arg(QLatin1String("strtab section seems to be at %1")) - .arg(QString::number(soff, 16)); - return Corrupt; - } - - parseSectionHeader(dataStart + soff, &strtab); - m_stringTableFileOffset = strtab.offset; - - if ((m_stringTableFileOffset + e_shentsize) >= fdlen || m_stringTableFileOffset == 0) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) - .arg(QLatin1String("string table seems to be at %1")) - .arg(QString::number(soff, 16)); - return Corrupt; - } - -#if defined(QELFPARSER_DEBUG) - qDebug(".shstrtab at 0x%s", QByteArray::number(m_stringTableFileOffset, 16).data()); -#endif - - const char *s = dataStart + e_shoff; - for (int i = 0; i < e_shnum; ++i) { - ElfSectionHeader sh; - parseSectionHeader(s, &sh); - if (sh.name == 0) { - s += e_shentsize; - continue; - } - const char *shnam = dataStart + m_stringTableFileOffset + sh.name; - - if (m_stringTableFileOffset + sh.name > fdlen) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) - .arg(QLatin1String("section name %2 of %3 behind end of file")) - .arg(i).arg(e_shnum); - return Corrupt; - } - -#if defined(QELFPARSER_DEBUG) - qDebug() << "++++" << i << shnam; -#endif - - if (qstrcmp(shnam, ".qtplugin") == 0 || qstrcmp(shnam, ".rodata") == 0) { - if (!(sh.type & 0x1)) { - if (shnam[1] == 'r') { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) - .arg(QLatin1String("empty .rodata. not a library.")); - return Corrupt; - } -#if defined(QELFPARSER_DEBUG) - qDebug()<<"section is not program data. skipped."; -#endif - s += e_shentsize; - continue; - } - - if (sh.offset == 0 || (sh.offset + sh.size) > fdlen) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) - .arg(QLatin1String("missing section data. This is not a library.")); - return Corrupt; - } - *pos = sh.offset; - *sectionlen = sh.size - 1; - if (shnam[1] == 'q') - return Ok; - } - s += e_shentsize; - } - return NoQtSection; -} - -QT_END_NAMESPACE - diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h deleted file mode 100644 index 380d5a1..0000000 --- a/src/corelib/plugin/qelfparser_p.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QELFPARSER_P_H -#define QELFPARSER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qendian.h> -#include <qglobal.h> - -QT_BEGIN_NAMESPACE - -class QString; -class QLibraryPrivate; - -typedef quint16 qelfhalf_t; -typedef quint32 qelfword_t; -typedef quintptr qelfoff_t; -typedef quintptr qelfaddr_t; - -class QElfParser -{ -public: - enum {Ok = 0, NotElf = 1, NoQtSection = 2, Corrupt = 3}; - enum {ElfLittleEndian = 0, ElfBigEndian = 1}; - - struct ElfSectionHeader - { - qelfword_t name; - qelfword_t type; - qelfoff_t offset; - qelfword_t size; - }; - - int m_endian; - int m_bits; - int m_stringTableFileOffset; - - template <typename T> - T read(const char *s) - { - if (m_endian == ElfBigEndian) - return qFromBigEndian<T>(reinterpret_cast<const uchar *>(s)); - else - return qFromLittleEndian<T>(reinterpret_cast<const uchar *>(s)); - } - - const char *parseSectionHeader(const char* s, ElfSectionHeader *sh); - int parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen); -}; - -QT_END_NAMESPACE - -#endif // QELFPARSER_P_H - diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 8f82cc4..1ca9d70 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "qplatformdefs.h" #include "qlibrary.h" @@ -60,7 +61,6 @@ #include <qdebug.h> #include <qvector.h> #include <qdir.h> -#include "qelfparser_p.h" QT_BEGIN_NAMESPACE @@ -365,31 +365,11 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB fdlen = data.size(); } - /* - ELF binaries on GNU, have .qplugin sections. - */ - long pos = 0; + // verify that the pattern is present in the plugin const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; const ulong plen = qstrlen(pattern); -#if defined (Q_OF_ELF) && defined(Q_CC_GNU) - int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen); - if (r == QElfParser::NoQtSection) { - if (pos > 0) { - // find inside .rodata - long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen); - if (rel < 0) { - pos = -1; - } else { - pos += rel; - } - } else { - pos = qt_find_pattern(filedata, fdlen, pattern, plen); - } - } else if (r != QElfParser::Ok) - return false; -#else - pos = qt_find_pattern(filedata, fdlen, pattern, plen); -#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) + long pos = qt_find_pattern(filedata, fdlen, pattern, plen); + bool ret = false; if (pos >= 0) ret = qt_parse_pattern(filedata + pos, version, debug, key); diff --git a/tests/auto/qpluginloader/elftest/.gitattributes b/tests/auto/qpluginloader/elftest/.gitattributes deleted file mode 100644 index 891192c..0000000 --- a/tests/auto/qpluginloader/elftest/.gitattributes +++ /dev/null @@ -1,10 +0,0 @@ -corrupt1.elf64.so set -crlf -diff -corrupt2.elf64.so set -crlf -diff -corrupt3.elf64.so set -crlf -diff -debugobj.so set -crlf -diff -garbage1.so set -crlf -diff -garbage2.so set -crlf -diff -garbage3.so set -crlf -diff -garbage4.so set -crlf -diff -garbage5.so set -crlf -diff - diff --git a/tests/auto/qpluginloader/elftest/corrupt1.elf64.so b/tests/auto/qpluginloader/elftest/corrupt1.elf64.so Binary files differdeleted file mode 100755 index 12ce736..0000000 --- a/tests/auto/qpluginloader/elftest/corrupt1.elf64.so +++ /dev/null diff --git a/tests/auto/qpluginloader/elftest/corrupt2.elf64.so b/tests/auto/qpluginloader/elftest/corrupt2.elf64.so Binary files differdeleted file mode 100755 index 11fdc2c..0000000 --- a/tests/auto/qpluginloader/elftest/corrupt2.elf64.so +++ /dev/null diff --git a/tests/auto/qpluginloader/elftest/corrupt3.elf64.so b/tests/auto/qpluginloader/elftest/corrupt3.elf64.so Binary files differdeleted file mode 100755 index 94a2bc3..0000000 --- a/tests/auto/qpluginloader/elftest/corrupt3.elf64.so +++ /dev/null diff --git a/tests/auto/qpluginloader/elftest/debugobj.so b/tests/auto/qpluginloader/elftest/debugobj.so Binary files differdeleted file mode 100644 index f0ee056..0000000 --- a/tests/auto/qpluginloader/elftest/debugobj.so +++ /dev/null diff --git a/tests/auto/qpluginloader/elftest/garbage1.so b/tests/auto/qpluginloader/elftest/garbage1.so deleted file mode 100644 index 0c74530..0000000 --- a/tests/auto/qpluginloader/elftest/garbage1.so +++ /dev/null @@ -1,4 +0,0 @@ -pcdL+&&e= -oÒʎIٝmg]!Z -L')t -N(eP)Y8G 6-y"Zk4?^n5$Y=#y
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage2.so b/tests/auto/qpluginloader/elftest/garbage2.so deleted file mode 100644 index c06338e..0000000 --- a/tests/auto/qpluginloader/elftest/garbage2.so +++ /dev/null @@ -1 +0,0 @@ -v.YtKW3
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage3.so b/tests/auto/qpluginloader/elftest/garbage3.so deleted file mode 100644 index a24c523..0000000 --- a/tests/auto/qpluginloader/elftest/garbage3.so +++ /dev/null @@ -1 +0,0 @@ -ȂT-ڥ 쾜i8_xIx=4@[BKS$
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage4.so b/tests/auto/qpluginloader/elftest/garbage4.so deleted file mode 100644 index 4f45cf5..0000000 --- a/tests/auto/qpluginloader/elftest/garbage4.so +++ /dev/null @@ -1 +0,0 @@ -!\~Uu:9T+91QEǚxng5zh^t'mm*ˈdXH;vw+G
9L0!
\ No newline at end of file diff --git a/tests/auto/qpluginloader/elftest/garbage5.so b/tests/auto/qpluginloader/elftest/garbage5.so deleted file mode 100644 index f8c0a1d..0000000 --- a/tests/auto/qpluginloader/elftest/garbage5.so +++ /dev/null @@ -1,2 +0,0 @@ -Q --9
\ No newline at end of file diff --git a/tests/auto/qpluginloader/tst_qpluginloader.cpp b/tests/auto/qpluginloader/tst_qpluginloader.cpp index 9374dd0..1e382b8 100644 --- a/tests/auto/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/qpluginloader/tst_qpluginloader.cpp @@ -100,14 +100,6 @@ # define PREFIX "lib" #endif -#ifdef QT_NO_DEBUG -# define QLIBRARY_AS_DEBUG false -#else -# define QLIBRARY_AS_DEBUG true -#endif - -// #define SHOW_ERRORS 1 - static QString sys_qualifiedLibraryName(const QString &fileName) { QString currDir = QDir::currentPath(); @@ -127,14 +119,10 @@ public: virtual ~tst_QPluginLoader(); private slots: - void clearPluginCache(); void errorString(); void loadHints(); void deleteinstanceOnUnload(); void checkingStubsFromDifferentDrives(); - void loadDebugObj(); - void loadCorruptElf(); - void loadGarbage(); }; tst_QPluginLoader::tst_QPluginLoader() @@ -146,25 +134,7 @@ tst_QPluginLoader::~tst_QPluginLoader() { } -void tst_QPluginLoader::clearPluginCache() -{ - QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3") - .arg((QT_VERSION & 0xff0000) >> 16) - .arg((QT_VERSION & 0xff00) >> 8) - .arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false")); -#ifdef Q_WS_MAC -#if defined(__x86_64__) - regkey += QLatin1String("-x86_64"); -#elif defined(__i386__) - regkey += QLatin1String("-i386"); -#elif defined(__ppc64__) - regkey += QLatin1String("-ppc64"); -#elif defined(__ppc__) - regkey += QLatin1String("-ppc"); -#endif -#endif // Q_WS_MAC - QSettings(QSettings::UserScope, QLatin1String("Trolltech")).remove(regkey); -} +//#define SHOW_ERRORS 1 void tst_QPluginLoader::errorString() { @@ -380,54 +350,5 @@ void tst_QPluginLoader::checkingStubsFromDifferentDrives() #endif//Q_OS_SYMBIAN } -void tst_QPluginLoader::loadDebugObj() -{ -#if defined (__ELF__) - QVERIFY(QFile::exists(SRCDIR "elftest/debugobj.so")); - QPluginLoader lib1(SRCDIR "elftest/debugobj.so"); - QCOMPARE(lib1.load(), false); -#endif -} - -void tst_QPluginLoader::loadCorruptElf() -{ -#if defined (__ELF__) -if (sizeof(void*) == 8) { - QVERIFY(QFile::exists(SRCDIR "elftest/corrupt1.elf64.so")); - - QPluginLoader lib1(SRCDIR "elftest/corrupt1.elf64.so"); - QCOMPARE(lib1.load(), false); - QVERIFY(lib1.errorString().contains("not an ELF object")); - - QPluginLoader lib2(SRCDIR "elftest/corrupt2.elf64.so"); - QCOMPARE(lib2.load(), false); - QVERIFY(lib2.errorString().contains("invalid")); - - QPluginLoader lib3(SRCDIR "elftest/corrupt3.elf64.so"); - QCOMPARE(lib3.load(), false); - QVERIFY(lib3.errorString().contains("invalid")); -} else if (sizeof(void*) == 4) { - QPluginLoader libW(SRCDIR "elftest/corrupt3.elf64.so"); - QCOMPARE(libW.load(), false); - QVERIFY(libW.errorString().contains("architecture")); -} else { - QFAIL("Please port QElfParser to this platform or blacklist this test."); -} -#endif -} - -void tst_QPluginLoader::loadGarbage() -{ -#if defined (Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) - for (int i=0; i<5; i++) { - QPluginLoader lib(QString(SRCDIR "elftest/garbage%1.so").arg(i)); - QCOMPARE(lib.load(), false); -#ifdef SHOW_ERRORS - qDebug() << lib.errorString(); -#endif - } -#endif -} - QTEST_APPLESS_MAIN(tst_QPluginLoader) #include "tst_qpluginloader.moc" |