1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker * fuzz.c: Common functions 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 <stdlib.h>
9*7c568831SAndroid Build Coastguard Worker #include <string.h>
10*7c568831SAndroid Build Coastguard Worker #include <sys/stat.h>
11*7c568831SAndroid Build Coastguard Worker
12*7c568831SAndroid Build Coastguard Worker #include <libxml/hash.h>
13*7c568831SAndroid Build Coastguard Worker #include <libxml/parser.h>
14*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
15*7c568831SAndroid Build Coastguard Worker #include <libxml/tree.h>
16*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlIO.h>
17*7c568831SAndroid Build Coastguard Worker #include "fuzz.h"
18*7c568831SAndroid Build Coastguard Worker
19*7c568831SAndroid Build Coastguard Worker typedef struct {
20*7c568831SAndroid Build Coastguard Worker const char *data;
21*7c568831SAndroid Build Coastguard Worker size_t size;
22*7c568831SAndroid Build Coastguard Worker } xmlFuzzEntityInfo;
23*7c568831SAndroid Build Coastguard Worker
24*7c568831SAndroid Build Coastguard Worker /* Single static instance for now */
25*7c568831SAndroid Build Coastguard Worker static struct {
26*7c568831SAndroid Build Coastguard Worker /* Original data */
27*7c568831SAndroid Build Coastguard Worker const char *data;
28*7c568831SAndroid Build Coastguard Worker size_t size;
29*7c568831SAndroid Build Coastguard Worker
30*7c568831SAndroid Build Coastguard Worker /* Remaining data */
31*7c568831SAndroid Build Coastguard Worker const char *ptr;
32*7c568831SAndroid Build Coastguard Worker size_t remaining;
33*7c568831SAndroid Build Coastguard Worker
34*7c568831SAndroid Build Coastguard Worker /* Buffer for unescaped strings */
35*7c568831SAndroid Build Coastguard Worker char *outBuf;
36*7c568831SAndroid Build Coastguard Worker char *outPtr; /* Free space at end of buffer */
37*7c568831SAndroid Build Coastguard Worker
38*7c568831SAndroid Build Coastguard Worker xmlHashTablePtr entities; /* Maps URLs to xmlFuzzEntityInfos */
39*7c568831SAndroid Build Coastguard Worker
40*7c568831SAndroid Build Coastguard Worker /* The first entity is the main entity. */
41*7c568831SAndroid Build Coastguard Worker const char *mainUrl;
42*7c568831SAndroid Build Coastguard Worker xmlFuzzEntityInfo *mainEntity;
43*7c568831SAndroid Build Coastguard Worker } fuzzData;
44*7c568831SAndroid Build Coastguard Worker
45*7c568831SAndroid Build Coastguard Worker size_t fuzzNumAllocs;
46*7c568831SAndroid Build Coastguard Worker size_t fuzzMaxAllocs;
47*7c568831SAndroid Build Coastguard Worker int fuzzAllocFailed;
48*7c568831SAndroid Build Coastguard Worker
49*7c568831SAndroid Build Coastguard Worker /**
50*7c568831SAndroid Build Coastguard Worker * xmlFuzzErrorFunc:
51*7c568831SAndroid Build Coastguard Worker *
52*7c568831SAndroid Build Coastguard Worker * An error function that simply discards all errors.
53*7c568831SAndroid Build Coastguard Worker */
54*7c568831SAndroid Build Coastguard Worker void
xmlFuzzErrorFunc(void * ctx ATTRIBUTE_UNUSED,const char * msg ATTRIBUTE_UNUSED,...)55*7c568831SAndroid Build Coastguard Worker xmlFuzzErrorFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,
56*7c568831SAndroid Build Coastguard Worker ...) {
57*7c568831SAndroid Build Coastguard Worker }
58*7c568831SAndroid Build Coastguard Worker
59*7c568831SAndroid Build Coastguard Worker /**
60*7c568831SAndroid Build Coastguard Worker * xmlFuzzSErrorFunc:
61*7c568831SAndroid Build Coastguard Worker *
62*7c568831SAndroid Build Coastguard Worker * A structured error function that simply discards all errors.
63*7c568831SAndroid Build Coastguard Worker */
64*7c568831SAndroid Build Coastguard Worker void
xmlFuzzSErrorFunc(void * ctx ATTRIBUTE_UNUSED,const xmlError * error ATTRIBUTE_UNUSED)65*7c568831SAndroid Build Coastguard Worker xmlFuzzSErrorFunc(void *ctx ATTRIBUTE_UNUSED,
66*7c568831SAndroid Build Coastguard Worker const xmlError *error ATTRIBUTE_UNUSED) {
67*7c568831SAndroid Build Coastguard Worker }
68*7c568831SAndroid Build Coastguard Worker
69*7c568831SAndroid Build Coastguard Worker /*
70*7c568831SAndroid Build Coastguard Worker * Malloc failure injection.
71*7c568831SAndroid Build Coastguard Worker *
72*7c568831SAndroid Build Coastguard Worker * To debug issues involving malloc failures, it's often helpful to set
73*7c568831SAndroid Build Coastguard Worker * MALLOC_ABORT to 1. This should provide a backtrace of the failed
74*7c568831SAndroid Build Coastguard Worker * allocation.
75*7c568831SAndroid Build Coastguard Worker */
76*7c568831SAndroid Build Coastguard Worker
77*7c568831SAndroid Build Coastguard Worker #define XML_FUZZ_MALLOC_ABORT 0
78*7c568831SAndroid Build Coastguard Worker
79*7c568831SAndroid Build Coastguard Worker static void *
xmlFuzzMalloc(size_t size)80*7c568831SAndroid Build Coastguard Worker xmlFuzzMalloc(size_t size) {
81*7c568831SAndroid Build Coastguard Worker void *ret;
82*7c568831SAndroid Build Coastguard Worker
83*7c568831SAndroid Build Coastguard Worker if (fuzzMaxAllocs > 0) {
84*7c568831SAndroid Build Coastguard Worker fuzzNumAllocs += 1;
85*7c568831SAndroid Build Coastguard Worker if (fuzzNumAllocs == fuzzMaxAllocs) {
86*7c568831SAndroid Build Coastguard Worker #if XML_FUZZ_MALLOC_ABORT
87*7c568831SAndroid Build Coastguard Worker abort();
88*7c568831SAndroid Build Coastguard Worker #endif
89*7c568831SAndroid Build Coastguard Worker fuzzAllocFailed = 1;
90*7c568831SAndroid Build Coastguard Worker return NULL;
91*7c568831SAndroid Build Coastguard Worker }
92*7c568831SAndroid Build Coastguard Worker }
93*7c568831SAndroid Build Coastguard Worker
94*7c568831SAndroid Build Coastguard Worker ret = malloc(size);
95*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
96*7c568831SAndroid Build Coastguard Worker fuzzAllocFailed = 1;
97*7c568831SAndroid Build Coastguard Worker
98*7c568831SAndroid Build Coastguard Worker return ret;
99*7c568831SAndroid Build Coastguard Worker }
100*7c568831SAndroid Build Coastguard Worker
101*7c568831SAndroid Build Coastguard Worker static void *
xmlFuzzRealloc(void * ptr,size_t size)102*7c568831SAndroid Build Coastguard Worker xmlFuzzRealloc(void *ptr, size_t size) {
103*7c568831SAndroid Build Coastguard Worker void *ret;
104*7c568831SAndroid Build Coastguard Worker
105*7c568831SAndroid Build Coastguard Worker if (fuzzMaxAllocs > 0) {
106*7c568831SAndroid Build Coastguard Worker fuzzNumAllocs += 1;
107*7c568831SAndroid Build Coastguard Worker if (fuzzNumAllocs == fuzzMaxAllocs) {
108*7c568831SAndroid Build Coastguard Worker #if XML_FUZZ_MALLOC_ABORT
109*7c568831SAndroid Build Coastguard Worker abort();
110*7c568831SAndroid Build Coastguard Worker #endif
111*7c568831SAndroid Build Coastguard Worker fuzzAllocFailed = 1;
112*7c568831SAndroid Build Coastguard Worker return NULL;
113*7c568831SAndroid Build Coastguard Worker }
114*7c568831SAndroid Build Coastguard Worker }
115*7c568831SAndroid Build Coastguard Worker
116*7c568831SAndroid Build Coastguard Worker ret = realloc(ptr, size);
117*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
118*7c568831SAndroid Build Coastguard Worker fuzzAllocFailed = 1;
119*7c568831SAndroid Build Coastguard Worker
120*7c568831SAndroid Build Coastguard Worker return ret;
121*7c568831SAndroid Build Coastguard Worker }
122*7c568831SAndroid Build Coastguard Worker
123*7c568831SAndroid Build Coastguard Worker void
xmlFuzzMemSetup(void)124*7c568831SAndroid Build Coastguard Worker xmlFuzzMemSetup(void) {
125*7c568831SAndroid Build Coastguard Worker xmlMemSetup(free, xmlFuzzMalloc, xmlFuzzRealloc, xmlMemStrdup);
126*7c568831SAndroid Build Coastguard Worker }
127*7c568831SAndroid Build Coastguard Worker
128*7c568831SAndroid Build Coastguard Worker void
xmlFuzzMemSetLimit(size_t limit)129*7c568831SAndroid Build Coastguard Worker xmlFuzzMemSetLimit(size_t limit) {
130*7c568831SAndroid Build Coastguard Worker fuzzNumAllocs = 0;
131*7c568831SAndroid Build Coastguard Worker fuzzMaxAllocs = limit;
132*7c568831SAndroid Build Coastguard Worker fuzzAllocFailed = 0;
133*7c568831SAndroid Build Coastguard Worker }
134*7c568831SAndroid Build Coastguard Worker
135*7c568831SAndroid Build Coastguard Worker int
xmlFuzzMallocFailed(void)136*7c568831SAndroid Build Coastguard Worker xmlFuzzMallocFailed(void) {
137*7c568831SAndroid Build Coastguard Worker return fuzzAllocFailed;
138*7c568831SAndroid Build Coastguard Worker }
139*7c568831SAndroid Build Coastguard Worker
140*7c568831SAndroid Build Coastguard Worker void
xmlFuzzResetMallocFailed(void)141*7c568831SAndroid Build Coastguard Worker xmlFuzzResetMallocFailed(void) {
142*7c568831SAndroid Build Coastguard Worker fuzzAllocFailed = 0;
143*7c568831SAndroid Build Coastguard Worker }
144*7c568831SAndroid Build Coastguard Worker
145*7c568831SAndroid Build Coastguard Worker void
xmlFuzzCheckMallocFailure(const char * func,int error)146*7c568831SAndroid Build Coastguard Worker xmlFuzzCheckMallocFailure(const char *func, int error) {
147*7c568831SAndroid Build Coastguard Worker if (error >= 0 && fuzzAllocFailed != error) {
148*7c568831SAndroid Build Coastguard Worker fprintf(stderr, "%s: malloc failure %s reported\n",
149*7c568831SAndroid Build Coastguard Worker func, fuzzAllocFailed ? "not" : "erroneously");
150*7c568831SAndroid Build Coastguard Worker abort();
151*7c568831SAndroid Build Coastguard Worker }
152*7c568831SAndroid Build Coastguard Worker fuzzAllocFailed = 0;
153*7c568831SAndroid Build Coastguard Worker }
154*7c568831SAndroid Build Coastguard Worker
155*7c568831SAndroid Build Coastguard Worker /**
156*7c568831SAndroid Build Coastguard Worker * xmlFuzzDataInit:
157*7c568831SAndroid Build Coastguard Worker *
158*7c568831SAndroid Build Coastguard Worker * Initialize fuzz data provider.
159*7c568831SAndroid Build Coastguard Worker */
160*7c568831SAndroid Build Coastguard Worker void
xmlFuzzDataInit(const char * data,size_t size)161*7c568831SAndroid Build Coastguard Worker xmlFuzzDataInit(const char *data, size_t size) {
162*7c568831SAndroid Build Coastguard Worker fuzzData.data = data;
163*7c568831SAndroid Build Coastguard Worker fuzzData.size = size;
164*7c568831SAndroid Build Coastguard Worker fuzzData.ptr = data;
165*7c568831SAndroid Build Coastguard Worker fuzzData.remaining = size;
166*7c568831SAndroid Build Coastguard Worker
167*7c568831SAndroid Build Coastguard Worker fuzzData.outBuf = xmlMalloc(size + 1);
168*7c568831SAndroid Build Coastguard Worker fuzzData.outPtr = fuzzData.outBuf;
169*7c568831SAndroid Build Coastguard Worker
170*7c568831SAndroid Build Coastguard Worker fuzzData.entities = xmlHashCreate(8);
171*7c568831SAndroid Build Coastguard Worker fuzzData.mainUrl = NULL;
172*7c568831SAndroid Build Coastguard Worker fuzzData.mainEntity = NULL;
173*7c568831SAndroid Build Coastguard Worker }
174*7c568831SAndroid Build Coastguard Worker
175*7c568831SAndroid Build Coastguard Worker /**
176*7c568831SAndroid Build Coastguard Worker * xmlFuzzDataFree:
177*7c568831SAndroid Build Coastguard Worker *
178*7c568831SAndroid Build Coastguard Worker * Cleanup fuzz data provider.
179*7c568831SAndroid Build Coastguard Worker */
180*7c568831SAndroid Build Coastguard Worker void
xmlFuzzDataCleanup(void)181*7c568831SAndroid Build Coastguard Worker xmlFuzzDataCleanup(void) {
182*7c568831SAndroid Build Coastguard Worker xmlFree(fuzzData.outBuf);
183*7c568831SAndroid Build Coastguard Worker xmlHashFree(fuzzData.entities, xmlHashDefaultDeallocator);
184*7c568831SAndroid Build Coastguard Worker }
185*7c568831SAndroid Build Coastguard Worker
186*7c568831SAndroid Build Coastguard Worker /**
187*7c568831SAndroid Build Coastguard Worker * xmlFuzzWriteInt:
188*7c568831SAndroid Build Coastguard Worker * @out: output file
189*7c568831SAndroid Build Coastguard Worker * @v: integer to write
190*7c568831SAndroid Build Coastguard Worker * @size: size of integer in bytes
191*7c568831SAndroid Build Coastguard Worker *
192*7c568831SAndroid Build Coastguard Worker * Write an integer to the fuzz data.
193*7c568831SAndroid Build Coastguard Worker */
194*7c568831SAndroid Build Coastguard Worker void
xmlFuzzWriteInt(FILE * out,size_t v,int size)195*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteInt(FILE *out, size_t v, int size) {
196*7c568831SAndroid Build Coastguard Worker int shift;
197*7c568831SAndroid Build Coastguard Worker
198*7c568831SAndroid Build Coastguard Worker while (size > (int) sizeof(size_t)) {
199*7c568831SAndroid Build Coastguard Worker putc(0, out);
200*7c568831SAndroid Build Coastguard Worker size--;
201*7c568831SAndroid Build Coastguard Worker }
202*7c568831SAndroid Build Coastguard Worker
203*7c568831SAndroid Build Coastguard Worker shift = size * 8;
204*7c568831SAndroid Build Coastguard Worker while (shift > 0) {
205*7c568831SAndroid Build Coastguard Worker shift -= 8;
206*7c568831SAndroid Build Coastguard Worker putc((v >> shift) & 255, out);
207*7c568831SAndroid Build Coastguard Worker }
208*7c568831SAndroid Build Coastguard Worker }
209*7c568831SAndroid Build Coastguard Worker
210*7c568831SAndroid Build Coastguard Worker /**
211*7c568831SAndroid Build Coastguard Worker * xmlFuzzReadInt:
212*7c568831SAndroid Build Coastguard Worker * @size: size of integer in bytes
213*7c568831SAndroid Build Coastguard Worker *
214*7c568831SAndroid Build Coastguard Worker * Read an integer from the fuzz data.
215*7c568831SAndroid Build Coastguard Worker */
216*7c568831SAndroid Build Coastguard Worker size_t
xmlFuzzReadInt(int size)217*7c568831SAndroid Build Coastguard Worker xmlFuzzReadInt(int size) {
218*7c568831SAndroid Build Coastguard Worker size_t ret = 0;
219*7c568831SAndroid Build Coastguard Worker
220*7c568831SAndroid Build Coastguard Worker while ((size > 0) && (fuzzData.remaining > 0)) {
221*7c568831SAndroid Build Coastguard Worker unsigned char c = (unsigned char) *fuzzData.ptr++;
222*7c568831SAndroid Build Coastguard Worker fuzzData.remaining--;
223*7c568831SAndroid Build Coastguard Worker ret = (ret << 8) | c;
224*7c568831SAndroid Build Coastguard Worker size--;
225*7c568831SAndroid Build Coastguard Worker }
226*7c568831SAndroid Build Coastguard Worker
227*7c568831SAndroid Build Coastguard Worker return ret;
228*7c568831SAndroid Build Coastguard Worker }
229*7c568831SAndroid Build Coastguard Worker
230*7c568831SAndroid Build Coastguard Worker /**
231*7c568831SAndroid Build Coastguard Worker * xmlFuzzBytesRemaining:
232*7c568831SAndroid Build Coastguard Worker *
233*7c568831SAndroid Build Coastguard Worker * Return number of remaining bytes in fuzz data.
234*7c568831SAndroid Build Coastguard Worker */
235*7c568831SAndroid Build Coastguard Worker size_t
xmlFuzzBytesRemaining(void)236*7c568831SAndroid Build Coastguard Worker xmlFuzzBytesRemaining(void) {
237*7c568831SAndroid Build Coastguard Worker return(fuzzData.remaining);
238*7c568831SAndroid Build Coastguard Worker }
239*7c568831SAndroid Build Coastguard Worker
240*7c568831SAndroid Build Coastguard Worker /**
241*7c568831SAndroid Build Coastguard Worker * xmlFuzzReadRemaining:
242*7c568831SAndroid Build Coastguard Worker * @size: size of string in bytes
243*7c568831SAndroid Build Coastguard Worker *
244*7c568831SAndroid Build Coastguard Worker * Read remaining bytes from fuzz data.
245*7c568831SAndroid Build Coastguard Worker */
246*7c568831SAndroid Build Coastguard Worker const char *
xmlFuzzReadRemaining(size_t * size)247*7c568831SAndroid Build Coastguard Worker xmlFuzzReadRemaining(size_t *size) {
248*7c568831SAndroid Build Coastguard Worker const char *ret = fuzzData.ptr;
249*7c568831SAndroid Build Coastguard Worker
250*7c568831SAndroid Build Coastguard Worker *size = fuzzData.remaining;
251*7c568831SAndroid Build Coastguard Worker fuzzData.ptr += fuzzData.remaining;
252*7c568831SAndroid Build Coastguard Worker fuzzData.remaining = 0;
253*7c568831SAndroid Build Coastguard Worker
254*7c568831SAndroid Build Coastguard Worker return(ret);
255*7c568831SAndroid Build Coastguard Worker }
256*7c568831SAndroid Build Coastguard Worker
257*7c568831SAndroid Build Coastguard Worker /*
258*7c568831SAndroid Build Coastguard Worker * xmlFuzzWriteString:
259*7c568831SAndroid Build Coastguard Worker * @out: output file
260*7c568831SAndroid Build Coastguard Worker * @str: string to write
261*7c568831SAndroid Build Coastguard Worker *
262*7c568831SAndroid Build Coastguard Worker * Write a random-length string to file in a format similar to
263*7c568831SAndroid Build Coastguard Worker * FuzzedDataProvider. Backslash followed by newline marks the end of the
264*7c568831SAndroid Build Coastguard Worker * string. Two backslashes are used to escape a backslash.
265*7c568831SAndroid Build Coastguard Worker */
266*7c568831SAndroid Build Coastguard Worker void
xmlFuzzWriteString(FILE * out,const char * str)267*7c568831SAndroid Build Coastguard Worker xmlFuzzWriteString(FILE *out, const char *str) {
268*7c568831SAndroid Build Coastguard Worker for (; *str; str++) {
269*7c568831SAndroid Build Coastguard Worker int c = (unsigned char) *str;
270*7c568831SAndroid Build Coastguard Worker putc(c, out);
271*7c568831SAndroid Build Coastguard Worker if (c == '\\')
272*7c568831SAndroid Build Coastguard Worker putc(c, out);
273*7c568831SAndroid Build Coastguard Worker }
274*7c568831SAndroid Build Coastguard Worker putc('\\', out);
275*7c568831SAndroid Build Coastguard Worker putc('\n', out);
276*7c568831SAndroid Build Coastguard Worker }
277*7c568831SAndroid Build Coastguard Worker
278*7c568831SAndroid Build Coastguard Worker /**
279*7c568831SAndroid Build Coastguard Worker * xmlFuzzReadString:
280*7c568831SAndroid Build Coastguard Worker * @size: size of string in bytes
281*7c568831SAndroid Build Coastguard Worker *
282*7c568831SAndroid Build Coastguard Worker * Read a random-length string from the fuzz data.
283*7c568831SAndroid Build Coastguard Worker *
284*7c568831SAndroid Build Coastguard Worker * The format is similar to libFuzzer's FuzzedDataProvider but treats
285*7c568831SAndroid Build Coastguard Worker * backslash followed by newline as end of string. This makes the fuzz data
286*7c568831SAndroid Build Coastguard Worker * more readable. A backslash character is escaped with another backslash.
287*7c568831SAndroid Build Coastguard Worker *
288*7c568831SAndroid Build Coastguard Worker * Returns a zero-terminated string or NULL if the fuzz data is exhausted.
289*7c568831SAndroid Build Coastguard Worker */
290*7c568831SAndroid Build Coastguard Worker const char *
xmlFuzzReadString(size_t * size)291*7c568831SAndroid Build Coastguard Worker xmlFuzzReadString(size_t *size) {
292*7c568831SAndroid Build Coastguard Worker const char *out = fuzzData.outPtr;
293*7c568831SAndroid Build Coastguard Worker
294*7c568831SAndroid Build Coastguard Worker while (fuzzData.remaining > 0) {
295*7c568831SAndroid Build Coastguard Worker int c = *fuzzData.ptr++;
296*7c568831SAndroid Build Coastguard Worker fuzzData.remaining--;
297*7c568831SAndroid Build Coastguard Worker
298*7c568831SAndroid Build Coastguard Worker if ((c == '\\') && (fuzzData.remaining > 0)) {
299*7c568831SAndroid Build Coastguard Worker int c2 = *fuzzData.ptr;
300*7c568831SAndroid Build Coastguard Worker
301*7c568831SAndroid Build Coastguard Worker if (c2 == '\n') {
302*7c568831SAndroid Build Coastguard Worker fuzzData.ptr++;
303*7c568831SAndroid Build Coastguard Worker fuzzData.remaining--;
304*7c568831SAndroid Build Coastguard Worker if (size != NULL)
305*7c568831SAndroid Build Coastguard Worker *size = fuzzData.outPtr - out;
306*7c568831SAndroid Build Coastguard Worker *fuzzData.outPtr++ = '\0';
307*7c568831SAndroid Build Coastguard Worker return(out);
308*7c568831SAndroid Build Coastguard Worker }
309*7c568831SAndroid Build Coastguard Worker if (c2 == '\\') {
310*7c568831SAndroid Build Coastguard Worker fuzzData.ptr++;
311*7c568831SAndroid Build Coastguard Worker fuzzData.remaining--;
312*7c568831SAndroid Build Coastguard Worker }
313*7c568831SAndroid Build Coastguard Worker }
314*7c568831SAndroid Build Coastguard Worker
315*7c568831SAndroid Build Coastguard Worker *fuzzData.outPtr++ = c;
316*7c568831SAndroid Build Coastguard Worker }
317*7c568831SAndroid Build Coastguard Worker
318*7c568831SAndroid Build Coastguard Worker if (fuzzData.outPtr > out) {
319*7c568831SAndroid Build Coastguard Worker if (size != NULL)
320*7c568831SAndroid Build Coastguard Worker *size = fuzzData.outPtr - out;
321*7c568831SAndroid Build Coastguard Worker *fuzzData.outPtr++ = '\0';
322*7c568831SAndroid Build Coastguard Worker return(out);
323*7c568831SAndroid Build Coastguard Worker }
324*7c568831SAndroid Build Coastguard Worker
325*7c568831SAndroid Build Coastguard Worker if (size != NULL)
326*7c568831SAndroid Build Coastguard Worker *size = 0;
327*7c568831SAndroid Build Coastguard Worker return(NULL);
328*7c568831SAndroid Build Coastguard Worker }
329*7c568831SAndroid Build Coastguard Worker
330*7c568831SAndroid Build Coastguard Worker /**
331*7c568831SAndroid Build Coastguard Worker * xmlFuzzReadEntities:
332*7c568831SAndroid Build Coastguard Worker *
333*7c568831SAndroid Build Coastguard Worker * Read entities like the main XML file, external DTDs, external parsed
334*7c568831SAndroid Build Coastguard Worker * entities from fuzz data.
335*7c568831SAndroid Build Coastguard Worker */
336*7c568831SAndroid Build Coastguard Worker void
xmlFuzzReadEntities(void)337*7c568831SAndroid Build Coastguard Worker xmlFuzzReadEntities(void) {
338*7c568831SAndroid Build Coastguard Worker size_t num = 0;
339*7c568831SAndroid Build Coastguard Worker
340*7c568831SAndroid Build Coastguard Worker while (1) {
341*7c568831SAndroid Build Coastguard Worker const char *url, *entity;
342*7c568831SAndroid Build Coastguard Worker size_t urlSize, entitySize;
343*7c568831SAndroid Build Coastguard Worker xmlFuzzEntityInfo *entityInfo;
344*7c568831SAndroid Build Coastguard Worker
345*7c568831SAndroid Build Coastguard Worker url = xmlFuzzReadString(&urlSize);
346*7c568831SAndroid Build Coastguard Worker if (url == NULL) break;
347*7c568831SAndroid Build Coastguard Worker
348*7c568831SAndroid Build Coastguard Worker entity = xmlFuzzReadString(&entitySize);
349*7c568831SAndroid Build Coastguard Worker if (entity == NULL) break;
350*7c568831SAndroid Build Coastguard Worker
351*7c568831SAndroid Build Coastguard Worker /*
352*7c568831SAndroid Build Coastguard Worker * Cap URL size to avoid quadratic behavior when generating
353*7c568831SAndroid Build Coastguard Worker * error messages or looking up entities.
354*7c568831SAndroid Build Coastguard Worker */
355*7c568831SAndroid Build Coastguard Worker if (urlSize < 50 &&
356*7c568831SAndroid Build Coastguard Worker xmlHashLookup(fuzzData.entities, (xmlChar *)url) == NULL) {
357*7c568831SAndroid Build Coastguard Worker entityInfo = xmlMalloc(sizeof(xmlFuzzEntityInfo));
358*7c568831SAndroid Build Coastguard Worker if (entityInfo == NULL)
359*7c568831SAndroid Build Coastguard Worker break;
360*7c568831SAndroid Build Coastguard Worker entityInfo->data = entity;
361*7c568831SAndroid Build Coastguard Worker entityInfo->size = entitySize;
362*7c568831SAndroid Build Coastguard Worker
363*7c568831SAndroid Build Coastguard Worker xmlHashAddEntry(fuzzData.entities, (xmlChar *)url, entityInfo);
364*7c568831SAndroid Build Coastguard Worker
365*7c568831SAndroid Build Coastguard Worker if (num == 0) {
366*7c568831SAndroid Build Coastguard Worker fuzzData.mainUrl = url;
367*7c568831SAndroid Build Coastguard Worker fuzzData.mainEntity = entityInfo;
368*7c568831SAndroid Build Coastguard Worker }
369*7c568831SAndroid Build Coastguard Worker
370*7c568831SAndroid Build Coastguard Worker num++;
371*7c568831SAndroid Build Coastguard Worker }
372*7c568831SAndroid Build Coastguard Worker }
373*7c568831SAndroid Build Coastguard Worker }
374*7c568831SAndroid Build Coastguard Worker
375*7c568831SAndroid Build Coastguard Worker /**
376*7c568831SAndroid Build Coastguard Worker * xmlFuzzMainUrl:
377*7c568831SAndroid Build Coastguard Worker *
378*7c568831SAndroid Build Coastguard Worker * Returns the main URL.
379*7c568831SAndroid Build Coastguard Worker */
380*7c568831SAndroid Build Coastguard Worker const char *
xmlFuzzMainUrl(void)381*7c568831SAndroid Build Coastguard Worker xmlFuzzMainUrl(void) {
382*7c568831SAndroid Build Coastguard Worker return(fuzzData.mainUrl);
383*7c568831SAndroid Build Coastguard Worker }
384*7c568831SAndroid Build Coastguard Worker
385*7c568831SAndroid Build Coastguard Worker /**
386*7c568831SAndroid Build Coastguard Worker * xmlFuzzMainEntity:
387*7c568831SAndroid Build Coastguard Worker * @size: size of the main entity in bytes
388*7c568831SAndroid Build Coastguard Worker *
389*7c568831SAndroid Build Coastguard Worker * Returns the main entity.
390*7c568831SAndroid Build Coastguard Worker */
391*7c568831SAndroid Build Coastguard Worker const char *
xmlFuzzMainEntity(size_t * size)392*7c568831SAndroid Build Coastguard Worker xmlFuzzMainEntity(size_t *size) {
393*7c568831SAndroid Build Coastguard Worker if (fuzzData.mainEntity == NULL)
394*7c568831SAndroid Build Coastguard Worker return(NULL);
395*7c568831SAndroid Build Coastguard Worker *size = fuzzData.mainEntity->size;
396*7c568831SAndroid Build Coastguard Worker return(fuzzData.mainEntity->data);
397*7c568831SAndroid Build Coastguard Worker }
398*7c568831SAndroid Build Coastguard Worker
399*7c568831SAndroid Build Coastguard Worker /**
400*7c568831SAndroid Build Coastguard Worker * xmlFuzzResourceLoader:
401*7c568831SAndroid Build Coastguard Worker *
402*7c568831SAndroid Build Coastguard Worker * The resource loader for fuzz data.
403*7c568831SAndroid Build Coastguard Worker */
404*7c568831SAndroid Build Coastguard Worker int
xmlFuzzResourceLoader(void * data ATTRIBUTE_UNUSED,const char * URL,const char * ID ATTRIBUTE_UNUSED,xmlResourceType type ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,xmlParserInputPtr * out)405*7c568831SAndroid Build Coastguard Worker xmlFuzzResourceLoader(void *data ATTRIBUTE_UNUSED, const char *URL,
406*7c568831SAndroid Build Coastguard Worker const char *ID ATTRIBUTE_UNUSED,
407*7c568831SAndroid Build Coastguard Worker xmlResourceType type ATTRIBUTE_UNUSED,
408*7c568831SAndroid Build Coastguard Worker int flags ATTRIBUTE_UNUSED, xmlParserInputPtr *out) {
409*7c568831SAndroid Build Coastguard Worker xmlParserInputPtr input;
410*7c568831SAndroid Build Coastguard Worker xmlFuzzEntityInfo *entity;
411*7c568831SAndroid Build Coastguard Worker
412*7c568831SAndroid Build Coastguard Worker entity = xmlHashLookup(fuzzData.entities, (xmlChar *) URL);
413*7c568831SAndroid Build Coastguard Worker if (entity == NULL)
414*7c568831SAndroid Build Coastguard Worker return(XML_IO_ENOENT);
415*7c568831SAndroid Build Coastguard Worker
416*7c568831SAndroid Build Coastguard Worker input = xmlNewInputFromMemory(URL, entity->data, entity->size,
417*7c568831SAndroid Build Coastguard Worker XML_INPUT_BUF_STATIC |
418*7c568831SAndroid Build Coastguard Worker XML_INPUT_BUF_ZERO_TERMINATED);
419*7c568831SAndroid Build Coastguard Worker if (input == NULL)
420*7c568831SAndroid Build Coastguard Worker return(XML_ERR_NO_MEMORY);
421*7c568831SAndroid Build Coastguard Worker
422*7c568831SAndroid Build Coastguard Worker *out = input;
423*7c568831SAndroid Build Coastguard Worker return(XML_ERR_OK);
424*7c568831SAndroid Build Coastguard Worker }
425*7c568831SAndroid Build Coastguard Worker
426*7c568831SAndroid Build Coastguard Worker /**
427*7c568831SAndroid Build Coastguard Worker * xmlFuzzEntityLoader:
428*7c568831SAndroid Build Coastguard Worker *
429*7c568831SAndroid Build Coastguard Worker * The entity loader for fuzz data.
430*7c568831SAndroid Build Coastguard Worker */
431*7c568831SAndroid Build Coastguard Worker xmlParserInputPtr
xmlFuzzEntityLoader(const char * URL,const char * ID ATTRIBUTE_UNUSED,xmlParserCtxtPtr ctxt)432*7c568831SAndroid Build Coastguard Worker xmlFuzzEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED,
433*7c568831SAndroid Build Coastguard Worker xmlParserCtxtPtr ctxt) {
434*7c568831SAndroid Build Coastguard Worker xmlParserInputBufferPtr buf;
435*7c568831SAndroid Build Coastguard Worker xmlFuzzEntityInfo *entity;
436*7c568831SAndroid Build Coastguard Worker
437*7c568831SAndroid Build Coastguard Worker if (URL == NULL)
438*7c568831SAndroid Build Coastguard Worker return(NULL);
439*7c568831SAndroid Build Coastguard Worker entity = xmlHashLookup(fuzzData.entities, (xmlChar *) URL);
440*7c568831SAndroid Build Coastguard Worker if (entity == NULL)
441*7c568831SAndroid Build Coastguard Worker return(NULL);
442*7c568831SAndroid Build Coastguard Worker
443*7c568831SAndroid Build Coastguard Worker buf = xmlParserInputBufferCreateMem(entity->data, entity->size,
444*7c568831SAndroid Build Coastguard Worker XML_CHAR_ENCODING_NONE);
445*7c568831SAndroid Build Coastguard Worker if (buf == NULL) {
446*7c568831SAndroid Build Coastguard Worker xmlCtxtErrMemory(ctxt);
447*7c568831SAndroid Build Coastguard Worker return(NULL);
448*7c568831SAndroid Build Coastguard Worker }
449*7c568831SAndroid Build Coastguard Worker
450*7c568831SAndroid Build Coastguard Worker return(xmlNewIOInputStream(ctxt, buf, XML_CHAR_ENCODING_NONE));
451*7c568831SAndroid Build Coastguard Worker }
452*7c568831SAndroid Build Coastguard Worker
453*7c568831SAndroid Build Coastguard Worker char *
xmlSlurpFile(const char * path,size_t * sizeRet)454*7c568831SAndroid Build Coastguard Worker xmlSlurpFile(const char *path, size_t *sizeRet) {
455*7c568831SAndroid Build Coastguard Worker FILE *file;
456*7c568831SAndroid Build Coastguard Worker struct stat statbuf;
457*7c568831SAndroid Build Coastguard Worker char *data;
458*7c568831SAndroid Build Coastguard Worker size_t size;
459*7c568831SAndroid Build Coastguard Worker
460*7c568831SAndroid Build Coastguard Worker if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
461*7c568831SAndroid Build Coastguard Worker return(NULL);
462*7c568831SAndroid Build Coastguard Worker size = statbuf.st_size;
463*7c568831SAndroid Build Coastguard Worker file = fopen(path, "rb");
464*7c568831SAndroid Build Coastguard Worker if (file == NULL)
465*7c568831SAndroid Build Coastguard Worker return(NULL);
466*7c568831SAndroid Build Coastguard Worker data = xmlMalloc(size + 1);
467*7c568831SAndroid Build Coastguard Worker if (data != NULL) {
468*7c568831SAndroid Build Coastguard Worker if (fread(data, 1, size, file) != size) {
469*7c568831SAndroid Build Coastguard Worker xmlFree(data);
470*7c568831SAndroid Build Coastguard Worker data = NULL;
471*7c568831SAndroid Build Coastguard Worker } else {
472*7c568831SAndroid Build Coastguard Worker data[size] = 0;
473*7c568831SAndroid Build Coastguard Worker if (sizeRet != NULL)
474*7c568831SAndroid Build Coastguard Worker *sizeRet = size;
475*7c568831SAndroid Build Coastguard Worker }
476*7c568831SAndroid Build Coastguard Worker }
477*7c568831SAndroid Build Coastguard Worker fclose(file);
478*7c568831SAndroid Build Coastguard Worker
479*7c568831SAndroid Build Coastguard Worker return(data);
480*7c568831SAndroid Build Coastguard Worker }
481*7c568831SAndroid Build Coastguard Worker
482