/src/libxml2/fuzz/xinclude.c
Line | Count | Source |
1 | | /* |
2 | | * xinclude.c: a libFuzzer target to test the XInclude engine. |
3 | | * |
4 | | * See Copyright for the status of this software. |
5 | | */ |
6 | | |
7 | | #include <libxml/catalog.h> |
8 | | #include <libxml/parser.h> |
9 | | #include <libxml/tree.h> |
10 | | #include <libxml/xmlerror.h> |
11 | | #include <libxml/xinclude.h> |
12 | | #include "fuzz.h" |
13 | | |
14 | | int |
15 | | LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED, |
16 | 2 | char ***argv ATTRIBUTE_UNUSED) { |
17 | 2 | xmlFuzzMemSetup(); |
18 | 2 | xmlInitParser(); |
19 | 2 | #ifdef LIBXML_CATALOG_ENABLED |
20 | 2 | xmlInitializeCatalog(); |
21 | 2 | xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE); |
22 | 2 | #endif |
23 | 2 | xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc); |
24 | | |
25 | 2 | return 0; |
26 | 2 | } |
27 | | |
28 | | int |
29 | 31.5k | LLVMFuzzerTestOneInput(const char *data, size_t size) { |
30 | 31.5k | xmlParserCtxtPtr ctxt; |
31 | 31.5k | xmlDocPtr doc; |
32 | 31.5k | const char *docBuffer, *docUrl; |
33 | 31.5k | size_t failurePos, docSize; |
34 | 31.5k | int opts; |
35 | | |
36 | 31.5k | xmlFuzzDataInit(data, size); |
37 | 31.5k | opts = (int) xmlFuzzReadInt(4); |
38 | 31.5k | opts &= ~XML_PARSE_DTDVALID & |
39 | 31.5k | ~XML_PARSE_SAX1; |
40 | 31.5k | failurePos = xmlFuzzReadInt(4) % (size + 100); |
41 | | |
42 | 31.5k | xmlFuzzReadEntities(); |
43 | 31.5k | docBuffer = xmlFuzzMainEntity(&docSize); |
44 | 31.5k | docUrl = xmlFuzzMainUrl(); |
45 | 31.5k | if (docBuffer == NULL) |
46 | 67 | goto exit; |
47 | | |
48 | | /* Pull parser */ |
49 | | |
50 | 31.4k | xmlFuzzInjectFailure(failurePos); |
51 | 31.4k | ctxt = xmlNewParserCtxt(); |
52 | 31.4k | if (ctxt != NULL) { |
53 | 31.4k | xmlXIncludeCtxtPtr xinc; |
54 | 31.4k | xmlDocPtr copy; |
55 | | |
56 | 31.4k | xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL); |
57 | | |
58 | 31.4k | doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts); |
59 | 31.4k | xmlFuzzCheckFailureReport("xmlCtxtReadMemory", |
60 | 31.4k | doc == NULL && ctxt->errNo == XML_ERR_NO_MEMORY, |
61 | 31.4k | doc == NULL && ctxt->errNo == XML_IO_EIO); |
62 | | |
63 | 31.4k | xinc = xmlXIncludeNewContext(doc); |
64 | 31.4k | xmlXIncludeSetResourceLoader(xinc, xmlFuzzResourceLoader, NULL); |
65 | 31.4k | xmlXIncludeSetFlags(xinc, opts); |
66 | 31.4k | xmlXIncludeProcessNode(xinc, (xmlNodePtr) doc); |
67 | 31.4k | if (doc != NULL) { |
68 | 21.8k | xmlFuzzCheckFailureReport("xmlXIncludeProcessNode", |
69 | 21.8k | xinc == NULL || |
70 | 21.7k | xmlXIncludeGetLastError(xinc) == XML_ERR_NO_MEMORY, |
71 | 21.8k | xinc != NULL && |
72 | 21.7k | xmlXIncludeGetLastError(xinc) == XML_IO_EIO); |
73 | 21.8k | } |
74 | 31.4k | xmlXIncludeFreeContext(xinc); |
75 | | |
76 | 31.4k | xmlFuzzResetFailure(); |
77 | 31.4k | copy = xmlCopyDoc(doc, 1); |
78 | 31.4k | if (doc != NULL) |
79 | 21.8k | xmlFuzzCheckFailureReport("xmlCopyNode", copy == NULL, 0); |
80 | 31.4k | xmlFreeDoc(copy); |
81 | | |
82 | 31.4k | xmlFreeDoc(doc); |
83 | 31.4k | xmlFreeParserCtxt(ctxt); |
84 | 31.4k | } |
85 | | |
86 | 31.5k | exit: |
87 | 31.5k | xmlFuzzInjectFailure(0); |
88 | 31.5k | xmlFuzzDataCleanup(); |
89 | 31.5k | xmlResetLastError(); |
90 | 31.5k | return(0); |
91 | 31.4k | } |
92 | | |
93 | | size_t |
94 | | LLVMFuzzerCustomMutator(char *data, size_t size, size_t maxSize, |
95 | 0 | unsigned seed) { |
96 | 0 | static const xmlFuzzChunkDesc chunks[] = { |
97 | 0 | { 4, XML_FUZZ_PROB_ONE / 10 }, /* opts */ |
98 | 0 | { 4, XML_FUZZ_PROB_ONE / 10 }, /* failurePos */ |
99 | 0 | { 0, 0 } |
100 | 0 | }; |
101 | |
|
102 | 0 | return xmlFuzzMutateChunks(chunks, data, size, maxSize, seed, |
103 | 0 | LLVMFuzzerMutate); |
104 | 0 | } |
105 | | |