Coverage Report

Created: 2025-12-14 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
20
                     char ***argv ATTRIBUTE_UNUSED) {
17
20
    xmlFuzzMemSetup();
18
20
    xmlInitParser();
19
20
#ifdef LIBXML_CATALOG_ENABLED
20
20
    xmlInitializeCatalog();
21
20
    xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
22
20
#endif
23
20
    xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
24
25
20
    return 0;
26
20
}
27
28
int
29
30.7k
LLVMFuzzerTestOneInput(const char *data, size_t size) {
30
30.7k
    xmlParserCtxtPtr ctxt;
31
30.7k
    xmlDocPtr doc;
32
30.7k
    const char *docBuffer, *docUrl;
33
30.7k
    size_t failurePos, docSize;
34
30.7k
    int opts;
35
36
30.7k
    xmlFuzzDataInit(data, size);
37
30.7k
    opts = (int) xmlFuzzReadInt(4);
38
30.7k
    opts &= ~XML_PARSE_DTDVALID &
39
30.7k
            ~XML_PARSE_SAX1;
40
30.7k
    failurePos = xmlFuzzReadInt(4) % (size + 100);
41
42
30.7k
    xmlFuzzReadEntities();
43
30.7k
    docBuffer = xmlFuzzMainEntity(&docSize);
44
30.7k
    docUrl = xmlFuzzMainUrl();
45
30.7k
    if (docBuffer == NULL)
46
67
        goto exit;
47
48
    /* Pull parser */
49
50
30.7k
    xmlFuzzInjectFailure(failurePos);
51
30.7k
    ctxt = xmlNewParserCtxt();
52
30.7k
    if (ctxt != NULL) {
53
30.6k
        xmlXIncludeCtxtPtr xinc;
54
30.6k
        xmlDocPtr copy;
55
56
30.6k
        xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
57
58
30.6k
        doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts);
59
30.6k
        xmlFuzzCheckFailureReport("xmlCtxtReadMemory",
60
30.6k
                doc == NULL && ctxt->errNo == XML_ERR_NO_MEMORY,
61
30.6k
                doc == NULL && ctxt->errNo == XML_IO_EIO);
62
63
30.6k
        xinc = xmlXIncludeNewContext(doc);
64
30.6k
        xmlXIncludeSetResourceLoader(xinc, xmlFuzzResourceLoader, NULL);
65
30.6k
        xmlXIncludeSetFlags(xinc, opts);
66
30.6k
        xmlXIncludeProcessNode(xinc, (xmlNodePtr) doc);
67
30.6k
        if (doc != NULL) {
68
21.2k
            xmlFuzzCheckFailureReport("xmlXIncludeProcessNode",
69
21.2k
                    xinc == NULL ||
70
21.2k
                    xmlXIncludeGetLastError(xinc) == XML_ERR_NO_MEMORY,
71
21.2k
                    xinc != NULL &&
72
21.2k
                    xmlXIncludeGetLastError(xinc) == XML_IO_EIO);
73
21.2k
        }
74
30.6k
        xmlXIncludeFreeContext(xinc);
75
76
30.6k
        xmlFuzzResetFailure();
77
30.6k
        copy = xmlCopyDoc(doc, 1);
78
30.6k
        if (doc != NULL)
79
21.2k
            xmlFuzzCheckFailureReport("xmlCopyNode", copy == NULL, 0);
80
30.6k
        xmlFreeDoc(copy);
81
82
30.6k
        xmlFreeDoc(doc);
83
30.6k
        xmlFreeParserCtxt(ctxt);
84
30.6k
    }
85
86
30.7k
exit:
87
30.7k
    xmlFuzzInjectFailure(0);
88
30.7k
    xmlFuzzDataCleanup();
89
30.7k
    xmlResetLastError();
90
30.7k
    return(0);
91
30.7k
}
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