1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker * xmlSeed.c: Generate the XML seed corpus for fuzzing.
3*7c568831SAndroid Build Coastguard Worker *
4*7c568831SAndroid Build Coastguard Worker * See Copyright for the status of this software.
5*7c568831SAndroid Build Coastguard Worker */
6*7c568831SAndroid Build Coastguard Worker
7*7c568831SAndroid Build Coastguard Worker #include <stdio.h>
8*7c568831SAndroid Build Coastguard Worker #include <string.h>
9*7c568831SAndroid Build Coastguard Worker #include <glob.h>
10*7c568831SAndroid Build Coastguard Worker #include <libgen.h>
11*7c568831SAndroid Build Coastguard Worker #include <sys/stat.h>
12*7c568831SAndroid Build Coastguard Worker
13*7c568831SAndroid Build Coastguard Worker #ifdef _WIN32
14*7c568831SAndroid Build Coastguard Worker #include <direct.h>
15*7c568831SAndroid Build Coastguard Worker #else
16*7c568831SAndroid Build Coastguard Worker #include <unistd.h>
17*7c568831SAndroid Build Coastguard Worker #endif
18*7c568831SAndroid Build Coastguard Worker
19*7c568831SAndroid Build Coastguard Worker #include <libxml/parser.h>
20*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
21*7c568831SAndroid Build Coastguard Worker #include <libxml/HTMLparser.h>
22*7c568831SAndroid Build Coastguard Worker #include <libxml/xinclude.h>
23*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlschemas.h>
24*7c568831SAndroid Build Coastguard Worker #include "fuzz.h"
25*7c568831SAndroid Build Coastguard Worker
26*7c568831SAndroid Build Coastguard Worker #define PATH_SIZE 500
27*7c568831SAndroid Build Coastguard Worker #define SEED_BUF_SIZE 16384
28*7c568831SAndroid Build Coastguard Worker #define EXPR_SIZE 4500
29*7c568831SAndroid Build Coastguard Worker
30*7c568831SAndroid Build Coastguard Worker #define FLAG_READER (1 << 0)
31*7c568831SAndroid Build Coastguard Worker #define FLAG_LINT (1 << 1)
32*7c568831SAndroid Build Coastguard Worker
33*7c568831SAndroid Build Coastguard Worker typedef int
34*7c568831SAndroid Build Coastguard Worker (*fileFunc)(const char *base, FILE *out);
35*7c568831SAndroid Build Coastguard Worker
36*7c568831SAndroid Build Coastguard Worker typedef int
37*7c568831SAndroid Build Coastguard Worker (*mainFunc)(const char *arg);
38*7c568831SAndroid Build Coastguard Worker
39*7c568831SAndroid Build Coastguard Worker static struct {
40*7c568831SAndroid Build Coastguard Worker FILE *out;
41*7c568831SAndroid Build Coastguard Worker xmlHashTablePtr entities; /* Maps URLs to xmlFuzzEntityInfos */
42*7c568831SAndroid Build Coastguard Worker xmlExternalEntityLoader oldLoader;
43*7c568831SAndroid Build Coastguard Worker fileFunc processFile;
44*7c568831SAndroid Build Coastguard Worker const char *fuzzer;
45*7c568831SAndroid Build Coastguard Worker int counter;
46*7c568831SAndroid Build Coastguard Worker char cwd[PATH_SIZE];
47*7c568831SAndroid Build Coastguard Worker int flags;
48*7c568831SAndroid Build Coastguard Worker } globalData;
49*7c568831SAndroid Build Coastguard Worker
50*7c568831SAndroid Build Coastguard Worker #if defined(HAVE_SCHEMA_FUZZER) || \
51*7c568831SAndroid Build Coastguard Worker defined(HAVE_XML_FUZZER)
52*7c568831SAndroid Build Coastguard Worker /*
53*7c568831SAndroid Build Coastguard Worker * A custom resource loader that writes all external DTDs or entities to a
54*7c568831SAndroid Build Coastguard Worker * single file in the format expected by xmlFuzzResourceLoader.
55*7c568831SAndroid Build Coastguard Worker */
56*7c568831SAndroid Build Coastguard Worker static int
fuzzResourceRecorder(void * data ATTRIBUTE_UNUSED,const char * URL,const char * ID ATTRIBUTE_UNUSED,xmlResourceType type ATTRIBUTE_UNUSED,int flags,xmlParserInputPtr * out)57*7c568831SAndroid Build Coastguard Worker fuzzResourceRecorder(void *data ATTRIBUTE_UNUSED, const char *URL,
58*7c568831SAndroid Build Coastguard Worker const char *ID ATTRIBUTE_UNUSED,
59*7c568831SAndroid Build Coastguard Worker xmlResourceType type ATTRIBUTE_UNUSED, int flags,
60*7c568831SAndroid Build Coastguard Worker xmlParserInputPtr *out) {
61*7c568831SAndroid Build Coastguard Worker xmlParserInputPtr in;
62*7c568831SAndroid Build Coastguard Worker static const int chunkSize = 16384;
63*7c568831SAndroid Build Coastguard Worker int code, len;
64*7c568831SAndroid Build Coastguard Worker
65*7c568831SAndroid Build Coastguard Worker *out = NULL;
66*7c568831SAndroid Build Coastguard Worker
67*7c568831SAndroid Build Coastguard Worker code = xmlNewInputFromUrl(URL, flags, &in);
68*7c568831SAndroid Build Coastguard Worker if (code != XML_ERR_OK)
69*7c568831SAndroid Build Coastguard Worker return(code);
70*7c568831SAndroid Build Coastguard Worker
71*7c568831SAndroid Build Coastguard Worker if (globalData.entities == NULL) {
72*7c568831SAndroid Build Coastguard Worker globalData.entities = xmlHashCreate(4);
73*7c568831SAndroid Build Coastguard Worker } else if (xmlHashLookup(globalData.entities,
74*7c568831SAndroid Build Coastguard Worker (const xmlChar *) URL) != NULL) {
75*7c568831SAndroid Build Coastguard Worker *out = in;
76*7c568831SAndroid Build Coastguard Worker return(XML_ERR_OK);
77*7c568831SAndroid Build Coastguard Worker }
78*7c568831SAndroid Build Coastguard Worker
79*7c568831SAndroid Build Coastguard Worker do {
80*7c568831SAndroid Build Coastguard Worker len = xmlParserInputGrow(in, chunkSize);
81*7c568831SAndroid Build Coastguard Worker if (len < 0) {
82*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "Error reading %s\n", URL);
83*7c568831SAndroid Build Coastguard Worker xmlFreeInputStream(in);
84*7c568831SAndroid Build Coastguard Worker return(in->buf->error);
85*7c568831SAndroid Build Coastguard Worker }
86*7c568831SAndroid Build Coastguard Worker } while (len > 0);
87*7c568831SAndroid Build Coastguard Worker
88*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(globalData.out, URL);
89*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(globalData.out,
90*7c568831SAndroid Build Coastguard Worker (char *) xmlBufContent(in->buf->buffer));
91*7c568831SAndroid Build Coastguard Worker
92*7c568831SAndroid Build Coastguard Worker xmlFreeInputStream(in);
93*7c568831SAndroid Build Coastguard Worker
94*7c568831SAndroid Build Coastguard Worker xmlHashAddEntry(globalData.entities, (const xmlChar *) URL,
95*7c568831SAndroid Build Coastguard Worker globalData.entities);
96*7c568831SAndroid Build Coastguard Worker
97*7c568831SAndroid Build Coastguard Worker return(xmlNewInputFromUrl(URL, flags, out));
98*7c568831SAndroid Build Coastguard Worker }
99*7c568831SAndroid Build Coastguard Worker
100*7c568831SAndroid Build Coastguard Worker static void
fuzzRecorderInit(FILE * out)101*7c568831SAndroid Build Coastguard Worker fuzzRecorderInit(FILE *out) {
102*7c568831SAndroid Build Coastguard Worker globalData.out = out;
103*7c568831SAndroid Build Coastguard Worker globalData.entities = xmlHashCreate(8);
104*7c568831SAndroid Build Coastguard Worker globalData.oldLoader = xmlGetExternalEntityLoader();
105*7c568831SAndroid Build Coastguard Worker }
106*7c568831SAndroid Build Coastguard Worker
107*7c568831SAndroid Build Coastguard Worker static void
fuzzRecorderCleanup(void)108*7c568831SAndroid Build Coastguard Worker fuzzRecorderCleanup(void) {
109*7c568831SAndroid Build Coastguard Worker xmlHashFree(globalData.entities, NULL);
110*7c568831SAndroid Build Coastguard Worker globalData.out = NULL;
111*7c568831SAndroid Build Coastguard Worker globalData.entities = NULL;
112*7c568831SAndroid Build Coastguard Worker globalData.oldLoader = NULL;
113*7c568831SAndroid Build Coastguard Worker }
114*7c568831SAndroid Build Coastguard Worker #endif
115*7c568831SAndroid Build Coastguard Worker
116*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_XML_FUZZER
117*7c568831SAndroid Build Coastguard Worker static int
processXml(const char * docFile,FILE * out)118*7c568831SAndroid Build Coastguard Worker processXml(const char *docFile, FILE *out) {
119*7c568831SAndroid Build Coastguard Worker int opts = XML_PARSE_NOENT | XML_PARSE_DTDLOAD;
120*7c568831SAndroid Build Coastguard Worker xmlParserCtxtPtr ctxt;
121*7c568831SAndroid Build Coastguard Worker xmlDocPtr doc;
122*7c568831SAndroid Build Coastguard Worker
123*7c568831SAndroid Build Coastguard Worker if (globalData.flags & FLAG_LINT) {
124*7c568831SAndroid Build Coastguard Worker /* Switches */
125*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
126*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
127*7c568831SAndroid Build Coastguard Worker /* maxmem */
128*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
129*7c568831SAndroid Build Coastguard Worker /* max-ampl */
130*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 1);
131*7c568831SAndroid Build Coastguard Worker /* pretty */
132*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 1);
133*7c568831SAndroid Build Coastguard Worker /* encode */
134*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(out, "");
135*7c568831SAndroid Build Coastguard Worker /* pattern */
136*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(out, "");
137*7c568831SAndroid Build Coastguard Worker /* xpath */
138*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(out, "");
139*7c568831SAndroid Build Coastguard Worker } else {
140*7c568831SAndroid Build Coastguard Worker /* Parser options. */
141*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, opts, 4);
142*7c568831SAndroid Build Coastguard Worker /* Max allocations. */
143*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
144*7c568831SAndroid Build Coastguard Worker
145*7c568831SAndroid Build Coastguard Worker if (globalData.flags & FLAG_READER) {
146*7c568831SAndroid Build Coastguard Worker /* Initial reader program with a couple of OP_READs */
147*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(out, "\x01\x01\x01\x01\x01\x01\x01\x01");
148*7c568831SAndroid Build Coastguard Worker }
149*7c568831SAndroid Build Coastguard Worker }
150*7c568831SAndroid Build Coastguard Worker
151*7c568831SAndroid Build Coastguard Worker fuzzRecorderInit(out);
152*7c568831SAndroid Build Coastguard Worker
153*7c568831SAndroid Build Coastguard Worker ctxt = xmlNewParserCtxt();
154*7c568831SAndroid Build Coastguard Worker xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
155*7c568831SAndroid Build Coastguard Worker xmlCtxtSetResourceLoader(ctxt, fuzzResourceRecorder, NULL);
156*7c568831SAndroid Build Coastguard Worker doc = xmlCtxtReadFile(ctxt, docFile, NULL, opts);
157*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_XINCLUDE_ENABLED
158*7c568831SAndroid Build Coastguard Worker {
159*7c568831SAndroid Build Coastguard Worker xmlXIncludeCtxtPtr xinc = xmlXIncludeNewContext(doc);
160*7c568831SAndroid Build Coastguard Worker
161*7c568831SAndroid Build Coastguard Worker xmlXIncludeSetErrorHandler(xinc, xmlFuzzSErrorFunc, NULL);
162*7c568831SAndroid Build Coastguard Worker xmlXIncludeSetResourceLoader(xinc, fuzzResourceRecorder, NULL);
163*7c568831SAndroid Build Coastguard Worker xmlXIncludeSetFlags(xinc, opts);
164*7c568831SAndroid Build Coastguard Worker xmlXIncludeProcessNode(xinc, (xmlNodePtr) doc);
165*7c568831SAndroid Build Coastguard Worker xmlXIncludeFreeContext(xinc);
166*7c568831SAndroid Build Coastguard Worker }
167*7c568831SAndroid Build Coastguard Worker #endif
168*7c568831SAndroid Build Coastguard Worker xmlFreeDoc(doc);
169*7c568831SAndroid Build Coastguard Worker xmlFreeParserCtxt(ctxt);
170*7c568831SAndroid Build Coastguard Worker
171*7c568831SAndroid Build Coastguard Worker fuzzRecorderCleanup();
172*7c568831SAndroid Build Coastguard Worker
173*7c568831SAndroid Build Coastguard Worker return(0);
174*7c568831SAndroid Build Coastguard Worker }
175*7c568831SAndroid Build Coastguard Worker #endif
176*7c568831SAndroid Build Coastguard Worker
177*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_HTML_FUZZER
178*7c568831SAndroid Build Coastguard Worker static int
processHtml(const char * docFile,FILE * out)179*7c568831SAndroid Build Coastguard Worker processHtml(const char *docFile, FILE *out) {
180*7c568831SAndroid Build Coastguard Worker char buf[SEED_BUF_SIZE];
181*7c568831SAndroid Build Coastguard Worker FILE *file;
182*7c568831SAndroid Build Coastguard Worker size_t size;
183*7c568831SAndroid Build Coastguard Worker
184*7c568831SAndroid Build Coastguard Worker /* Parser options. */
185*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
186*7c568831SAndroid Build Coastguard Worker /* Max allocations. */
187*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
188*7c568831SAndroid Build Coastguard Worker
189*7c568831SAndroid Build Coastguard Worker /* Copy file */
190*7c568831SAndroid Build Coastguard Worker file = fopen(docFile, "rb");
191*7c568831SAndroid Build Coastguard Worker if (file == NULL) {
192*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "couldn't open %s\n", docFile);
193*7c568831SAndroid Build Coastguard Worker return(0);
194*7c568831SAndroid Build Coastguard Worker }
195*7c568831SAndroid Build Coastguard Worker do {
196*7c568831SAndroid Build Coastguard Worker size = fread(buf, 1, SEED_BUF_SIZE, file);
197*7c568831SAndroid Build Coastguard Worker if (size > 0)
198*7c568831SAndroid Build Coastguard Worker fwrite(buf, 1, size, out);
199*7c568831SAndroid Build Coastguard Worker } while (size == SEED_BUF_SIZE);
200*7c568831SAndroid Build Coastguard Worker fclose(file);
201*7c568831SAndroid Build Coastguard Worker
202*7c568831SAndroid Build Coastguard Worker return(0);
203*7c568831SAndroid Build Coastguard Worker }
204*7c568831SAndroid Build Coastguard Worker #endif
205*7c568831SAndroid Build Coastguard Worker
206*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_SCHEMA_FUZZER
207*7c568831SAndroid Build Coastguard Worker static int
processSchema(const char * docFile,FILE * out)208*7c568831SAndroid Build Coastguard Worker processSchema(const char *docFile, FILE *out) {
209*7c568831SAndroid Build Coastguard Worker xmlSchemaPtr schema;
210*7c568831SAndroid Build Coastguard Worker xmlSchemaParserCtxtPtr pctxt;
211*7c568831SAndroid Build Coastguard Worker
212*7c568831SAndroid Build Coastguard Worker /* Max allocations. */
213*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
214*7c568831SAndroid Build Coastguard Worker
215*7c568831SAndroid Build Coastguard Worker fuzzRecorderInit(out);
216*7c568831SAndroid Build Coastguard Worker
217*7c568831SAndroid Build Coastguard Worker pctxt = xmlSchemaNewParserCtxt(docFile);
218*7c568831SAndroid Build Coastguard Worker xmlSchemaSetParserStructuredErrors(pctxt, xmlFuzzSErrorFunc, NULL);
219*7c568831SAndroid Build Coastguard Worker xmlSchemaSetResourceLoader(pctxt, fuzzResourceRecorder, NULL);
220*7c568831SAndroid Build Coastguard Worker schema = xmlSchemaParse(pctxt);
221*7c568831SAndroid Build Coastguard Worker xmlSchemaFreeParserCtxt(pctxt);
222*7c568831SAndroid Build Coastguard Worker xmlSchemaFree(schema);
223*7c568831SAndroid Build Coastguard Worker
224*7c568831SAndroid Build Coastguard Worker fuzzRecorderCleanup();
225*7c568831SAndroid Build Coastguard Worker
226*7c568831SAndroid Build Coastguard Worker return(0);
227*7c568831SAndroid Build Coastguard Worker }
228*7c568831SAndroid Build Coastguard Worker #endif
229*7c568831SAndroid Build Coastguard Worker
230*7c568831SAndroid Build Coastguard Worker #if defined(HAVE_HTML_FUZZER) || \
231*7c568831SAndroid Build Coastguard Worker defined(HAVE_SCHEMA_FUZZER) || \
232*7c568831SAndroid Build Coastguard Worker defined(HAVE_XML_FUZZER)
233*7c568831SAndroid Build Coastguard Worker static int
processPattern(const char * pattern)234*7c568831SAndroid Build Coastguard Worker processPattern(const char *pattern) {
235*7c568831SAndroid Build Coastguard Worker glob_t globbuf;
236*7c568831SAndroid Build Coastguard Worker int ret = 0;
237*7c568831SAndroid Build Coastguard Worker int res;
238*7c568831SAndroid Build Coastguard Worker size_t i;
239*7c568831SAndroid Build Coastguard Worker
240*7c568831SAndroid Build Coastguard Worker res = glob(pattern, 0, NULL, &globbuf);
241*7c568831SAndroid Build Coastguard Worker if (res == GLOB_NOMATCH)
242*7c568831SAndroid Build Coastguard Worker return(0);
243*7c568831SAndroid Build Coastguard Worker if (res != 0) {
244*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "couldn't match pattern %s\n", pattern);
245*7c568831SAndroid Build Coastguard Worker return(-1);
246*7c568831SAndroid Build Coastguard Worker }
247*7c568831SAndroid Build Coastguard Worker
248*7c568831SAndroid Build Coastguard Worker for (i = 0; i < globbuf.gl_pathc; i++) {
249*7c568831SAndroid Build Coastguard Worker struct stat statbuf;
250*7c568831SAndroid Build Coastguard Worker char outPath[PATH_SIZE];
251*7c568831SAndroid Build Coastguard Worker char *dirBuf = NULL;
252*7c568831SAndroid Build Coastguard Worker char *baseBuf = NULL;
253*7c568831SAndroid Build Coastguard Worker const char *path, *dir, *base;
254*7c568831SAndroid Build Coastguard Worker FILE *out = NULL;
255*7c568831SAndroid Build Coastguard Worker int dirChanged = 0;
256*7c568831SAndroid Build Coastguard Worker size_t size;
257*7c568831SAndroid Build Coastguard Worker
258*7c568831SAndroid Build Coastguard Worker path = globbuf.gl_pathv[i];
259*7c568831SAndroid Build Coastguard Worker
260*7c568831SAndroid Build Coastguard Worker if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
261*7c568831SAndroid Build Coastguard Worker continue;
262*7c568831SAndroid Build Coastguard Worker
263*7c568831SAndroid Build Coastguard Worker dirBuf = (char *) xmlCharStrdup(path);
264*7c568831SAndroid Build Coastguard Worker baseBuf = (char *) xmlCharStrdup(path);
265*7c568831SAndroid Build Coastguard Worker if ((dirBuf == NULL) || (baseBuf == NULL)) {
266*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "memory allocation failed\n");
267*7c568831SAndroid Build Coastguard Worker ret = -1;
268*7c568831SAndroid Build Coastguard Worker goto error;
269*7c568831SAndroid Build Coastguard Worker }
270*7c568831SAndroid Build Coastguard Worker dir = dirname(dirBuf);
271*7c568831SAndroid Build Coastguard Worker base = basename(baseBuf);
272*7c568831SAndroid Build Coastguard Worker
273*7c568831SAndroid Build Coastguard Worker size = snprintf(outPath, sizeof(outPath), "seed/%s/%s",
274*7c568831SAndroid Build Coastguard Worker globalData.fuzzer, base);
275*7c568831SAndroid Build Coastguard Worker if (size >= PATH_SIZE) {
276*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "creating path failed\n");
277*7c568831SAndroid Build Coastguard Worker ret = -1;
278*7c568831SAndroid Build Coastguard Worker goto error;
279*7c568831SAndroid Build Coastguard Worker }
280*7c568831SAndroid Build Coastguard Worker out = fopen(outPath, "wb");
281*7c568831SAndroid Build Coastguard Worker if (out == NULL) {
282*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "couldn't open %s for writing\n", outPath);
283*7c568831SAndroid Build Coastguard Worker ret = -1;
284*7c568831SAndroid Build Coastguard Worker goto error;
285*7c568831SAndroid Build Coastguard Worker }
286*7c568831SAndroid Build Coastguard Worker if (chdir(dir) != 0) {
287*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "couldn't chdir to %s\n", dir);
288*7c568831SAndroid Build Coastguard Worker ret = -1;
289*7c568831SAndroid Build Coastguard Worker goto error;
290*7c568831SAndroid Build Coastguard Worker }
291*7c568831SAndroid Build Coastguard Worker dirChanged = 1;
292*7c568831SAndroid Build Coastguard Worker if (globalData.processFile(base, out) != 0)
293*7c568831SAndroid Build Coastguard Worker ret = -1;
294*7c568831SAndroid Build Coastguard Worker
295*7c568831SAndroid Build Coastguard Worker error:
296*7c568831SAndroid Build Coastguard Worker if (out != NULL)
297*7c568831SAndroid Build Coastguard Worker fclose(out);
298*7c568831SAndroid Build Coastguard Worker xmlFree(dirBuf);
299*7c568831SAndroid Build Coastguard Worker xmlFree(baseBuf);
300*7c568831SAndroid Build Coastguard Worker if ((dirChanged) && (chdir(globalData.cwd) != 0)) {
301*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "couldn't chdir to %s\n", globalData.cwd);
302*7c568831SAndroid Build Coastguard Worker ret = -1;
303*7c568831SAndroid Build Coastguard Worker break;
304*7c568831SAndroid Build Coastguard Worker }
305*7c568831SAndroid Build Coastguard Worker }
306*7c568831SAndroid Build Coastguard Worker
307*7c568831SAndroid Build Coastguard Worker globfree(&globbuf);
308*7c568831SAndroid Build Coastguard Worker return(ret);
309*7c568831SAndroid Build Coastguard Worker }
310*7c568831SAndroid Build Coastguard Worker #endif
311*7c568831SAndroid Build Coastguard Worker
312*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_XPATH_FUZZER
313*7c568831SAndroid Build Coastguard Worker static int
processXPath(const char * testDir,const char * prefix,const char * name,const char * data,const char * subdir,int xptr)314*7c568831SAndroid Build Coastguard Worker processXPath(const char *testDir, const char *prefix, const char *name,
315*7c568831SAndroid Build Coastguard Worker const char *data, const char *subdir, int xptr) {
316*7c568831SAndroid Build Coastguard Worker char pattern[PATH_SIZE];
317*7c568831SAndroid Build Coastguard Worker glob_t globbuf;
318*7c568831SAndroid Build Coastguard Worker size_t i, size;
319*7c568831SAndroid Build Coastguard Worker int ret = 0, res;
320*7c568831SAndroid Build Coastguard Worker
321*7c568831SAndroid Build Coastguard Worker size = snprintf(pattern, sizeof(pattern), "%s/%s/%s*",
322*7c568831SAndroid Build Coastguard Worker testDir, subdir, prefix);
323*7c568831SAndroid Build Coastguard Worker if (size >= PATH_SIZE)
324*7c568831SAndroid Build Coastguard Worker return(-1);
325*7c568831SAndroid Build Coastguard Worker res = glob(pattern, 0, NULL, &globbuf);
326*7c568831SAndroid Build Coastguard Worker if (res == GLOB_NOMATCH)
327*7c568831SAndroid Build Coastguard Worker return(0);
328*7c568831SAndroid Build Coastguard Worker if (res != 0) {
329*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "couldn't match pattern %s\n", pattern);
330*7c568831SAndroid Build Coastguard Worker return(-1);
331*7c568831SAndroid Build Coastguard Worker }
332*7c568831SAndroid Build Coastguard Worker
333*7c568831SAndroid Build Coastguard Worker for (i = 0; i < globbuf.gl_pathc; i++) {
334*7c568831SAndroid Build Coastguard Worker char *path = globbuf.gl_pathv[i];
335*7c568831SAndroid Build Coastguard Worker struct stat statbuf;
336*7c568831SAndroid Build Coastguard Worker FILE *in;
337*7c568831SAndroid Build Coastguard Worker char expr[EXPR_SIZE];
338*7c568831SAndroid Build Coastguard Worker
339*7c568831SAndroid Build Coastguard Worker if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
340*7c568831SAndroid Build Coastguard Worker continue;
341*7c568831SAndroid Build Coastguard Worker
342*7c568831SAndroid Build Coastguard Worker in = fopen(path, "rb");
343*7c568831SAndroid Build Coastguard Worker if (in == NULL) {
344*7c568831SAndroid Build Coastguard Worker ret = -1;
345*7c568831SAndroid Build Coastguard Worker continue;
346*7c568831SAndroid Build Coastguard Worker }
347*7c568831SAndroid Build Coastguard Worker
348*7c568831SAndroid Build Coastguard Worker while (fgets(expr, EXPR_SIZE, in) != NULL) {
349*7c568831SAndroid Build Coastguard Worker char outPath[PATH_SIZE];
350*7c568831SAndroid Build Coastguard Worker FILE *out;
351*7c568831SAndroid Build Coastguard Worker int j;
352*7c568831SAndroid Build Coastguard Worker
353*7c568831SAndroid Build Coastguard Worker for (j = 0; expr[j] != 0; j++)
354*7c568831SAndroid Build Coastguard Worker if (expr[j] == '\r' || expr[j] == '\n')
355*7c568831SAndroid Build Coastguard Worker break;
356*7c568831SAndroid Build Coastguard Worker expr[j] = 0;
357*7c568831SAndroid Build Coastguard Worker
358*7c568831SAndroid Build Coastguard Worker size = snprintf(outPath, sizeof(outPath), "seed/xpath/%s-%d",
359*7c568831SAndroid Build Coastguard Worker name, globalData.counter);
360*7c568831SAndroid Build Coastguard Worker if (size >= PATH_SIZE) {
361*7c568831SAndroid Build Coastguard Worker ret = -1;
362*7c568831SAndroid Build Coastguard Worker continue;
363*7c568831SAndroid Build Coastguard Worker }
364*7c568831SAndroid Build Coastguard Worker out = fopen(outPath, "wb");
365*7c568831SAndroid Build Coastguard Worker if (out == NULL) {
366*7c568831SAndroid Build Coastguard Worker ret = -1;
367*7c568831SAndroid Build Coastguard Worker continue;
368*7c568831SAndroid Build Coastguard Worker }
369*7c568831SAndroid Build Coastguard Worker
370*7c568831SAndroid Build Coastguard Worker /* Max allocations. */
371*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(out, 0, 4);
372*7c568831SAndroid Build Coastguard Worker
373*7c568831SAndroid Build Coastguard Worker if (xptr) {
374*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(out, expr);
375*7c568831SAndroid Build Coastguard Worker } else {
376*7c568831SAndroid Build Coastguard Worker char xptrExpr[EXPR_SIZE+100];
377*7c568831SAndroid Build Coastguard Worker
378*7c568831SAndroid Build Coastguard Worker /* Wrap XPath expressions as XPointer */
379*7c568831SAndroid Build Coastguard Worker snprintf(xptrExpr, sizeof(xptrExpr), "xpointer(%s)", expr);
380*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(out, xptrExpr);
381*7c568831SAndroid Build Coastguard Worker }
382*7c568831SAndroid Build Coastguard Worker
383*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(out, data);
384*7c568831SAndroid Build Coastguard Worker
385*7c568831SAndroid Build Coastguard Worker fclose(out);
386*7c568831SAndroid Build Coastguard Worker globalData.counter++;
387*7c568831SAndroid Build Coastguard Worker }
388*7c568831SAndroid Build Coastguard Worker
389*7c568831SAndroid Build Coastguard Worker fclose(in);
390*7c568831SAndroid Build Coastguard Worker }
391*7c568831SAndroid Build Coastguard Worker
392*7c568831SAndroid Build Coastguard Worker globfree(&globbuf);
393*7c568831SAndroid Build Coastguard Worker
394*7c568831SAndroid Build Coastguard Worker return(ret);
395*7c568831SAndroid Build Coastguard Worker }
396*7c568831SAndroid Build Coastguard Worker
397*7c568831SAndroid Build Coastguard Worker static int
processXPathDir(const char * testDir)398*7c568831SAndroid Build Coastguard Worker processXPathDir(const char *testDir) {
399*7c568831SAndroid Build Coastguard Worker char pattern[PATH_SIZE];
400*7c568831SAndroid Build Coastguard Worker glob_t globbuf;
401*7c568831SAndroid Build Coastguard Worker size_t i, size;
402*7c568831SAndroid Build Coastguard Worker int ret = 0;
403*7c568831SAndroid Build Coastguard Worker
404*7c568831SAndroid Build Coastguard Worker globalData.counter = 1;
405*7c568831SAndroid Build Coastguard Worker if (processXPath(testDir, "", "expr", "<d></d>", "expr", 0) != 0)
406*7c568831SAndroid Build Coastguard Worker ret = -1;
407*7c568831SAndroid Build Coastguard Worker
408*7c568831SAndroid Build Coastguard Worker size = snprintf(pattern, sizeof(pattern), "%s/docs/*", testDir);
409*7c568831SAndroid Build Coastguard Worker if (size >= PATH_SIZE)
410*7c568831SAndroid Build Coastguard Worker return(1);
411*7c568831SAndroid Build Coastguard Worker if (glob(pattern, 0, NULL, &globbuf) != 0)
412*7c568831SAndroid Build Coastguard Worker return(1);
413*7c568831SAndroid Build Coastguard Worker
414*7c568831SAndroid Build Coastguard Worker for (i = 0; i < globbuf.gl_pathc; i++) {
415*7c568831SAndroid Build Coastguard Worker char *path = globbuf.gl_pathv[i];
416*7c568831SAndroid Build Coastguard Worker char *data;
417*7c568831SAndroid Build Coastguard Worker const char *docFile;
418*7c568831SAndroid Build Coastguard Worker
419*7c568831SAndroid Build Coastguard Worker data = xmlSlurpFile(path, NULL);
420*7c568831SAndroid Build Coastguard Worker if (data == NULL) {
421*7c568831SAndroid Build Coastguard Worker ret = -1;
422*7c568831SAndroid Build Coastguard Worker continue;
423*7c568831SAndroid Build Coastguard Worker }
424*7c568831SAndroid Build Coastguard Worker docFile = basename(path);
425*7c568831SAndroid Build Coastguard Worker
426*7c568831SAndroid Build Coastguard Worker globalData.counter = 1;
427*7c568831SAndroid Build Coastguard Worker if (processXPath(testDir, docFile, docFile, data, "tests", 0) != 0)
428*7c568831SAndroid Build Coastguard Worker ret = -1;
429*7c568831SAndroid Build Coastguard Worker if (processXPath(testDir, docFile, docFile, data, "xptr", 1) != 0)
430*7c568831SAndroid Build Coastguard Worker ret = -1;
431*7c568831SAndroid Build Coastguard Worker if (processXPath(testDir, docFile, docFile, data, "xptr-xp1", 1) != 0)
432*7c568831SAndroid Build Coastguard Worker ret = -1;
433*7c568831SAndroid Build Coastguard Worker
434*7c568831SAndroid Build Coastguard Worker xmlFree(data);
435*7c568831SAndroid Build Coastguard Worker }
436*7c568831SAndroid Build Coastguard Worker
437*7c568831SAndroid Build Coastguard Worker globfree(&globbuf);
438*7c568831SAndroid Build Coastguard Worker
439*7c568831SAndroid Build Coastguard Worker return(ret);
440*7c568831SAndroid Build Coastguard Worker }
441*7c568831SAndroid Build Coastguard Worker #endif
442*7c568831SAndroid Build Coastguard Worker
443*7c568831SAndroid Build Coastguard Worker int
main(int argc,const char ** argv)444*7c568831SAndroid Build Coastguard Worker main(int argc, const char **argv) {
445*7c568831SAndroid Build Coastguard Worker mainFunc processArg = NULL;
446*7c568831SAndroid Build Coastguard Worker const char *fuzzer;
447*7c568831SAndroid Build Coastguard Worker int ret = 0;
448*7c568831SAndroid Build Coastguard Worker int i;
449*7c568831SAndroid Build Coastguard Worker
450*7c568831SAndroid Build Coastguard Worker if (argc < 3) {
451*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "usage: seed [FUZZER] [PATTERN...]\n");
452*7c568831SAndroid Build Coastguard Worker return(1);
453*7c568831SAndroid Build Coastguard Worker }
454*7c568831SAndroid Build Coastguard Worker
455*7c568831SAndroid Build Coastguard Worker fuzzer = argv[1];
456*7c568831SAndroid Build Coastguard Worker if (strcmp(fuzzer, "html") == 0) {
457*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_HTML_FUZZER
458*7c568831SAndroid Build Coastguard Worker processArg = processPattern;
459*7c568831SAndroid Build Coastguard Worker globalData.processFile = processHtml;
460*7c568831SAndroid Build Coastguard Worker #endif
461*7c568831SAndroid Build Coastguard Worker } else if (strcmp(fuzzer, "lint") == 0) {
462*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_LINT_FUZZER
463*7c568831SAndroid Build Coastguard Worker processArg = processPattern;
464*7c568831SAndroid Build Coastguard Worker globalData.flags |= FLAG_LINT;
465*7c568831SAndroid Build Coastguard Worker globalData.processFile = processXml;
466*7c568831SAndroid Build Coastguard Worker #endif
467*7c568831SAndroid Build Coastguard Worker } else if (strcmp(fuzzer, "reader") == 0) {
468*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_READER_FUZZER
469*7c568831SAndroid Build Coastguard Worker processArg = processPattern;
470*7c568831SAndroid Build Coastguard Worker globalData.flags |= FLAG_READER;
471*7c568831SAndroid Build Coastguard Worker globalData.processFile = processXml;
472*7c568831SAndroid Build Coastguard Worker #endif
473*7c568831SAndroid Build Coastguard Worker } else if (strcmp(fuzzer, "schema") == 0) {
474*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_SCHEMA_FUZZER
475*7c568831SAndroid Build Coastguard Worker processArg = processPattern;
476*7c568831SAndroid Build Coastguard Worker globalData.processFile = processSchema;
477*7c568831SAndroid Build Coastguard Worker #endif
478*7c568831SAndroid Build Coastguard Worker } else if (strcmp(fuzzer, "valid") == 0) {
479*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_VALID_FUZZER
480*7c568831SAndroid Build Coastguard Worker processArg = processPattern;
481*7c568831SAndroid Build Coastguard Worker globalData.processFile = processXml;
482*7c568831SAndroid Build Coastguard Worker #endif
483*7c568831SAndroid Build Coastguard Worker } else if (strcmp(fuzzer, "xinclude") == 0) {
484*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_XINCLUDE_FUZZER
485*7c568831SAndroid Build Coastguard Worker processArg = processPattern;
486*7c568831SAndroid Build Coastguard Worker globalData.processFile = processXml;
487*7c568831SAndroid Build Coastguard Worker #endif
488*7c568831SAndroid Build Coastguard Worker } else if (strcmp(fuzzer, "xml") == 0) {
489*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_XML_FUZZER
490*7c568831SAndroid Build Coastguard Worker processArg = processPattern;
491*7c568831SAndroid Build Coastguard Worker globalData.processFile = processXml;
492*7c568831SAndroid Build Coastguard Worker #endif
493*7c568831SAndroid Build Coastguard Worker } else if (strcmp(fuzzer, "xpath") == 0) {
494*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_XPATH_FUZZER
495*7c568831SAndroid Build Coastguard Worker processArg = processXPathDir;
496*7c568831SAndroid Build Coastguard Worker #endif
497*7c568831SAndroid Build Coastguard Worker } else {
498*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "unknown fuzzer %s\n", fuzzer);
499*7c568831SAndroid Build Coastguard Worker return(1);
500*7c568831SAndroid Build Coastguard Worker }
501*7c568831SAndroid Build Coastguard Worker globalData.fuzzer = fuzzer;
502*7c568831SAndroid Build Coastguard Worker
503*7c568831SAndroid Build Coastguard Worker if (getcwd(globalData.cwd, PATH_SIZE) == NULL) {
504*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "couldn't get current directory\n");
505*7c568831SAndroid Build Coastguard Worker return(1);
506*7c568831SAndroid Build Coastguard Worker }
507*7c568831SAndroid Build Coastguard Worker
508*7c568831SAndroid Build Coastguard Worker if (processArg != NULL)
509*7c568831SAndroid Build Coastguard Worker for (i = 2; i < argc; i++)
510*7c568831SAndroid Build Coastguard Worker processArg(argv[i]);
511*7c568831SAndroid Build Coastguard Worker
512*7c568831SAndroid Build Coastguard Worker return(ret);
513*7c568831SAndroid Build Coastguard Worker }
514*7c568831SAndroid Build Coastguard Worker
515