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