xref: /aosp_15_r20/external/libxml2/fuzz/testFuzzer.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
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