/src/libxml2/fuzz/xpath.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * xpath.c: a libFuzzer target to test XPath and XPointer expressions. |
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/xpointer.h> |
10 | | #include "fuzz.h" |
11 | | |
12 | | int |
13 | | LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED, |
14 | 20 | char ***argv ATTRIBUTE_UNUSED) { |
15 | 20 | xmlFuzzMemSetup(); |
16 | 20 | xmlInitParser(); |
17 | 20 | #ifdef LIBXML_CATALOG_ENABLED |
18 | 20 | xmlInitializeCatalog(); |
19 | 20 | xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE); |
20 | 20 | #endif |
21 | 20 | xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc); |
22 | | |
23 | 20 | return 0; |
24 | 20 | } |
25 | | |
26 | | int |
27 | 25.4k | LLVMFuzzerTestOneInput(const char *data, size_t size) { |
28 | 25.4k | xmlDocPtr doc; |
29 | 25.4k | const char *expr, *xml; |
30 | 25.4k | size_t failurePos, exprSize, xmlSize; |
31 | | |
32 | 25.4k | if (size > 10000) |
33 | 5 | return(0); |
34 | | |
35 | 25.4k | xmlFuzzDataInit(data, size); |
36 | | |
37 | 25.4k | failurePos = xmlFuzzReadInt(4) % (size + 100); |
38 | 25.4k | expr = xmlFuzzReadString(&exprSize); |
39 | 25.4k | xml = xmlFuzzReadString(&xmlSize); |
40 | | |
41 | | /* Recovery mode allows more input to be fuzzed. */ |
42 | 25.4k | doc = xmlReadMemory(xml, xmlSize, NULL, NULL, XML_PARSE_RECOVER); |
43 | 25.4k | if (doc != NULL) { |
44 | 25.3k | xmlXPathContextPtr xpctxt; |
45 | | |
46 | 25.3k | xmlFuzzInjectFailure(failurePos); |
47 | | |
48 | 25.3k | xpctxt = xmlXPathNewContext(doc); |
49 | 25.3k | if (xpctxt != NULL) { |
50 | 25.2k | int res; |
51 | | |
52 | | /* Operation limit to avoid timeout */ |
53 | 25.2k | xpctxt->opLimit = 500000; |
54 | | |
55 | 25.2k | res = xmlXPathContextSetCache(xpctxt, 1, 4, 0); |
56 | 25.2k | xmlFuzzCheckFailureReport("xmlXPathContextSetCache", res == -1, 0); |
57 | | |
58 | 25.2k | xmlFuzzResetFailure(); |
59 | 25.2k | xmlXPathFreeObject(xmlXPtrEval(BAD_CAST expr, xpctxt)); |
60 | 25.2k | xmlFuzzCheckFailureReport("xmlXPtrEval", |
61 | 25.2k | xpctxt->lastError.code == XML_ERR_NO_MEMORY, 0); |
62 | 25.2k | xmlXPathFreeContext(xpctxt); |
63 | 25.2k | } |
64 | | |
65 | 25.3k | xmlFuzzInjectFailure(0); |
66 | 25.3k | xmlFreeDoc(doc); |
67 | 25.3k | } |
68 | | |
69 | 25.4k | xmlFuzzDataCleanup(); |
70 | 25.4k | xmlResetLastError(); |
71 | | |
72 | 25.4k | return(0); |
73 | 25.4k | } |
74 | | |
75 | | size_t |
76 | | LLVMFuzzerCustomMutator(char *data, size_t size, size_t maxSize, |
77 | 0 | unsigned seed) { |
78 | 0 | static const xmlFuzzChunkDesc chunks[] = { |
79 | 0 | { 4, XML_FUZZ_PROB_ONE / 10 }, /* failurePos */ |
80 | 0 | { 0, 0 } |
81 | 0 | }; |
82 | |
|
83 | 0 | return xmlFuzzMutateChunks(chunks, data, size, maxSize, seed, |
84 | 0 | LLVMFuzzerMutate); |
85 | 0 | } |
86 | | |