[libxml2] Fuzz XInclude engine



commit 6c128fd58a0e4641c23a345d413672494622db1b
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Fri Jun 5 13:43:45 2020 +0200

    Fuzz XInclude engine

 fuzz/Makefile.am |  5 +++--
 fuzz/xml.c       |  5 +++++
 fuzz/xmlSeed.c   |  6 +++++-
 xinclude.c       | 15 +++++++++++++++
 4 files changed, 28 insertions(+), 3 deletions(-)
---
diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am
index 6d31c2273..30883de5f 100644
--- a/fuzz/Makefile.am
+++ b/fuzz/Makefile.am
@@ -13,9 +13,10 @@ XML_SEED_CORPUS_SRC = \
     $(top_srcdir)/test/errors10/*.xml \
     $(top_srcdir)/test/namespaces/* \
     $(top_srcdir)/test/valid/*.xml \
-    $(top_srcdir)/test/xmlid/* \
     $(top_srcdir)/test/VC/* \
-    $(top_srcdir)/test/VCM/*
+    $(top_srcdir)/test/VCM/* \
+    $(top_srcdir)/test/XInclude/docs/* \
+    $(top_srcdir)/test/xmlid/*
 
 testFuzzer_SOURCES = testFuzzer.c fuzz.c
 
diff --git a/fuzz/xml.c b/fuzz/xml.c
index 50dd967d0..f3e74ef84 100644
--- a/fuzz/xml.c
+++ b/fuzz/xml.c
@@ -7,6 +7,7 @@
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <libxml/xmlerror.h>
+#include <libxml/xinclude.h>
 #include <libxml/xmlreader.h>
 #include "fuzz.h"
 
@@ -46,6 +47,8 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
     /* Pull parser */
 
     doc = xmlReadMemory(docBuffer, docSize, NULL, NULL, opts);
+    if (opts & XML_PARSE_XINCLUDE)
+        xmlXIncludeProcessFlags(doc, opts);
     /* Also test the serializer. */
     xmlDocDumpMemory(doc, &out, &outSize);
     xmlFree(out);
@@ -64,6 +67,8 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
     }
 
     xmlParseChunk(ctxt, NULL, 0, 1);
+    if (opts & XML_PARSE_XINCLUDE)
+        xmlXIncludeProcessFlags(ctxt->myDoc, opts);
     xmlFreeDoc(ctxt->myDoc);
     xmlFreeParserCtxt(ctxt);
 
diff --git a/fuzz/xmlSeed.c b/fuzz/xmlSeed.c
index 5ce97d0b2..8f164ddcf 100644
--- a/fuzz/xmlSeed.c
+++ b/fuzz/xmlSeed.c
@@ -5,11 +5,13 @@
  */
 
 #include <stdio.h>
+#include <libxml/xinclude.h>
 #include "fuzz.h"
 
 int
 main(int argc, char **argv) {
     int opts = XML_PARSE_NOENT | XML_PARSE_DTDLOAD;
+    xmlDocPtr doc;
 
     if (argc != 2) {
         fprintf(stderr, "Usage: xmlSeed [FILE]\n");
@@ -20,7 +22,9 @@ main(int argc, char **argv) {
 
     xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
     xmlSetExternalEntityLoader(xmlFuzzEntityRecorder);
-    xmlFreeDoc(xmlReadFile(argv[1], NULL, opts));
+    doc = xmlReadFile(argv[1], NULL, opts);
+    xmlXIncludeProcessFlags(doc, opts);
+    xmlFreeDoc(doc);
     xmlFuzzDataCleanup();
 
     return(0);
diff --git a/xinclude.c b/xinclude.c
index 5ea87adec..41ff4e5fd 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -86,6 +86,8 @@ struct _xmlXIncludeCtxt {
     xmlChar *           base; /* the current xml:base */
 
     void            *_private; /* application data */
+
+    unsigned long    incTotal; /* total number of processed inclusions */
 };
 
 static int
@@ -729,7 +731,9 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
         * (bug 132597)
         */
        newctxt->parseFlags = ctxt->parseFlags;
+        newctxt->incTotal = ctxt->incTotal;
        xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
+        ctxt->incTotal = newctxt->incTotal;
        for (i = 0;i < ctxt->incNr;i++) {
            newctxt->incTab[i]->count--;
            newctxt->incTab[i] = NULL;
@@ -1992,11 +1996,13 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
        newctxt->_private = ctxt->_private;
        newctxt->base = xmlStrdup(ctxt->base);  /* Inherit the base from the existing context */
        xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
+        newctxt->incTotal = ctxt->incTotal;
         for (child = fallback->children; child != NULL; child = next) {
             next = child->next;
            if (xmlXIncludeDoProcess(newctxt, ctxt->doc, child) < 0)
                 ret = -1;
         }
+        ctxt->incTotal = newctxt->incTotal;
        if (ctxt->nbErrors > oldNbErrors)
            ret = -1;
        xmlXIncludeFreeContext(newctxt);
@@ -2411,6 +2417,15 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
     do {
        /* TODO: need to work on entities -> stack */
         if (xmlXIncludeTestNode(ctxt, cur) == 1) {
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+            /*
+             * Avoid superlinear expansion by limiting the total number
+             * of replacements.
+             */
+            if (ctxt->incTotal >= 20)
+                return(-1);
+#endif
+            ctxt->incTotal++;
             xmlXIncludePreProcessNode(ctxt, cur);
         } else if ((cur->children != NULL) &&
                    (cur->children->type != XML_ENTITY_DECL) &&


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