[libxml2] Patch for security issue CVE-2021-3541



commit 8598060bacada41a0eb09d95c97744ff4e428f8e
Author: Daniel Veillard <veillard redhat com>
Date:   Thu May 13 14:55:12 2021 +0200

    Patch for security issue CVE-2021-3541
    
    This is relapted to parameter entities expansion and following
    the line of the billion laugh attack. Somehow in that path the
    counting of parameters was missed and the normal algorithm based
    on entities "density" was useless.

 parser.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
---
diff --git a/parser.c b/parser.c
index f5e5e169..c9312fa4 100644
--- a/parser.c
+++ b/parser.c
@@ -140,6 +140,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
                      xmlEntityPtr ent, size_t replacement)
 {
     size_t consumed = 0;
+    int i;
 
     if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
         return (0);
@@ -177,6 +178,28 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
            rep = NULL;
        }
     }
+
+    /*
+     * Prevent entity exponential check, not just replacement while
+     * parsing the DTD
+     * The check is potentially costly so do that only once in a thousand
+     */
+    if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
+        (ctxt->nbentities % 1024 == 0)) {
+       for (i = 0;i < ctxt->inputNr;i++) {
+           consumed += ctxt->inputTab[i]->consumed +
+                      (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
+       }
+       if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
+           xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+           ctxt->instate = XML_PARSER_EOF;
+           return (1);
+       }
+       consumed = 0;
+    }
+
+
+
     if (replacement != 0) {
        if (replacement < XML_MAX_TEXT_LENGTH)
            return(0);
@@ -7963,6 +7986,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
             xmlChar start[4];
             xmlCharEncoding enc;
 
+           if (xmlParserEntityCheck(ctxt, 0, entity, 0))
+               return;
+
            if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
                ((ctxt->options & XML_PARSE_NOENT) == 0) &&
                ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]