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/xmlsave.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 xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
22 #endif
23
24 return 0;
25 }
26
27 int
LLVMFuzzerTestOneInput(const char * data,size_t size)28 LLVMFuzzerTestOneInput(const char *data, size_t size) {
29 xmlParserCtxtPtr ctxt;
30 xmlDocPtr doc;
31 const char *docBuffer, *docUrl;
32 size_t maxAlloc, docSize;
33 int opts;
34
35 xmlFuzzDataInit(data, size);
36 opts = (int) xmlFuzzReadInt(4);
37 /*
38 * Disable options that are known to cause timeouts
39 */
40 opts &= ~XML_PARSE_XINCLUDE &
41 ~XML_PARSE_DTDVALID &
42 ~XML_PARSE_SAX1;
43 maxAlloc = xmlFuzzReadInt(4) % (size + 100);
44
45 xmlFuzzReadEntities();
46 docBuffer = xmlFuzzMainEntity(&docSize);
47 docUrl = xmlFuzzMainUrl();
48 if (docBuffer == NULL)
49 goto exit;
50
51 /* Pull parser */
52
53 xmlFuzzMemSetLimit(maxAlloc);
54 ctxt = xmlNewParserCtxt();
55 if (ctxt != NULL) {
56 xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
57 xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
58 doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts);
59 xmlFuzzCheckMallocFailure("xmlCtxtReadMemory",
60 doc == NULL &&
61 ctxt->errNo == XML_ERR_NO_MEMORY);
62
63 if (doc != NULL) {
64 #ifdef LIBXML_OUTPUT_ENABLED
65 xmlBufferPtr buffer;
66 xmlSaveCtxtPtr save;
67
68 /* Also test the serializer. */
69 buffer = xmlBufferCreate();
70 save = xmlSaveToBuffer(buffer, NULL, 0);
71 if (save != NULL) {
72 int errNo;
73
74 xmlSaveDoc(save, doc);
75 errNo = xmlSaveFinish(save);
76 xmlFuzzCheckMallocFailure("xmlSaveDoc",
77 errNo == XML_ERR_NO_MEMORY);
78 }
79 xmlBufferFree(buffer);
80 #endif
81 xmlFreeDoc(doc);
82 }
83
84 xmlFreeParserCtxt(ctxt);
85 }
86
87 /* Push parser */
88
89 #ifdef LIBXML_PUSH_ENABLED
90 {
91 static const size_t maxChunkSize = 128;
92 size_t consumed, chunkSize;
93
94 xmlFuzzMemSetLimit(maxAlloc);
95 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
96 if (ctxt != NULL) {
97 xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
98 xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
99 xmlCtxtUseOptions(ctxt, opts);
100
101 for (consumed = 0; consumed < docSize; consumed += chunkSize) {
102 chunkSize = docSize - consumed;
103 if (chunkSize > maxChunkSize)
104 chunkSize = maxChunkSize;
105 xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
106 }
107
108 xmlParseChunk(ctxt, NULL, 0, 1);
109 xmlFuzzCheckMallocFailure("xmlParseChunk",
110 ctxt->errNo == XML_ERR_NO_MEMORY);
111 xmlFreeDoc(ctxt->myDoc);
112 xmlFreeParserCtxt(ctxt);
113 }
114 }
115 #endif
116
117 exit:
118 xmlFuzzMemSetLimit(0);
119 xmlFuzzDataCleanup();
120 xmlResetLastError();
121 return(0);
122 }
123
124