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/xinclude.h>
12 #include <libxml/xmlreader.h>
13 #include "fuzz.h"
14
15 int
LLVMFuzzerInitialize(int * argc ATTRIBUTE_UNUSED,char *** argv ATTRIBUTE_UNUSED)16 LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
17 char ***argv ATTRIBUTE_UNUSED) {
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 maxSize, docSize, consumed, chunkSize;
37 int opts, outSize;
38
39 xmlFuzzDataInit(data, size);
40 opts = xmlFuzzReadInt();
41
42 /* Lower maximum size when processing entities for now. */
43 maxSize = opts & XML_PARSE_NOENT ? 50000 : 500000;
44 if (size > maxSize)
45 goto exit;
46
47 xmlFuzzReadEntities();
48 docBuffer = xmlFuzzMainEntity(&docSize);
49 docUrl = xmlFuzzMainUrl();
50 if (docBuffer == NULL)
51 goto exit;
52
53 /* Pull parser */
54
55 doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts);
56 if (opts & XML_PARSE_XINCLUDE)
57 xmlXIncludeProcessFlags(doc, opts);
58 /* Also test the serializer. */
59 xmlDocDumpMemory(doc, &out, &outSize);
60 xmlFree(out);
61 xmlFreeDoc(doc);
62
63 /* Push parser */
64
65 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
66 if (ctxt == NULL)
67 goto exit;
68 xmlCtxtUseOptions(ctxt, opts);
69
70 for (consumed = 0; consumed < docSize; consumed += chunkSize) {
71 chunkSize = docSize - consumed;
72 if (chunkSize > maxChunkSize)
73 chunkSize = maxChunkSize;
74 xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
75 }
76
77 xmlParseChunk(ctxt, NULL, 0, 1);
78 if (opts & XML_PARSE_XINCLUDE)
79 xmlXIncludeProcessFlags(ctxt->myDoc, opts);
80 xmlFreeDoc(ctxt->myDoc);
81 xmlFreeParserCtxt(ctxt);
82
83 /* Reader */
84
85 reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts);
86 if (reader == NULL)
87 goto exit;
88 while (xmlTextReaderRead(reader) == 1) {
89 if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) {
90 int i, n = xmlTextReaderAttributeCount(reader);
91 for (i=0; i<n; i++) {
92 xmlTextReaderMoveToAttributeNo(reader, i);
93 while (xmlTextReaderReadAttributeValue(reader) == 1);
94 }
95 }
96 }
97 xmlFreeTextReader(reader);
98
99 exit:
100 xmlFuzzDataCleanup();
101 xmlResetLastError();
102 return(0);
103 }
104
105