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