Windows: Fix another crash when creating QRawFont from invalid data

The sanity check added in d16508a285
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>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2014-05-15 13:32:27 +02:00 committed by The Qt Project
parent 3478ec2949
commit 909b0de5d1
2 changed files with 32 additions and 9 deletions

View File

@ -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;

View File

@ -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