From 33a870afae5434d9463b9d9877127078cdd3c8e3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 9 Sep 2021 20:11:21 -0700 Subject: [PATCH] QElfParser: don't attempt to parse ELF files of the wrong endianness There's no sense in continuing to parse. We'll never be able to load such a plugin anyway. This simplifies the code generation a lot because now all the read calls become unconditional qFromUnaligned, which is just a memcpy(), which for primitive types the compiler will simply emit a memory load into a register. Task-number: QTBUG-96327 Pick-to: 6.2 Change-Id: I2de1b4dfacd443148279fffd16a3574daf010635 Reviewed-by: Oswald Buddenhagen Reviewed-by: Lars Knoll --- src/corelib/plugin/qelfparser_p.cpp | 23 ++++++++++++----------- src/corelib/plugin/qelfparser_p.h | 10 ---------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp index 84373795f61..46df38debc7 100644 --- a/src/corelib/plugin/qelfparser_p.cpp +++ b/src/corelib/plugin/qelfparser_p.cpp @@ -50,15 +50,15 @@ QT_BEGIN_NAMESPACE const char *QElfParser::parseSectionHeader(const char *data, ElfSectionHeader *sh) { - sh->name = read(data); + sh->name = qFromUnaligned(data); data += sizeof(qelfword_t); // sh_name - sh->type = read(data); + sh->type = qFromUnaligned(data); data += sizeof(qelfword_t) // sh_type + sizeof(qelfaddr_t) // sh_flags + sizeof(qelfaddr_t); // sh_addr - sh->offset = read(data); + sh->offset = qFromUnaligned(data); data += sizeof(qelfoff_t); // sh_offset - sh->size = read(data); + sh->size = qFromUnaligned(data); data += sizeof(qelfoff_t); // sh_size return data; } @@ -97,13 +97,14 @@ auto QElfParser::parse(const char *dataStart, ulong fdlen, const QString &librar lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, QLibrary::tr("wrong cpu architecture")); return Corrupt; } + // endian - if (data[5] == 0) { + constexpr int ExpectedEndianness = (Q_BYTE_ORDER == Q_LITTLE_ENDIAN) ? 1 : 2; + if (data[5] != ExpectedEndianness) { if (lib) lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library, QLibrary::tr("odd endianness")); return Corrupt; } - m_endian = (data[5] == 1 ? ElfLittleEndian : ElfBigEndian); data += 16 // e_ident + sizeof(qelfhalf_t) // e_type @@ -112,11 +113,11 @@ auto QElfParser::parse(const char *dataStart, ulong fdlen, const QString &librar + sizeof(qelfaddr_t) // e_entry + sizeof(qelfoff_t); // e_phoff - qelfoff_t e_shoff = read (data); + qelfoff_t e_shoff = qFromUnaligned (data); data += sizeof(qelfoff_t) // e_shoff + sizeof(qelfword_t); // e_flags - qelfhalf_t e_shsize = read (data); + qelfhalf_t e_shsize = qFromUnaligned (data); if (e_shsize > fdlen) { if (lib) @@ -128,7 +129,7 @@ auto QElfParser::parse(const char *dataStart, ulong fdlen, const QString &librar + sizeof(qelfhalf_t) // e_phentsize + sizeof(qelfhalf_t); // e_phnum - qelfhalf_t e_shentsize = read (data); + qelfhalf_t e_shentsize = qFromUnaligned (data); if (e_shentsize % 4) { if (lib) @@ -136,9 +137,9 @@ auto QElfParser::parse(const char *dataStart, ulong fdlen, const QString &librar return Corrupt; } data += sizeof(qelfhalf_t); // e_shentsize - qelfhalf_t e_shnum = read (data); + qelfhalf_t e_shnum = qFromUnaligned (data); data += sizeof(qelfhalf_t); // e_shnum - qelfhalf_t e_shtrndx = read (data); + qelfhalf_t e_shtrndx = qFromUnaligned (data); data += sizeof(qelfhalf_t); // e_shtrndx if ((quint32)(e_shnum * e_shentsize) > fdlen) { diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h index 796b987eb31..0a3470dab72 100644 --- a/src/corelib/plugin/qelfparser_p.h +++ b/src/corelib/plugin/qelfparser_p.h @@ -82,19 +82,9 @@ public: qelfoff_t size; }; - int m_endian; int m_bits; qelfoff_t m_stringTableFileOffset; - template - T read(const char *s) - { - if (m_endian == ElfBigEndian) - return qFromBigEndian(s); - else - return qFromLittleEndian(s); - } - const char *parseSectionHeader(const char* s, ElfSectionHeader *sh); ScanResult parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, qsizetype *pos, qsizetype *sectionlen); };