VirtualBox

source: vbox/trunk/src/libs/libxml2-2.12.6/fuzz/fuzz.c@ 105635

最後變更 在這個檔案從105635是 104106,由 vboxsync 提交於 10 月 前

libxml2-2.9.14: Applied and adjusted our libxml2 changes to 2.9.14. bugref:10640

  • 屬性 svn:eol-style 設為 native
檔案大小: 8.9 KB
 
1/*
2 * fuzz.c: Common functions for fuzzing.
3 *
4 * See Copyright for the status of this software.
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/stat.h>
11
12#include <libxml/hash.h>
13#include <libxml/parser.h>
14#include <libxml/parserInternals.h>
15#include <libxml/tree.h>
16#include <libxml/xmlIO.h>
17#include "fuzz.h"
18
19typedef struct {
20 const char *data;
21 size_t size;
22} xmlFuzzEntityInfo;
23
24/* Single static instance for now */
25static struct {
26 /* Original data */
27 const char *data;
28 size_t size;
29
30 /* Remaining data */
31 const char *ptr;
32 size_t remaining;
33
34 /* Buffer for unescaped strings */
35 char *outBuf;
36 char *outPtr; /* Free space at end of buffer */
37
38 xmlHashTablePtr entities; /* Maps URLs to xmlFuzzEntityInfos */
39
40 /* The first entity is the main entity. */
41 const char *mainUrl;
42 xmlFuzzEntityInfo *mainEntity;
43} fuzzData;
44
45size_t fuzzNumAllocs;
46size_t fuzzMaxAllocs;
47int fuzzAllocFailed;
48
49/**
50 * xmlFuzzErrorFunc:
51 *
52 * An error function that simply discards all errors.
53 */
54void
55xmlFuzzErrorFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,
56 ...) {
57}
58
59/*
60 * Malloc failure injection.
61 *
62 * Quick tip to debug complicated issues: Increase MALLOC_OFFSET until
63 * the crash disappears (or a different issue is triggered). Then set
64 * the offset to the highest value that produces a crash and set
65 * MALLOC_ABORT to 1 to see which failed memory allocation causes the
66 * issue.
67 */
68
69#define XML_FUZZ_MALLOC_OFFSET 0
70#define XML_FUZZ_MALLOC_ABORT 0
71
72static void *
73xmlFuzzMalloc(size_t size) {
74 if (fuzzMaxAllocs > 0) {
75 if (fuzzNumAllocs >= fuzzMaxAllocs - 1) {
76#if XML_FUZZ_MALLOC_ABORT
77 abort();
78#endif
79 fuzzAllocFailed = 1;
80 return(NULL);
81 }
82 fuzzNumAllocs += 1;
83 }
84 return malloc(size);
85}
86
87static void *
88xmlFuzzRealloc(void *ptr, size_t size) {
89 if (fuzzMaxAllocs > 0) {
90 if (fuzzNumAllocs >= fuzzMaxAllocs - 1) {
91#if XML_FUZZ_MALLOC_ABORT
92 abort();
93#endif
94 fuzzAllocFailed = 1;
95 return(NULL);
96 }
97 fuzzNumAllocs += 1;
98 }
99 return realloc(ptr, size);
100}
101
102void
103xmlFuzzMemSetup(void) {
104 xmlMemSetup(free, xmlFuzzMalloc, xmlFuzzRealloc, xmlMemStrdup);
105}
106
107void
108xmlFuzzMemSetLimit(size_t limit) {
109 fuzzNumAllocs = 0;
110 fuzzMaxAllocs = limit ? limit + XML_FUZZ_MALLOC_OFFSET : 0;
111 fuzzAllocFailed = 0;
112}
113
114int
115xmlFuzzMallocFailed(void) {
116 return fuzzAllocFailed;
117}
118
119/**
120 * xmlFuzzDataInit:
121 *
122 * Initialize fuzz data provider.
123 */
124void
125xmlFuzzDataInit(const char *data, size_t size) {
126 fuzzData.data = data;
127 fuzzData.size = size;
128 fuzzData.ptr = data;
129 fuzzData.remaining = size;
130
131 fuzzData.outBuf = xmlMalloc(size + 1);
132 fuzzData.outPtr = fuzzData.outBuf;
133
134 fuzzData.entities = xmlHashCreate(8);
135 fuzzData.mainUrl = NULL;
136 fuzzData.mainEntity = NULL;
137}
138
139/**
140 * xmlFuzzDataFree:
141 *
142 * Cleanup fuzz data provider.
143 */
144void
145xmlFuzzDataCleanup(void) {
146 xmlFree(fuzzData.outBuf);
147 xmlHashFree(fuzzData.entities, xmlHashDefaultDeallocator);
148}
149
150/**
151 * xmlFuzzWriteInt:
152 * @out: output file
153 * @v: integer to write
154 * @size: size of integer in bytes
155 *
156 * Write an integer to the fuzz data.
157 */
158void
159xmlFuzzWriteInt(FILE *out, size_t v, int size) {
160 int shift;
161
162 while (size > (int) sizeof(size_t)) {
163 putc(0, out);
164 size--;
165 }
166
167 shift = size * 8;
168 while (shift > 0) {
169 shift -= 8;
170 putc((v >> shift) & 255, out);
171 }
172}
173
174/**
175 * xmlFuzzReadInt:
176 * @size: size of integer in bytes
177 *
178 * Read an integer from the fuzz data.
179 */
180size_t
181xmlFuzzReadInt(int size) {
182 size_t ret = 0;
183
184 while ((size > 0) && (fuzzData.remaining > 0)) {
185 unsigned char c = (unsigned char) *fuzzData.ptr++;
186 fuzzData.remaining--;
187 ret = (ret << 8) | c;
188 size--;
189 }
190
191 return ret;
192}
193
194/**
195 * xmlFuzzReadRemaining:
196 * @size: size of string in bytes
197 *
198 * Read remaining bytes from fuzz data.
199 */
200const char *
201xmlFuzzReadRemaining(size_t *size) {
202 const char *ret = fuzzData.ptr;
203
204 *size = fuzzData.remaining;
205 fuzzData.ptr += fuzzData.remaining;
206 fuzzData.remaining = 0;
207
208 return(ret);
209}
210
211/*
212 * xmlFuzzWriteString:
213 * @out: output file
214 * @str: string to write
215 *
216 * Write a random-length string to file in a format similar to
217 * FuzzedDataProvider. Backslash followed by newline marks the end of the
218 * string. Two backslashes are used to escape a backslash.
219 */
220void
221xmlFuzzWriteString(FILE *out, const char *str) {
222 for (; *str; str++) {
223 int c = (unsigned char) *str;
224 putc(c, out);
225 if (c == '\\')
226 putc(c, out);
227 }
228 putc('\\', out);
229 putc('\n', out);
230}
231
232/**
233 * xmlFuzzReadString:
234 * @size: size of string in bytes
235 *
236 * Read a random-length string from the fuzz data.
237 *
238 * The format is similar to libFuzzer's FuzzedDataProvider but treats
239 * backslash followed by newline as end of string. This makes the fuzz data
240 * more readable. A backslash character is escaped with another backslash.
241 *
242 * Returns a zero-terminated string or NULL if the fuzz data is exhausted.
243 */
244const char *
245xmlFuzzReadString(size_t *size) {
246 const char *out = fuzzData.outPtr;
247
248 while (fuzzData.remaining > 0) {
249 int c = *fuzzData.ptr++;
250 fuzzData.remaining--;
251
252 if ((c == '\\') && (fuzzData.remaining > 0)) {
253 int c2 = *fuzzData.ptr;
254
255 if (c2 == '\n') {
256 fuzzData.ptr++;
257 fuzzData.remaining--;
258 if (size != NULL)
259 *size = fuzzData.outPtr - out;
260 *fuzzData.outPtr++ = '\0';
261 return(out);
262 }
263 if (c2 == '\\') {
264 fuzzData.ptr++;
265 fuzzData.remaining--;
266 }
267 }
268
269 *fuzzData.outPtr++ = c;
270 }
271
272 if (fuzzData.outPtr > out) {
273 if (size != NULL)
274 *size = fuzzData.outPtr - out;
275 *fuzzData.outPtr++ = '\0';
276 return(out);
277 }
278
279 if (size != NULL)
280 *size = 0;
281 return(NULL);
282}
283
284/**
285 * xmlFuzzReadEntities:
286 *
287 * Read entities like the main XML file, external DTDs, external parsed
288 * entities from fuzz data.
289 */
290void
291xmlFuzzReadEntities(void) {
292 size_t num = 0;
293
294 while (1) {
295 const char *url, *entity;
296 size_t entitySize;
297 xmlFuzzEntityInfo *entityInfo;
298
299 url = xmlFuzzReadString(NULL);
300 if (url == NULL) break;
301
302 entity = xmlFuzzReadString(&entitySize);
303 if (entity == NULL) break;
304
305 if (xmlHashLookup(fuzzData.entities, (xmlChar *)url) == NULL) {
306 entityInfo = xmlMalloc(sizeof(xmlFuzzEntityInfo));
307 if (entityInfo == NULL)
308 break;
309 entityInfo->data = entity;
310 entityInfo->size = entitySize;
311
312 xmlHashAddEntry(fuzzData.entities, (xmlChar *)url, entityInfo);
313
314 if (num == 0) {
315 fuzzData.mainUrl = url;
316 fuzzData.mainEntity = entityInfo;
317 }
318
319 num++;
320 }
321 }
322}
323
324/**
325 * xmlFuzzMainUrl:
326 *
327 * Returns the main URL.
328 */
329const char *
330xmlFuzzMainUrl(void) {
331 return(fuzzData.mainUrl);
332}
333
334/**
335 * xmlFuzzMainEntity:
336 * @size: size of the main entity in bytes
337 *
338 * Returns the main entity.
339 */
340const char *
341xmlFuzzMainEntity(size_t *size) {
342 if (fuzzData.mainEntity == NULL)
343 return(NULL);
344 *size = fuzzData.mainEntity->size;
345 return(fuzzData.mainEntity->data);
346}
347
348/**
349 * xmlFuzzEntityLoader:
350 *
351 * The entity loader for fuzz data.
352 */
353xmlParserInputPtr
354xmlFuzzEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED,
355 xmlParserCtxtPtr ctxt) {
356 xmlParserInputPtr input;
357 xmlFuzzEntityInfo *entity;
358
359 if (URL == NULL)
360 return(NULL);
361 entity = xmlHashLookup(fuzzData.entities, (xmlChar *) URL);
362 if (entity == NULL)
363 return(NULL);
364
365 input = xmlNewInputStream(ctxt);
366 if (input == NULL)
367 return(NULL);
368 input->filename = (char *) xmlCharStrdup(URL);
369 input->buf = xmlParserInputBufferCreateMem(entity->data, entity->size,
370 XML_CHAR_ENCODING_NONE);
371 if (input->buf == NULL) {
372 xmlFreeInputStream(input);
373 return(NULL);
374 }
375 input->base = input->cur = xmlBufContent(input->buf->buffer);
376 input->end = input->base + xmlBufUse(input->buf->buffer);
377
378 return input;
379}
380
381char *
382xmlSlurpFile(const char *path, size_t *sizeRet) {
383 FILE *file;
384 struct stat statbuf;
385 char *data;
386 size_t size;
387
388 if ((stat(path, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
389 return(NULL);
390 size = statbuf.st_size;
391 file = fopen(path, "rb");
392 if (file == NULL)
393 return(NULL);
394 data = xmlMalloc(size + 1);
395 if (data != NULL) {
396 if (fread(data, 1, size, file) != size) {
397 xmlFree(data);
398 data = NULL;
399 } else {
400 data[size] = 0;
401 if (sizeRet != NULL)
402 *sizeRet = size;
403 }
404 }
405 fclose(file);
406
407 return(data);
408}
409
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette