From 20eb208612f2ea3601151a058bcfa743ab9ff3ac Mon Sep 17 00:00:00 2001
From: hua_yadong <huayadong@kylinos.cn>
Date: Sat, 25 Nov 2023 11:43:09 +0800
Subject: [PATCH] qtbase5.11.1-CVE-2023-43114

---
 .../windows/qwindowsfontdatabase.cpp          | 67 ++++++++++++++-----
 1 file changed, 51 insertions(+), 16 deletions(-)

diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index aab1ab98..a541326a 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -1463,36 +1463,70 @@ QT_WARNING_POP
     return fontEngine;
 }
 
-static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData)
+static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData, const uchar *fileEndSentinel)
 {
     QList<quint32> offsets;
-    const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData);
+    if (fileEndSentinel - fontData < 12) {
+        qCWarning(lcQpaFonts) << "Corrupted font data detected";
+        return offsets;
+    }
+
+    const quint32 headerTag = qFromUnaligned<quint32>(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<quint32>(fontData + 8);
-    for (uint i = 0; i < numFonts; ++i) {
-        offsets << qFromBigEndian<quint32>(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<quint32>(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<quint16>(data + 4);
-    for (uint i = 0; i < numTables; ++i) {
-        const quint32 offset = 12 + 16 * i;
-        if (*reinterpret_cast<const quint32 *>(data + offset) == tag) {
-            *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8);
-            *length = qFromBigEndian<quint32>(data + offset + 12);
-            return;
+    if (fileEndSentinel - data >= 6) {
+        const quint16 numTables = qFromBigEndian<quint16>(data + 4);
+        if (fileEndSentinel - data >= 28 + 16 * (numTables - 1)) {
+            for (quint32 i = 0; i < numTables; ++i) {
+                const quint32 offset = 12 + 16 * i;
+                if (qFromUnaligned<quint32>(data + offset) == tag) {
+                    const quint32 tableOffset = qFromBigEndian<quint32>(data + offset + 8);
+                    if (quintptr(fileEndSentinel - fileBegin) <= tableOffset) {
+                        qCWarning(lcQpaFonts) << "Corrupted font data detected";
+                        break;
+                    }
+                    *table = fileBegin + tableOffset;
+                    *length = qFromBigEndian<quint32>(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;
@@ -1504,8 +1538,9 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
                                      QVector<FONTSIGNATURE> *signatures)
 {
     const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
+    const uchar *dataEndSentinel = data + fontData.size();
 
-    QList<quint32> offsets = getTrueTypeFontOffsets(data);
+    QList<quint32> offsets = getTrueTypeFontOffsets(data, dataEndSentinel);
     if (offsets.isEmpty())
         return;
 
@@ -1513,7 +1548,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;
         FontNames names = qt_getCanonicalFontNames(table, length);
@@ -1524,7 +1559,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
 
         if (signatures) {
             FONTSIGNATURE signature;
-            getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
+            getFontTable(data, dataEndSentinel, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
             if (table && length >= 86) {
                 // Offsets taken from OS/2 table in the TrueType spec
                 signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42);
-- 
2.41.0

