diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index ba683cf686..217a968c64 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -1471,36 +1471,70 @@ QT_WARNING_POP return fontEngine; } -static QList getTrueTypeFontOffsets(const uchar *fontData) +static QList getTrueTypeFontOffsets(const uchar *fontData, const uchar *fileEndSentinel) { QList offsets; - const quint32 headerTag = *reinterpret_cast(fontData); + if (fileEndSentinel - fontData < 12) { + qCWarning(lcQpaFonts) << "Corrupted font data detected"; + return offsets; + } + + const quint32 headerTag = qFromUnaligned(fontData); if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) { if (headerTag != MAKE_TAG(0, 1, 0, 0) && headerTag != MAKE_TAG('O', 'T', 'T', 'O') && headerTag != MAKE_TAG('t', 'r', 'u', 'e') - && headerTag != MAKE_TAG('t', 'y', 'p', '1')) + && headerTag != MAKE_TAG('t', 'y', 'p', '1')) { return offsets; + } offsets << 0; return offsets; } + + const quint32 maximumNumFonts = 0xffff; const quint32 numFonts = qFromBigEndian(fontData + 8); - for (uint i = 0; i < numFonts; ++i) { - offsets << qFromBigEndian(fontData + 12 + i * 4); + if (numFonts > maximumNumFonts) { + qCWarning(lcQpaFonts) << "Font collection of" << numFonts << "fonts is too large. Aborting."; + return offsets; } + + if (quintptr(fileEndSentinel - fontData) > 12 + (numFonts - 1) * 4) { + for (quint32 i = 0; i < numFonts; ++i) + offsets << qFromBigEndian(fontData + 12 + i * 4); + } else { + qCWarning(lcQpaFonts) << "Corrupted font data detected"; + } + return offsets; } -static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length) +static void getFontTable(const uchar *fileBegin, const uchar *fileEndSentinel, const uchar *data, quint32 tag, const uchar **table, quint32 *length) { - const quint16 numTables = qFromBigEndian(data + 4); - for (uint i = 0; i < numTables; ++i) { - const quint32 offset = 12 + 16 * i; - if (*reinterpret_cast(data + offset) == tag) { - *table = fileBegin + qFromBigEndian(data + offset + 8); - *length = qFromBigEndian(data + offset + 12); - return; + if (fileEndSentinel - data >= 6) { + const quint16 numTables = qFromBigEndian(data + 4); + if (fileEndSentinel - data >= 28 + 16 * (numTables - 1)) { + for (quint32 i = 0; i < numTables; ++i) { + const quint32 offset = 12 + 16 * i; + if (qFromUnaligned(data + offset) == tag) { + const quint32 tableOffset = qFromBigEndian(data + offset + 8); + if (quintptr(fileEndSentinel - fileBegin) <= tableOffset) { + qCWarning(lcQpaFonts) << "Corrupted font data detected"; + break; + } + *table = fileBegin + tableOffset; + *length = qFromBigEndian(data + offset + 12); + if (quintptr(fileEndSentinel - *table) < *length) { + qCWarning(lcQpaFonts) << "Corrupted font data detected"; + break; + } + return; + } + } + } else { + qCWarning(lcQpaFonts) << "Corrupted font data detected"; } + } else { + qCWarning(lcQpaFonts) << "Corrupted font data detected"; } *table = 0; *length = 0; @@ -1513,8 +1547,9 @@ static void getFamiliesAndSignatures(const QByteArray &fontData, QVector *values) { const uchar *data = reinterpret_cast(fontData.constData()); + const uchar *dataEndSentinel = data + fontData.size(); - QList offsets = getTrueTypeFontOffsets(data); + QList offsets = getTrueTypeFontOffsets(data, dataEndSentinel); if (offsets.isEmpty()) return; @@ -1522,7 +1557,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData, const uchar *font = data + offsets.at(i); const uchar *table; quint32 length; - getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); + getFontTable(data, dataEndSentinel, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); if (!table) continue; QFontNames names = qt_getCanonicalFontNames(table, length); @@ -1532,7 +1567,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData, families->append(std::move(names)); if (values || signatures) - getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); + getFontTable(data, dataEndSentinel, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); if (values) { QFontValues fontValues; -- 2.27.0.windows.1