• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * xml.c: a libFuzzer target to test several XML parser interfaces.
3  *
4  * See Copyright for the status of this software.
5  */
6 
7 #include <libxml/catalog.h>
8 #include <libxml/parser.h>
9 #include <libxml/tree.h>
10 #include <libxml/xmlerror.h>
11 #include <libxml/xmlreader.h>
12 #include "fuzz.h"
13 
14 int
LLVMFuzzerInitialize(int * argc ATTRIBUTE_UNUSED,char *** argv ATTRIBUTE_UNUSED)15 LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
16                      char ***argv ATTRIBUTE_UNUSED) {
17     xmlFuzzMemSetup();
18     xmlInitParser();
19 #ifdef LIBXML_CATALOG_ENABLED
20     xmlInitializeCatalog();
21 #endif
22     xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
23     xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
24 
25     return 0;
26 }
27 
28 int
LLVMFuzzerTestOneInput(const char * data,size_t size)29 LLVMFuzzerTestOneInput(const char *data, size_t size) {
30     static const size_t maxChunkSize = 128;
31     xmlDocPtr doc;
32     xmlParserCtxtPtr ctxt;
33     xmlTextReaderPtr reader;
34     xmlChar *out;
35     const char *docBuffer, *docUrl;
36     size_t maxAlloc, docSize, consumed, chunkSize;
37     int opts, outSize;
38 
39     xmlFuzzDataInit(data, size);
40     opts = (int) xmlFuzzReadInt(4);
41     opts &= ~XML_PARSE_XINCLUDE & ~XML_PARSE_DTDVALID;
42     maxAlloc = xmlFuzzReadInt(4) % (size + 1);
43 
44     xmlFuzzReadEntities();
45     docBuffer = xmlFuzzMainEntity(&docSize);
46     docUrl = xmlFuzzMainUrl();
47     if (docBuffer == NULL)
48         goto exit;
49 
50     /* Pull parser */
51 
52     xmlFuzzMemSetLimit(maxAlloc);
53     doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts);
54     /* Also test the serializer. */
55     xmlDocDumpMemory(doc, &out, &outSize);
56     xmlFree(out);
57     xmlFreeDoc(doc);
58 
59     /* Push parser */
60 
61     xmlFuzzMemSetLimit(maxAlloc);
62     ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
63     if (ctxt == NULL)
64         goto exit;
65     xmlCtxtUseOptions(ctxt, opts);
66 
67     for (consumed = 0; consumed < docSize; consumed += chunkSize) {
68         chunkSize = docSize - consumed;
69         if (chunkSize > maxChunkSize)
70             chunkSize = maxChunkSize;
71         xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
72     }
73 
74     xmlParseChunk(ctxt, NULL, 0, 1);
75     xmlFreeDoc(ctxt->myDoc);
76     xmlFreeParserCtxt(ctxt);
77 
78     /* Reader */
79 
80     xmlFuzzMemSetLimit(maxAlloc);
81     reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts);
82     if (reader == NULL)
83         goto exit;
84     while (xmlTextReaderRead(reader) == 1) {
85         if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) {
86             int i, n = xmlTextReaderAttributeCount(reader);
87             for (i=0; i<n; i++) {
88                 xmlTextReaderMoveToAttributeNo(reader, i);
89                 while (xmlTextReaderReadAttributeValue(reader) == 1);
90             }
91         }
92     }
93     xmlFreeTextReader(reader);
94 
95 exit:
96     xmlFuzzMemSetLimit(0);
97     xmlFuzzDataCleanup();
98     xmlResetLastError();
99     return(0);
100 }
101 
102