• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   #define LLVMFuzzerInitialize fuzzHtmlInit
17   #define LLVMFuzzerTestOneInput fuzzHtml
18   #include "html.c"
19   #undef LLVMFuzzerInitialize
20   #undef LLVMFuzzerTestOneInput
21 #endif
22 
23 #ifdef HAVE_REGEXP_FUZZER
24   #define LLVMFuzzerInitialize fuzzRegexpInit
25   #define LLVMFuzzerTestOneInput fuzzRegexp
26   #include "regexp.c"
27   #undef LLVMFuzzerInitialize
28   #undef LLVMFuzzerTestOneInput
29 #endif
30 
31 #ifdef HAVE_SCHEMA_FUZZER
32   #define LLVMFuzzerInitialize fuzzSchemaInit
33   #define LLVMFuzzerTestOneInput fuzzSchema
34   #include "schema.c"
35   #undef LLVMFuzzerInitialize
36   #undef LLVMFuzzerTestOneInput
37 #endif
38 
39 #ifdef HAVE_URI_FUZZER
40   #define LLVMFuzzerInitialize fuzzUriInit
41   #define LLVMFuzzerTestOneInput fuzzUri
42   #include "uri.c"
43   #undef LLVMFuzzerInitialize
44   #undef LLVMFuzzerTestOneInput
45 #endif
46 
47 #ifdef HAVE_XML_FUZZER
48   #define LLVMFuzzerInitialize fuzzXmlInit
49   #define LLVMFuzzerTestOneInput fuzzXml
50   #include "xml.c"
51   #undef LLVMFuzzerInitialize
52   #undef LLVMFuzzerTestOneInput
53 #endif
54 
55 #ifdef HAVE_XPATH_FUZZER
56   #define LLVMFuzzerInitialize fuzzXPathInit
57   #define LLVMFuzzerTestOneInput fuzzXPath
58   #include "xpath.c"
59   #undef LLVMFuzzerInitialize
60   #undef LLVMFuzzerTestOneInput
61 #endif
62 
63 typedef int
64 (*initFunc)(int *argc, char ***argv);
65 typedef int
66 (*fuzzFunc)(const char *data, size_t size);
67 
68 int numInputs;
69 
70 static int
testFuzzer(initFunc init,fuzzFunc fuzz,const char * pattern)71 testFuzzer(initFunc init, fuzzFunc fuzz, const char *pattern) {
72     glob_t globbuf;
73     int ret = -1;
74     int i;
75 
76     if (glob(pattern, 0, NULL, &globbuf) != 0) {
77         fprintf(stderr, "pattern %s matches no files\n", pattern);
78         return(-1);
79     }
80 
81     if (init != NULL)
82         init(NULL, NULL);
83 
84     for (i = 0; i < globbuf.gl_pathc; i++) {
85         const char *path = globbuf.gl_pathv[i];
86         char *data;
87         size_t size;
88 
89         data = xmlSlurpFile(path, &size);
90         if (data == NULL) {
91             fprintf(stderr, "couldn't read %s\n", path);
92             goto error;
93         }
94         fuzz(data, size);
95         xmlFree(data);
96 
97         numInputs++;
98     }
99 
100     ret = 0;
101 error:
102     globfree(&globbuf);
103     return(ret);
104 }
105 
106 #ifdef HAVE_XML_FUZZER
107 static int
testEntityLoader()108 testEntityLoader() {
109     static const char data[] =
110         "doc.xml\\\n"
111         "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
112         "<doc>&ent;</doc>\\\n"
113         "doc.dtd\\\n"
114         "<!ELEMENT doc (#PCDATA)>\n"
115         "<!ENTITY ent SYSTEM \"ent.txt\">\\\n"
116         "ent.txt\\\n"
117         "Hello, world!\\\n";
118     static xmlChar expected[] =
119         "<?xml version=\"1.0\"?>\n"
120         "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
121         "<doc>Hello, world!</doc>\n";
122     const char *docBuffer;
123     size_t docSize;
124     xmlDocPtr doc;
125     xmlChar *out;
126     int ret = 0;
127 
128     xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
129 
130     xmlFuzzDataInit(data, sizeof(data) - 1);
131     xmlFuzzReadEntities();
132     docBuffer = xmlFuzzMainEntity(&docSize);
133     doc = xmlReadMemory(docBuffer, docSize, NULL, NULL,
134                         XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
135 
136     xmlDocDumpMemory(doc, &out, NULL);
137     if (xmlStrcmp(out, expected) != 0) {
138         fprintf(stderr, "Expected:\n%sGot:\n%s", expected, out);
139         ret = 1;
140     }
141 
142     xmlFree(out);
143     xmlFreeDoc(doc);
144     xmlFuzzDataCleanup();
145 
146     return(ret);
147 }
148 #endif
149 
150 int
main()151 main() {
152     int ret = 0;
153 
154 #ifdef HAVE_XML_FUZZER
155     if (testEntityLoader() != 0)
156         ret = 1;
157 #endif
158 #ifdef HAVE_HTML_FUZZER
159     if (testFuzzer(fuzzHtmlInit, fuzzHtml, "seed/html/*") != 0)
160         ret = 1;
161 #endif
162 #ifdef HAVE_REGEXP_FUZZER
163     if (testFuzzer(fuzzRegexpInit, fuzzRegexp, "seed/regexp/*") != 0)
164         ret = 1;
165 #endif
166 #ifdef HAVE_SCHEMA_FUZZER
167     if (testFuzzer(fuzzSchemaInit, fuzzSchema, "seed/schema/*") != 0)
168         ret = 1;
169 #endif
170 #ifdef HAVE_URI_FUZZER
171     if (testFuzzer(NULL, fuzzUri, "seed/uri/*") != 0)
172         ret = 1;
173 #endif
174 #ifdef HAVE_XML_FUZZER
175     if (testFuzzer(fuzzXmlInit, fuzzXml, "seed/xml/*") != 0)
176         ret = 1;
177 #endif
178 #ifdef HAVE_XPATH_FUZZER
179     if (testFuzzer(fuzzXPathInit, fuzzXPath, "seed/xpath/*") != 0)
180         ret = 1;
181 #endif
182 
183     if (ret == 0)
184         printf("Successfully tested %d inputs\n", numInputs);
185 
186     return(ret);
187 }
188 
189