File CVE-2023-37369.patch of Package libqt4.31633

---
 src/corelib/xml/qxmlstream.cpp |   41 +++++++++++++++++++++++++++++------------
 src/corelib/xml/qxmlstream.g   |   25 ++++++++++++++++++++++---
 src/corelib/xml/qxmlstream_p.h |   25 ++++++++++++++++++++++---
 3 files changed, 73 insertions(+), 18 deletions(-)

--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -1292,11 +1292,20 @@
     return n;
 }
 
-inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
+// Fast scan an XML attribute name (e.g. "xml:lang").
+inline QXmlStreamReaderPrivate::FastScanNameResult
+QXmlStreamReaderPrivate::fastScanName(Value *val)
 {
     int n = 0;
     ushort c;
     while ((c = getChar())) {
+        if (n >= 4096) {
+            // This is too long to be a sensible name, and
+            // can exhaust memory, or the range of decltype(*prefix)
+            raiseNamePrefixTooLongError();
+            QXmlStreamReaderPrivate::FastScanNameResult ret;
+            return ret;
+        }
         switch (c) {
         case '\n':
         case ' ':
@@ -1324,23 +1333,23 @@
         case '+':
         case '*':
             putChar(c);
-            if (prefix && *prefix == n+1) {
-                *prefix = 0;
+            if (val && val->prefix == n + 1) {
+                val->prefix = 0;
                 putChar(':');
                 --n;
             }
-            return n;
+            return FastScanNameResult(n);
         case ':':
-            if (prefix) {
-                if (*prefix == 0) {
-                    *prefix = n+2;
+            if (val) {
+                if (val->prefix == 0) {
+                    val->prefix = n + 2;
                 } else { // only one colon allowed according to the namespace spec.
                     putChar(c);
-                    return n;
+                    return FastScanNameResult(n);
                 }
             } else {
                 putChar(c);
-                return n;
+                return FastScanNameResult(n);
             }
             // fall through
         default:
@@ -1349,12 +1358,12 @@
         }
     }
 
-    if (prefix)
-        *prefix = 0;
+    if (val)
+        val->prefix = 0;
     int pos = textBuffer.size() - n;
     putString(textBuffer, pos);
     textBuffer.resize(pos);
-    return 0;
+    return FastScanNameResult(0);
 }
 
 enum NameChar { NameBeginning, NameNotBeginning, NotName };
@@ -1861,6 +1870,14 @@
     raiseError(QXmlStreamReader::NotWellFormedError, message);
 }
 
+void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
+{
+    // TODO: add a ImplementationLimitsExceededError and use it instead
+    raiseError(QXmlStreamReader::NotWellFormedError,
+               QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB "
+                              "characters)."));
+}
+
 void QXmlStreamReaderPrivate::parseError()
 {
 
--- a/src/corelib/xml/qxmlstream.g
+++ b/src/corelib/xml/qxmlstream.g
@@ -492,7 +492,16 @@
     int fastScanLiteralContent();
     int fastScanSpace();
     int fastScanContentCharList();
-    int fastScanName(int *prefix = 0);
+
+    struct FastScanNameResult {
+        FastScanNameResult() : ok(false) {}
+        explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
+        operator bool() { return ok; }
+        int operator*() { Q_ASSERT(ok); return addToLen; }
+        int addToLen;
+        bool ok;
+    };
+    FastScanNameResult fastScanName(Value *val = 0);
     inline int fastScanNMTOKEN();
 
 
@@ -501,6 +510,7 @@
 
     void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
     void raiseWellFormedError(const QString &message);
+    void raiseNamePrefixTooLongError();
 
     QXmlStreamEntityResolver *entityResolver;
 
@@ -1784,7 +1794,12 @@
 qname ::= LETTER;
 /.
         case $rule_number: {
-            sym(1).len += fastScanName(&sym(1).prefix);
+            Value &val = sym(1);
+            if (auto res = fastScanName(&val))
+                val.len += *res;
+            else
+                return false;
+
             if (atEnd) {
                 resume($rule_number);
                 return false;
@@ -1795,7 +1810,11 @@
 name ::= LETTER;
 /.
         case $rule_number:
-            sym(1).len += fastScanName();
+            if (auto res = fastScanName())
+                sym(1).len += *res;
+            else
+                return false;
+
             if (atEnd) {
                 resume($rule_number);
                 return false;
--- a/src/corelib/xml/qxmlstream_p.h
+++ b/src/corelib/xml/qxmlstream_p.h
@@ -986,7 +986,16 @@
     int fastScanLiteralContent();
     int fastScanSpace();
     int fastScanContentCharList();
-    int fastScanName(int *prefix = 0);
+
+    struct FastScanNameResult {
+        FastScanNameResult() : ok(false) {}
+        explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
+        operator bool() { return ok; }
+        int operator*() { Q_ASSERT(ok); return addToLen; }
+        int addToLen;
+        bool ok;
+    };
+    FastScanNameResult fastScanName(Value *val = 0);
     inline int fastScanNMTOKEN();
 
 
@@ -995,6 +1004,7 @@
 
     void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
     void raiseWellFormedError(const QString &message);
+    void raiseNamePrefixTooLongError();
 
     QXmlStreamEntityResolver *entityResolver;
 
@@ -1917,7 +1927,12 @@
         break;
 
         case 262: {
-            sym(1).len += fastScanName(&sym(1).prefix);
+            Value &val = sym(1);
+            if (FastScanNameResult res = fastScanName(&val))
+                val.len += *res;
+            else
+                return false;
+
             if (atEnd) {
                 resume(262);
                 return false;
@@ -1925,7 +1940,11 @@
         } break;
 
         case 263:
-            sym(1).len += fastScanName();
+            if (FastScanNameResult res = fastScanName())
+                sym(1).len += *res;
+            else
+                return false;
+
             if (atEnd) {
                 resume(263);
                 return false;
openSUSE Build Service is sponsored by