1 /*
2 * testFuzzer.c: Test program for the custom entity loader used to fuzz
3 * with multiple inputs.
4 *
5 * See Copyright for the status of this software.
6 */
7
8 #include <string.h>
9 #include <glob.h>
10 #include <libxml/parser.h>
11 #include <libxml/tree.h>
12 #include <libxml/xmlstring.h>
13 #include "fuzz.h"
14
15 #ifdef HAVE_HTML_FUZZER
16 int fuzzHtmlInit(int *argc, char ***argv);
17 int fuzzHtml(const char *data, size_t size);
18 #define LLVMFuzzerInitialize fuzzHtmlInit
19 #define LLVMFuzzerTestOneInput fuzzHtml
20 #include "html.c"
21 #undef LLVMFuzzerInitialize
22 #undef LLVMFuzzerTestOneInput
23 #endif
24
25 #ifdef HAVE_REGEXP_FUZZER
26 int fuzzRegexpInit(int *argc, char ***argv);
27 int fuzzRegexp(const char *data, size_t size);
28 #define LLVMFuzzerInitialize fuzzRegexpInit
29 #define LLVMFuzzerTestOneInput fuzzRegexp
30 #include "regexp.c"
31 #undef LLVMFuzzerInitialize
32 #undef LLVMFuzzerTestOneInput
33 #endif
34
35 #ifdef HAVE_SCHEMA_FUZZER
36 int fuzzSchemaInit(int *argc, char ***argv);
37 int fuzzSchema(const char *data, size_t size);
38 #define LLVMFuzzerInitialize fuzzSchemaInit
39 #define LLVMFuzzerTestOneInput fuzzSchema
40 #include "schema.c"
41 #undef LLVMFuzzerInitialize
42 #undef LLVMFuzzerTestOneInput
43 #endif
44
45 #ifdef HAVE_URI_FUZZER
46 int fuzzUriInit(int *argc, char ***argv);
47 int fuzzUri(const char *data, size_t size);
48 #define LLVMFuzzerInitialize fuzzUriInit
49 #define LLVMFuzzerTestOneInput fuzzUri
50 #include "uri.c"
51 #undef LLVMFuzzerInitialize
52 #undef LLVMFuzzerTestOneInput
53 #endif
54
55 #ifdef HAVE_VALID_FUZZER
56 int fuzzValidInit(int *argc, char ***argv);
57 int fuzzValid(const char *data, size_t size);
58 #define LLVMFuzzerInitialize fuzzValidInit
59 #define LLVMFuzzerTestOneInput fuzzValid
60 #include "valid.c"
61 #undef LLVMFuzzerInitialize
62 #undef LLVMFuzzerTestOneInput
63 #endif
64
65 #ifdef HAVE_XINCLUDE_FUZZER
66 int fuzzXIncludeInit(int *argc, char ***argv);
67 int fuzzXInclude(const char *data, size_t size);
68 #define LLVMFuzzerInitialize fuzzXIncludeInit
69 #define LLVMFuzzerTestOneInput fuzzXInclude
70 #include "xinclude.c"
71 #undef LLVMFuzzerInitialize
72 #undef LLVMFuzzerTestOneInput
73 #endif
74
75 #ifdef HAVE_XML_FUZZER
76 int fuzzXmlInit(int *argc, char ***argv);
77 int fuzzXml(const char *data, size_t size);
78 #define LLVMFuzzerInitialize fuzzXmlInit
79 #define LLVMFuzzerTestOneInput fuzzXml
80 #include "xml.c"
81 #undef LLVMFuzzerInitialize
82 #undef LLVMFuzzerTestOneInput
83 #endif
84
85 #ifdef HAVE_XPATH_FUZZER
86 int fuzzXPathInit(int *argc, char ***argv);
87 int fuzzXPath(const char *data, size_t size);
88 #define LLVMFuzzerInitialize fuzzXPathInit
89 #define LLVMFuzzerTestOneInput fuzzXPath
90 #include "xpath.c"
91 #undef LLVMFuzzerInitialize
92 #undef LLVMFuzzerTestOneInput
93 #endif
94
95 typedef int
96 (*initFunc)(int *argc, char ***argv);
97 typedef int
98 (*fuzzFunc)(const char *data, size_t size);
99
100 int numInputs;
101
102 static int
103 testFuzzer(initFunc init, fuzzFunc fuzz, const char *pattern) {
104 glob_t globbuf;
105 int ret = -1;
106 size_t i;
107
108 if (glob(pattern, 0, NULL, &globbuf) != 0) {
109 fprintf(stderr, "pattern %s matches no files\n", pattern);
110 return(-1);
111 }
112
113 if (init != NULL)
114 init(NULL, NULL);
115
116 for (i = 0; i < globbuf.gl_pathc; i++) {
117 const char *path = globbuf.gl_pathv[i];
118 char *data;
119 size_t size;
120
121 data = xmlSlurpFile(path, &size);
122 if (data == NULL) {
123 fprintf(stderr, "couldn't read %s\n", path);
124 goto error;
125 }
126 fuzz(data, size);
127 xmlFree(data);
128
129 numInputs++;
130 }
131
132 ret = 0;
133 error:
134 globfree(&globbuf);
135 return(ret);
136 }
137
138 #ifdef HAVE_XML_FUZZER
139 static int
140 testEntityLoader(void) {
141 static const char data[] =
142 "doc.xml\\\n"
143 "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
144 "<doc>&ent;</doc>\\\n"
145 "doc.dtd\\\n"
146 "<!ELEMENT doc (#PCDATA)>\n"
147 "<!ENTITY ent SYSTEM \"ent.txt\">\\\n"
148 "ent.txt\\\n"
149 "Hello, world!\\\n";
150 const char *docBuffer;
151 size_t docSize;
152 xmlDocPtr doc;
153 int ret = 0;
154
155 xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
156
157 xmlFuzzDataInit(data, sizeof(data) - 1);
158 xmlFuzzReadEntities();
159 docBuffer = xmlFuzzMainEntity(&docSize);
160 doc = xmlReadMemory(docBuffer, docSize, NULL, NULL,
161 XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
162
163 #ifdef LIBXML_OUTPUT_ENABLED
164 {
165 static xmlChar expected[] =
166 "<?xml version=\"1.0\"?>\n"
167 "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
168 "<doc>Hello, world!</doc>\n";
169 xmlChar *out;
170
171 xmlDocDumpMemory(doc, &out, NULL);
172 if (xmlStrcmp(out, expected) != 0) {
173 fprintf(stderr, "Expected:\n%sGot:\n%s", expected, out);
174 ret = 1;
175 }
176 xmlFree(out);
177 }
178 #endif
179
180 xmlFreeDoc(doc);
181 xmlFuzzDataCleanup();
182
183 return(ret);
184 }
185 #endif
186
187 int
188 main(void) {
189 int ret = 0;
190
191 #ifdef HAVE_XML_FUZZER
192 if (testEntityLoader() != 0)
193 ret = 1;
194 #endif
195 #ifdef HAVE_HTML_FUZZER
196 if (testFuzzer(fuzzHtmlInit, fuzzHtml, "seed/html/*") != 0)
197 ret = 1;
198 #endif
199 #ifdef HAVE_REGEXP_FUZZER
200 if (testFuzzer(fuzzRegexpInit, fuzzRegexp, "seed/regexp/*") != 0)
201 ret = 1;
202 #endif
203 #ifdef HAVE_SCHEMA_FUZZER
204 if (testFuzzer(fuzzSchemaInit, fuzzSchema, "seed/schema/*") != 0)
205 ret = 1;
206 #endif
207 #ifdef HAVE_URI_FUZZER
208 if (testFuzzer(fuzzUriInit, fuzzUri, "seed/uri/*") != 0)
209 ret = 1;
210 #endif
211 #ifdef HAVE_VALID_FUZZER
212 if (testFuzzer(fuzzValidInit, fuzzValid, "seed/valid/*") != 0)
213 ret = 1;
214 #endif
215 #ifdef HAVE_XINCLUDE_FUZZER
216 if (testFuzzer(fuzzXIncludeInit, fuzzXInclude, "seed/xinclude/*") != 0)
217 ret = 1;
218 #endif
219 #ifdef HAVE_XML_FUZZER
220 if (testFuzzer(fuzzXmlInit, fuzzXml, "seed/xml/*") != 0)
221 ret = 1;
222 #endif
223 #ifdef HAVE_XPATH_FUZZER
224 if (testFuzzer(fuzzXPathInit, fuzzXPath, "seed/xpath/*") != 0)
225 ret = 1;
226 #endif
227
228 if (ret == 0)
229 printf("Successfully tested %d inputs\n", numInputs);
230
231 return(ret);
232 }
233