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