Hi!

A fix for CVE-2013-4549:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4549

>From upstream, via Arch Linux.

Already tested during the lock...
OK?

Ciao,
David

Index: Makefile
===================================================================
RCS file: /cvs/ports/x11/qt4/Makefile,v
retrieving revision 1.118
diff -u -p -u -p -r1.118 Makefile
--- Makefile    25 Nov 2013 14:16:24 -0000      1.118
+++ Makefile    25 Feb 2014 09:47:59 -0000
@@ -24,7 +24,7 @@ PKGNAME-debug =               qt4-debug-${PKGVERSION}
 FULLPKGNAME-html =     qt4-html-${PKGVERSION}
 FULLPKGPATH-html =     ${BASE_PKGPATH},-html
 
-REVISION-main =                1
+REVISION-main =                2
 
 # XXX qmake include parser is bogus
 DPB_PROPERTIES =       parallel        nojunk
Index: patches/patch-src_xml_sax_qxml_cpp
===================================================================
RCS file: patches/patch-src_xml_sax_qxml_cpp
diff -N patches/patch-src_xml_sax_qxml_cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_xml_sax_qxml_cpp  25 Feb 2014 09:48:00 -0000
@@ -0,0 +1,105 @@
+$OpenBSD$
+
+Fix for CVE-2013-4549: QXmlSimpleReader in Qt before 5.2 allows
+context-dependent attackers to cause a denial of service (memory
+consumption) via an XML Entity Expansion (XEE) attack.
+
+--- src/xml/sax/qxml.cpp.orig  Fri Jun  7 07:16:58 2013
++++ src/xml/sax/qxml.cpp       Tue Feb 25 10:13:45 2014
+@@ -424,6 +424,12 @@ class QXmlSimpleReaderPrivate (private)
+     int     stringValueLen;
+     QString emptyStr;
+ 
++    // The limit to the amount of times the DTD parsing functions can be 
called
++    // for the DTD currently being parsed.
++    static const int dtdRecursionLimit = 2;
++    // The maximum amount of characters an entity value may contain, after 
expansion.
++    static const int entityCharacterLimit = 1024;
++
+     const QString &string();
+     void stringClear();
+     void stringAddC(QChar);
+@@ -492,6 +498,7 @@ class QXmlSimpleReaderPrivate (private)
+     void unexpectedEof(ParseFunction where, int state);
+     void parseFailed(ParseFunction where, int state);
+     void pushParseState(ParseFunction function, int state);
++    bool isExpandedEntityValueTooLarge(QString *errorMessage);
+ 
+     Q_DECLARE_PUBLIC(QXmlSimpleReader)
+     QXmlSimpleReader *q_ptr;
+@@ -5018,6 +5025,11 @@ bool QXmlSimpleReaderPrivate::parseDoctype()
+                 }
+                 break;
+             case Mup:
++                if (dtdRecursionLimit > 0 && parameterEntities.size() > 
dtdRecursionLimit) {
++                    reportParseError(QString::fromLatin1(
++                        "DTD parsing exceeded recursion limit of 
%1.").arg(dtdRecursionLimit));
++                    return false;
++                }
+                 if (!parseMarkupdecl()) {
+                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, 
state);
+                     return false;
+@@ -6627,6 +6639,50 @@ bool QXmlSimpleReaderPrivate::parseChoiceSeq()
+     return false;
+ }
+ 
++bool QXmlSimpleReaderPrivate::isExpandedEntityValueTooLarge(QString 
*errorMessage)
++{
++    QMap<QString, int> literalEntitySizes;
++    // The entity at (QMap<QString,) referenced the entities at 
(QMap<QString,) (int>) times.
++    QMap<QString, QMap<QString, int> > referencesToOtherEntities;
++    QMap<QString, int> expandedSizes;
++
++    // For every entity, check how many times all entity names were 
referenced in its value.
++    foreach (QString toSearch, entities.keys()) {
++        // The amount of characters that weren't entity names, but literals, 
like 'X'.
++        QString leftOvers = entities.value(toSearch);
++        // How many times was entityName referenced by toSearch?
++        foreach (QString entityName, entities.keys()) {
++            for (int i = 0; i < leftOvers.size() && i != -1; ) {
++                i = 
leftOvers.indexOf(QString::fromLatin1("&%1;").arg(entityName), i);
++                if (i != -1) {
++                    leftOvers.remove(i, entityName.size() + 2);
++                    // The entityName we're currently trying to find was 
matched in this string; increase our count.
++                    ++referencesToOtherEntities[toSearch][entityName];
++                }
++            }
++        }
++        literalEntitySizes[toSearch] = leftOvers.size();
++    }
++
++    foreach (QString entity, referencesToOtherEntities.keys()) {
++        expandedSizes[entity] = literalEntitySizes[entity];
++        foreach (QString referenceTo, 
referencesToOtherEntities.value(entity).keys()) {
++            const int references = 
referencesToOtherEntities.value(entity).value(referenceTo);
++            // The total size of an entity's value is the expanded size of 
all of its referenced entities, plus its literal size.
++            expandedSizes[entity] += expandedSizes[referenceTo] * references 
+ literalEntitySizes[referenceTo] * references;
++        }
++
++        if (expandedSizes[entity] > entityCharacterLimit) {
++            if (errorMessage) {
++                *errorMessage = QString::fromLatin1("The XML entity \"%1\" 
expands too a string that is too large to process (%2 characters > %3).");
++                *errorMessage = 
(*errorMessage).arg(entity).arg(expandedSizes[entity]).arg(entityCharacterLimit);
++            }
++            return true;
++        }
++    }
++    return false;
++}
++
+ /*
+   Parse a EntityDecl [70].
+ 
+@@ -6721,6 +6777,12 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
+         switch (state) {
+             case EValue:
+                 if ( !entityExist(name())) {
++                    QString errorMessage;
++                    if (isExpandedEntityValueTooLarge(&errorMessage)) {
++                        reportParseError(errorMessage);
++                        return false;
++                    }
++
+                     entities.insert(name(), string());
+                     if (declHnd) {
+                         if (!declHnd->internalEntityDecl(name(), string())) {

Reply via email to