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 <libxml/xmlreader.h>
12 #include "fuzz.h"
13
14 int
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
29 LLVMFuzzerTestOneInput(const char *data, size_t size) {
30 xmlDocPtr doc;
31 xmlValidCtxtPtr vctxt;
32 const char *docBuffer, *docUrl;
33 size_t maxAlloc, docSize;
34 int opts;
35
36 xmlFuzzDataInit(data, size);
37 opts = (int) xmlFuzzReadInt(4);
38 opts &= ~XML_PARSE_XINCLUDE;
39 opts |= XML_PARSE_DTDVALID;
40 maxAlloc = xmlFuzzReadInt(4) % (size + 1);
41
42 xmlFuzzReadEntities();
43 docBuffer = xmlFuzzMainEntity(&docSize);
44 docUrl = xmlFuzzMainUrl();
45 if (docBuffer == NULL)
46 goto exit;
47
48 /* Pull parser */
49
50 xmlFuzzMemSetLimit(maxAlloc);
51 doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts);
52 xmlFreeDoc(doc);
53
54 /* Post validation */
55
56 xmlFuzzMemSetLimit(maxAlloc);
57 doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts & ~XML_PARSE_DTDVALID);
58 vctxt = xmlNewValidCtxt();
59 xmlValidateDocument(vctxt, doc);
60 xmlFreeValidCtxt(vctxt);
61 xmlFreeDoc(doc);
62
63 /* Push parser */
64
65 #ifdef LIBXML_PUSH_ENABLED
66 {
67 static const size_t maxChunkSize = 128;
68 xmlParserCtxtPtr ctxt;
69 size_t consumed, chunkSize;
70
71 xmlFuzzMemSetLimit(maxAlloc);
72 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
73 if (ctxt == NULL)
74 goto exit;
75 xmlCtxtUseOptions(ctxt, opts);
76
77 for (consumed = 0; consumed < docSize; consumed += chunkSize) {
78 chunkSize = docSize - consumed;
79 if (chunkSize > maxChunkSize)
80 chunkSize = maxChunkSize;
81 xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
82 }
83
84 xmlParseChunk(ctxt, NULL, 0, 1);
85 xmlFreeDoc(ctxt->myDoc);
86 xmlFreeParserCtxt(ctxt);
87 }
88 #endif
89
90 /* Reader */
91
92 #ifdef LIBXML_READER_ENABLED
93 {
94 xmlTextReaderPtr reader;
95 int j;
96
97 xmlFuzzMemSetLimit(maxAlloc);
98 reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts);
99 if (reader == NULL)
100 goto exit;
101 while (xmlTextReaderRead(reader) == 1) {
102 if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) {
103 int i, n = xmlTextReaderAttributeCount(reader);
104 for (i=0; i<n; i++) {
105 xmlTextReaderMoveToAttributeNo(reader, i);
106 while (xmlTextReaderReadAttributeValue(reader) == 1);
107 }
108 }
109 }
110 for (j = 0; j < 10; j++)
111 xmlTextReaderRead(reader);
112 xmlFreeTextReader(reader);
113 }
114 #endif
115
116 exit:
117 xmlFuzzMemSetLimit(0);
118 xmlFuzzDataCleanup();
119 xmlResetLastError();
120 return(0);
121 }
122