1 /*
2 * valid.c: a libFuzzer target to test DTD validation.
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 "fuzz.h"
12
13 int
LLVMFuzzerInitialize(int * argc ATTRIBUTE_UNUSED,char *** argv ATTRIBUTE_UNUSED)14 LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
15 char ***argv ATTRIBUTE_UNUSED) {
16 xmlFuzzMemSetup();
17 xmlInitParser();
18 #ifdef LIBXML_CATALOG_ENABLED
19 xmlInitializeCatalog();
20 xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
21 #endif
22
23 return 0;
24 }
25
26 int
LLVMFuzzerTestOneInput(const char * data,size_t size)27 LLVMFuzzerTestOneInput(const char *data, size_t size) {
28 xmlParserCtxtPtr ctxt;
29 xmlDocPtr doc;
30 xmlValidCtxtPtr vctxt;
31 const char *docBuffer, *docUrl;
32 size_t maxAlloc, docSize;
33 int opts;
34
35 xmlFuzzDataInit(data, size);
36 opts = (int) xmlFuzzReadInt(4);
37 opts &= ~XML_PARSE_XINCLUDE;
38 opts |= XML_PARSE_DTDVALID;
39 maxAlloc = xmlFuzzReadInt(4) % (size + 100);
40
41 xmlFuzzReadEntities();
42 docBuffer = xmlFuzzMainEntity(&docSize);
43 docUrl = xmlFuzzMainUrl();
44 if (docBuffer == NULL)
45 goto exit;
46
47 /* Pull parser */
48
49 xmlFuzzMemSetLimit(maxAlloc);
50 ctxt = xmlNewParserCtxt();
51 if (ctxt != NULL) {
52 xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
53 xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
54 doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts);
55 xmlFuzzCheckMallocFailure("xmlCtxtReadMemory",
56 ctxt->errNo == XML_ERR_NO_MEMORY);
57 xmlFreeDoc(doc);
58 xmlFreeParserCtxt(ctxt);
59 }
60
61 /* Post validation */
62
63 xmlFuzzMemSetLimit(maxAlloc);
64 ctxt = xmlNewParserCtxt();
65 if (ctxt != NULL) {
66 xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
67 xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
68 doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL,
69 opts & ~XML_PARSE_DTDVALID);
70 xmlFreeParserCtxt(ctxt);
71
72 /* Post validation requires global callbacks */
73 xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
74 xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
75 vctxt = xmlNewValidCtxt();
76 xmlValidateDocument(vctxt, doc);
77 xmlFreeValidCtxt(vctxt);
78 xmlFreeDoc(doc);
79 xmlSetGenericErrorFunc(NULL, NULL);
80 xmlSetExternalEntityLoader(NULL);
81 }
82
83 /* Push parser */
84
85 #ifdef LIBXML_PUSH_ENABLED
86 {
87 static const size_t maxChunkSize = 128;
88 size_t consumed, chunkSize;
89
90 xmlFuzzMemSetLimit(maxAlloc);
91 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
92 if (ctxt != NULL) {
93 xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
94 xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
95 xmlCtxtUseOptions(ctxt, opts);
96
97 for (consumed = 0; consumed < docSize; consumed += chunkSize) {
98 chunkSize = docSize - consumed;
99 if (chunkSize > maxChunkSize)
100 chunkSize = maxChunkSize;
101 xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
102 }
103
104 xmlParseChunk(ctxt, NULL, 0, 1);
105 xmlFuzzCheckMallocFailure("xmlParseChunk",
106 ctxt->errNo == XML_ERR_NO_MEMORY);
107 xmlFreeDoc(ctxt->myDoc);
108 xmlFreeParserCtxt(ctxt);
109 }
110 }
111 #endif
112
113 exit:
114 xmlFuzzMemSetLimit(0);
115 xmlFuzzDataCleanup();
116 xmlResetLastError();
117 return(0);
118 }
119
120