summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>2014-05-15 13:32:27 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-28 16:52:04 +0200
commit909b0de5d16f2af3b3d6a3ca4c7e53b84836ad37 (patch)
tree07fa654820332e52af54c51c6be35054315246bd /src/plugins
parent3478ec29494c315c4e41f25a1265da928503694b (diff)
Windows: Fix another crash when creating QRawFont from invalid data
The sanity check added in d16508a285a5423ae9a5034e969801bce74ffb98 didn't actually catch the case where the invalid data is large enough to contain the offset table and table directory. Added sanity checks to all the code that accesses the font data now, so this should fix crashes with partial data as well as invalid data. Task-number: QTBUG-37190 Change-Id: Ie43f10d8cf0b09007783b9b1c4d91bfed8c6b0f0 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 6d9f01da4e..696dc06cee 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -164,15 +164,18 @@ namespace {
{
Q_ASSERT(tagName.size() == 4);
quint32 tagId = *(reinterpret_cast<const quint32 *>(tagName.constData()));
-
- if (m_fontData.size() < sizeof(OffsetSubTable) + sizeof(TableDirectory))
+ if (Q_UNLIKELY(m_fontData.size() < sizeof(OffsetSubTable)))
return 0;
OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data());
TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1);
+ quint16 tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables);
+ if (Q_UNLIKELY(quint32(m_fontData.size()) < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount))
+ return 0;
+
TableDirectory *nameTableDirectoryEntry = 0;
- for (int i = 0; i < qFromBigEndian<quint16>(offsetSubTable->numTables); ++i, ++tableDirectory) {
+ for (int i = 0; i < tableCount; ++i, ++tableDirectory) {
if (tableDirectory->identifier == tagId) {
nameTableDirectoryEntry = tableDirectory;
break;
@@ -190,19 +193,34 @@ namespace {
nameTableDirectoryEntry = tableDirectoryEntry("name");
if (nameTableDirectoryEntry != 0) {
- NameTable *nameTable = reinterpret_cast<NameTable *>(
- m_fontData.data() + qFromBigEndian<quint32>(nameTableDirectoryEntry->offset));
+ quint32 offset = qFromBigEndian<quint32>(nameTableDirectoryEntry->offset);
+ if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameTable)))
+ return QString();
+
+ NameTable *nameTable = reinterpret_cast<NameTable *>(m_fontData.data() + offset);
NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
- for (int i = 0; i < qFromBigEndian<quint16>(nameTable->count); ++i, ++nameRecord) {
+
+ quint16 nameTableCount = qFromBigEndian<quint16>(nameTable->count);
+ if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameRecord) * nameTableCount))
+ return QString();
+
+ for (int i = 0; i < nameTableCount; ++i, ++nameRecord) {
if (qFromBigEndian<quint16>(nameRecord->nameID) == 1
&& qFromBigEndian<quint16>(nameRecord->platformID) == 3 // Windows
&& qFromBigEndian<quint16>(nameRecord->languageID) == 0x0409) { // US English
+ quint16 stringOffset = qFromBigEndian<quint16>(nameTable->stringOffset);
+ quint16 nameOffset = qFromBigEndian<quint16>(nameRecord->offset);
+ quint16 nameLength = qFromBigEndian<quint16>(nameRecord->length);
+
+ if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + stringOffset + nameOffset + nameLength))
+ return QString();
+
const void *ptr = reinterpret_cast<const quint8 *>(nameTable)
- + qFromBigEndian<quint16>(nameTable->stringOffset)
- + qFromBigEndian<quint16>(nameRecord->offset);
+ + stringOffset
+ + nameOffset;
const quint16 *s = reinterpret_cast<const quint16 *>(ptr);
- const quint16 *e = s + qFromBigEndian<quint16>(nameRecord->length) / sizeof(quint16);
+ const quint16 *e = s + nameLength / sizeof(quint16);
while (s != e)
name += QChar( qFromBigEndian<quint16>(*s++));
break;