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(tagName.constData())); - - if (m_fontData.size() < sizeof(OffsetSubTable) + sizeof(TableDirectory)) + if (Q_UNLIKELY(m_fontData.size() < sizeof(OffsetSubTable))) return 0; OffsetSubTable *offsetSubTable = reinterpret_cast(m_fontData.data()); TableDirectory *tableDirectory = reinterpret_cast(offsetSubTable + 1); + quint16 tableCount = qFromBigEndian(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(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( - m_fontData.data() + qFromBigEndian(nameTableDirectoryEntry->offset)); + quint32 offset = qFromBigEndian(nameTableDirectoryEntry->offset); + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameTable))) + return QString(); + + NameTable *nameTable = reinterpret_cast(m_fontData.data() + offset); NameRecord *nameRecord = reinterpret_cast(nameTable + 1); - for (int i = 0; i < qFromBigEndian(nameTable->count); ++i, ++nameRecord) { + + quint16 nameTableCount = qFromBigEndian(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(nameRecord->nameID) == 1 && qFromBigEndian(nameRecord->platformID) == 3 // Windows && qFromBigEndian(nameRecord->languageID) == 0x0409) { // US English + quint16 stringOffset = qFromBigEndian(nameTable->stringOffset); + quint16 nameOffset = qFromBigEndian(nameRecord->offset); + quint16 nameLength = qFromBigEndian(nameRecord->length); + + if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + stringOffset + nameOffset + nameLength)) + return QString(); + const void *ptr = reinterpret_cast(nameTable) - + qFromBigEndian(nameTable->stringOffset) - + qFromBigEndian(nameRecord->offset); + + stringOffset + + nameOffset; const quint16 *s = reinterpret_cast(ptr); - const quint16 *e = s + qFromBigEndian(nameRecord->length) / sizeof(quint16); + const quint16 *e = s + nameLength / sizeof(quint16); while (s != e) name += QChar( qFromBigEndian(*s++)); break; diff --git a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp index 20bfaf99dd..a39277b093 100644 --- a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp +++ b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp @@ -948,6 +948,11 @@ void tst_QRawFont::rawFontFromInvalidData() font.loadFromData(invalidData, 10, QFont::PreferDefaultHinting); QVERIFY(!font.isValid()); + + invalidData.fill(255, 1024); + font.loadFromData(invalidData, 10, QFont::PreferDefaultHinting); + + QVERIFY(!font.isValid()); } #endif // QT_NO_RAWFONT