[packages/qt5-qtbase] upstream fixes for CVE-2023-37369 and CVE-2023-38197
atler
atler at pld-linux.org
Thu Oct 5 21:31:13 CEST 2023
commit 421a7426a34306643bdcd1a45779f00d27ef0e35
Author: Jan Palus <atler at pld-linux.org>
Date: Thu Oct 5 20:59:43 2023 +0200
upstream fixes for CVE-2023-37369 and CVE-2023-38197
as advised in:
https://lists.qt-project.org/pipermail/announce/2023-July/000430.html
https://lists.qt-project.org/pipermail/announce/2023-July/000433.html
CVE-2023-37369-qtbase-5.15.diff | 203 +++++++++++++++++++++++++++++++++++++
CVE-2023-38197-qtbase-5.15.diff | 219 ++++++++++++++++++++++++++++++++++++++++
qt5-qtbase.spec | 4 +
3 files changed, 426 insertions(+)
---
diff --git a/qt5-qtbase.spec b/qt5-qtbase.spec
index feac66e..3468d1d 100644
--- a/qt5-qtbase.spec
+++ b/qt5-qtbase.spec
@@ -85,6 +85,8 @@ Patch3: CVE-2023-32763-qtbase-5.15.diff
Patch4: CVE-2023-32762-qtbase-5.15.diff
Patch5: CVE-2023-33285-qtbase-5.15.diff
Patch6: CVE-2023-34410-qtbase-5.15.diff
+Patch7: CVE-2023-37369-qtbase-5.15.diff
+Patch8: CVE-2023-38197-qtbase-5.15.diff
URL: https://www.qt.io/
%{?with_directfb:BuildRequires: DirectFB-devel}
BuildRequires: EGL-devel
@@ -1184,6 +1186,8 @@ Generator plików makefile dla aplikacji Qt5.
%patch4 -p1
%patch5 -p1
%patch6 -p1
+%patch7 -p1
+%patch8 -p1
%{__sed} -i -e 's,usr/X11R6/,usr/,g' mkspecs/linux-g++-64/qmake.conf
diff --git a/CVE-2023-37369-qtbase-5.15.diff b/CVE-2023-37369-qtbase-5.15.diff
new file mode 100644
index 0000000..ad2984f
--- /dev/null
+++ b/CVE-2023-37369-qtbase-5.15.diff
@@ -0,0 +1,203 @@
+diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
+index 7cd457ba3a..11d162cb79 100644
+--- a/src/corelib/serialization/qxmlstream.cpp
++++ b/src/corelib/serialization/qxmlstream.cpp
+@@ -1302,15 +1302,18 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
+ 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;
+ uint c;
+ while ((c = getChar()) != StreamEOF) {
+ if (n >= 4096) {
+ // This is too long to be a sensible name, and
+- // can exhaust memory
+- return 0;
++ // can exhaust memory, or the range of decltype(*prefix)
++ raiseNamePrefixTooLongError();
++ return {};
+ }
+ switch (c) {
+ case '\n':
+@@ -1339,23 +1342,23 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
+ 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);
+ }
+ Q_FALLTHROUGH();
+ default:
+@@ -1364,12 +1367,12 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
+ }
+ }
+
+- 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 };
+@@ -1878,6 +1881,14 @@ void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
+ 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()
+ {
+
+diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
+index 4321fed68a..8c6a1a5887 100644
+--- a/src/corelib/serialization/qxmlstream.g
++++ b/src/corelib/serialization/qxmlstream.g
+@@ -516,7 +516,16 @@ public:
+ int fastScanLiteralContent();
+ int fastScanSpace();
+ int fastScanContentCharList();
+- int fastScanName(int *prefix = nullptr);
++
++ 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 = nullptr);
+ inline int fastScanNMTOKEN();
+
+
+@@ -525,6 +534,7 @@ public:
+
+ void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
+ void raiseWellFormedError(const QString &message);
++ void raiseNamePrefixTooLongError();
+
+ QXmlStreamEntityResolver *entityResolver;
+
+@@ -1811,7 +1821,12 @@ space_opt ::= space;
+ 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;
+@@ -1822,7 +1837,11 @@ qname ::= LETTER;
+ 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;
+diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
+index e5bde7b98e..b01484cac3 100644
+--- a/src/corelib/serialization/qxmlstream_p.h
++++ b/src/corelib/serialization/qxmlstream_p.h
+@@ -1005,7 +1005,16 @@ public:
+ int fastScanLiteralContent();
+ int fastScanSpace();
+ int fastScanContentCharList();
+- int fastScanName(int *prefix = nullptr);
++
++ 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 = nullptr);
+ inline int fastScanNMTOKEN();
+
+
+@@ -1014,6 +1023,7 @@ public:
+
+ void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
+ void raiseWellFormedError(const QString &message);
++ void raiseNamePrefixTooLongError();
+
+ QXmlStreamEntityResolver *entityResolver;
+
+@@ -1939,7 +1949,12 @@ bool QXmlStreamReaderPrivate::parse()
+ break;
+
+ case 262: {
+- 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(262);
+ return false;
+@@ -1947,7 +1962,11 @@ bool QXmlStreamReaderPrivate::parse()
+ } break;
+
+ case 263:
+- sym(1).len += fastScanName();
++ if (auto res = fastScanName())
++ sym(1).len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume(263);
+ return false;
diff --git a/CVE-2023-38197-qtbase-5.15.diff b/CVE-2023-38197-qtbase-5.15.diff
new file mode 100644
index 0000000..e9e622b
--- /dev/null
+++ b/CVE-2023-38197-qtbase-5.15.diff
@@ -0,0 +1,219 @@
+diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
+index bf8a2a9..6ab5d49 100644
+--- a/src/corelib/serialization/qxmlstream.cpp
++++ b/src/corelib/serialization/qxmlstream.cpp
+@@ -160,7 +160,7 @@
+ addData() or by waiting for it to arrive on the device().
+
+ \value UnexpectedElementError The parser encountered an element
+- that was different to those it expected.
++ or token that was different to those it expected.
+
+ */
+
+@@ -295,13 +295,34 @@
+
+ QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
+ include external parsed entities. As long as no error occurs, the
+- application code can thus be assured that the data provided by the
+- stream reader satisfies the W3C's criteria for well-formed XML. For
+- example, you can be certain that all tags are indeed nested and
+- closed properly, that references to internal entities have been
+- replaced with the correct replacement text, and that attributes have
+- been normalized or added according to the internal subset of the
+- DTD.
++ application code can thus be assured, that
++ \list
++ \li the data provided by the stream reader satisfies the W3C's
++ criteria for well-formed XML,
++ \li tokens are provided in a valid order.
++ \endlist
++
++ Unless QXmlStreamReader raises an error, it guarantees the following:
++ \list
++ \li All tags are nested and closed properly.
++ \li References to internal entities have been replaced with the
++ correct replacement text.
++ \li Attributes have been normalized or added according to the
++ internal subset of the \l DTD.
++ \li Tokens of type \l StartDocument happen before all others,
++ aside from comments and processing instructions.
++ \li At most one DOCTYPE element (a token of type \l DTD) is present.
++ \li If present, the DOCTYPE appears before all other elements,
++ aside from StartDocument, comments and processing instructions.
++ \endlist
++
++ In particular, once any token of type \l StartElement, \l EndElement,
++ \l Characters, \l EntityReference or \l EndDocument is seen, no
++ tokens of type StartDocument or DTD will be seen. If one is present in
++ the input stream, out of order, an error is raised.
++
++ \note The token types \l Comment and \l ProcessingInstruction may appear
++ anywhere in the stream.
+
+ If an error occurs while parsing, atEnd() and hasError() return
+ true, and error() returns the error that occurred. The functions
+@@ -620,6 +641,7 @@
+ d->token = -1;
+ return readNext();
+ }
++ d->checkToken();
+ return d->type;
+ }
+
+@@ -740,6 +762,14 @@
+ };
+
+
++static const char QXmlStreamReader_XmlContextString[] =
++ "Prolog\0"
++ "Body\0";
++
++static const short QXmlStreamReader_XmlContextString_indices[] = {
++ 0, 7
++};
++
+ /*!
+ \property QXmlStreamReader::namespaceProcessing
+ The namespace-processing flag of the stream reader
+@@ -775,6 +805,16 @@
+ QXmlStreamReader_tokenTypeString_indices[d->type]);
+ }
+
++/*!
++ \internal
++ \return \param ctxt (Prolog/Body) as a string.
++ */
++QString contextString(QXmlStreamReaderPrivate::XmlContext ctxt)
++{
++ return QLatin1String(QXmlStreamReader_XmlContextString +
++ QXmlStreamReader_XmlContextString_indices[static_cast<int>(ctxt)]);
++}
++
+ #endif // QT_NO_XMLSTREAMREADER
+
+ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
+@@ -866,6 +906,8 @@
+
+ type = QXmlStreamReader::NoToken;
+ error = QXmlStreamReader::NoError;
++ currentContext = XmlContext::Prolog;
++ foundDTD = false;
+ }
+
+ /*
+@@ -4061,6 +4103,92 @@
+ }
+ }
+
++static bool isTokenAllowedInContext(QXmlStreamReader::TokenType type,
++ QXmlStreamReaderPrivate::XmlContext loc)
++{
++ switch (type) {
++ case QXmlStreamReader::StartDocument:
++ case QXmlStreamReader::DTD:
++ return loc == QXmlStreamReaderPrivate::XmlContext::Prolog;
++
++ case QXmlStreamReader::StartElement:
++ case QXmlStreamReader::EndElement:
++ case QXmlStreamReader::Characters:
++ case QXmlStreamReader::EntityReference:
++ case QXmlStreamReader::EndDocument:
++ return loc == QXmlStreamReaderPrivate::XmlContext::Body;
++
++ case QXmlStreamReader::Comment:
++ case QXmlStreamReader::ProcessingInstruction:
++ return true;
++
++ case QXmlStreamReader::NoToken:
++ case QXmlStreamReader::Invalid:
++ return false;
++ default:
++ return false;
++ }
++}
++
++/*!
++ \internal
++ \brief QXmlStreamReader::isValidToken
++ \return \c true if \param type is a valid token type.
++ \return \c false if \param type is an unexpected token,
++ which indicates a non-well-formed or invalid XML stream.
++ */
++bool QXmlStreamReaderPrivate::isValidToken(QXmlStreamReader::TokenType type)
++{
++ // Don't change currentContext, if Invalid or NoToken occur in the prolog
++ if (type == QXmlStreamReader::Invalid || type == QXmlStreamReader::NoToken)
++ return false;
++
++ // If a token type gets rejected in the body, there is no recovery
++ const bool result = isTokenAllowedInContext(type, currentContext);
++ if (result || currentContext == XmlContext::Body)
++ return result;
++
++ // First non-Prolog token observed => switch context to body and check again.
++ currentContext = XmlContext::Body;
++ return isTokenAllowedInContext(type, currentContext);
++}
++
++/*!
++ \internal
++ Checks token type and raises an error, if it is invalid
++ in the current context (prolog/body).
++ */
++void QXmlStreamReaderPrivate::checkToken()
++{
++ Q_Q(QXmlStreamReader);
++
++ // The token type must be consumed, to keep track if the body has been reached.
++ const XmlContext context = currentContext;
++ const bool ok = isValidToken(type);
++
++ // Do nothing if an error has been raised already (going along with an unexpected token)
++ if (error != QXmlStreamReader::Error::NoError)
++ return;
++
++ if (!ok) {
++ raiseError(QXmlStreamReader::UnexpectedElementError,
++ QLatin1String("Unexpected token type %1 in %2.")
++ .arg(q->tokenString(), contextString(context)));
++ return;
++ }
++
++ if (type != QXmlStreamReader::DTD)
++ return;
++
++ // Raise error on multiple DTD tokens
++ if (foundDTD) {
++ raiseError(QXmlStreamReader::UnexpectedElementError,
++ QLatin1String("Found second DTD token in %1.").arg(contextString(context)));
++ } else {
++ foundDTD = true;
++ }
++}
++
+ /*!
+ \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
+ \since 4.5
+diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
+index 8f7c9e0..708059b 100644
+--- a/src/corelib/serialization/qxmlstream_p.h
++++ b/src/corelib/serialization/qxmlstream_p.h
+@@ -804,6 +804,17 @@
+ #endif
+ bool atEnd;
+
++ enum class XmlContext
++ {
++ Prolog,
++ Body,
++ };
++
++ XmlContext currentContext = XmlContext::Prolog;
++ bool foundDTD = false;
++ bool isValidToken(QXmlStreamReader::TokenType type);
++ void checkToken();
++
+ /*!
+ \sa setType()
+ */
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/qt5-qtbase.git/commitdiff/421a7426a34306643bdcd1a45779f00d27ef0e35
More information about the pld-cvs-commit
mailing list