xref: /aosp_15_r20/external/libxml2/fuzz/xml.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1 /*
2  * xml.c: a libFuzzer target to test several XML parser interfaces.
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/xmlsave.h>
12 #include "fuzz.h"
13 
14 int
LLVMFuzzerInitialize(int * argc ATTRIBUTE_UNUSED,char *** argv ATTRIBUTE_UNUSED)15 LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
16                      char ***argv ATTRIBUTE_UNUSED) {
17     xmlFuzzMemSetup();
18     xmlInitParser();
19 #ifdef LIBXML_CATALOG_ENABLED
20     xmlInitializeCatalog();
21     xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
22 #endif
23 
24     return 0;
25 }
26 
27 int
LLVMFuzzerTestOneInput(const char * data,size_t size)28 LLVMFuzzerTestOneInput(const char *data, size_t size) {
29     xmlParserCtxtPtr ctxt;
30     xmlDocPtr doc;
31     const char *docBuffer, *docUrl;
32     size_t maxAlloc, docSize;
33     int opts;
34 
35     xmlFuzzDataInit(data, size);
36     opts = (int) xmlFuzzReadInt(4);
37     /*
38      * Disable options that are known to cause timeouts
39      */
40     opts &= ~XML_PARSE_XINCLUDE &
41             ~XML_PARSE_DTDVALID &
42             ~XML_PARSE_SAX1;
43     maxAlloc = xmlFuzzReadInt(4) % (size + 100);
44 
45     xmlFuzzReadEntities();
46     docBuffer = xmlFuzzMainEntity(&docSize);
47     docUrl = xmlFuzzMainUrl();
48     if (docBuffer == NULL)
49         goto exit;
50 
51     /* Pull parser */
52 
53     xmlFuzzMemSetLimit(maxAlloc);
54     ctxt = xmlNewParserCtxt();
55     if (ctxt != NULL) {
56         xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
57         xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
58         doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts);
59         xmlFuzzCheckMallocFailure("xmlCtxtReadMemory",
60                                   doc == NULL &&
61                                   ctxt->errNo == XML_ERR_NO_MEMORY);
62 
63         if (doc != NULL) {
64 #ifdef LIBXML_OUTPUT_ENABLED
65             xmlBufferPtr buffer;
66             xmlSaveCtxtPtr save;
67 
68             /* Also test the serializer. */
69             buffer = xmlBufferCreate();
70             save = xmlSaveToBuffer(buffer, NULL, 0);
71             if (save != NULL) {
72                 int errNo;
73 
74                 xmlSaveDoc(save, doc);
75                 errNo = xmlSaveFinish(save);
76                 xmlFuzzCheckMallocFailure("xmlSaveDoc",
77                                           errNo == XML_ERR_NO_MEMORY);
78             }
79             xmlBufferFree(buffer);
80 #endif
81             xmlFreeDoc(doc);
82         }
83 
84         xmlFreeParserCtxt(ctxt);
85     }
86 
87     /* Push parser */
88 
89 #ifdef LIBXML_PUSH_ENABLED
90     {
91         static const size_t maxChunkSize = 128;
92         size_t consumed, chunkSize;
93 
94         xmlFuzzMemSetLimit(maxAlloc);
95         ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
96         if (ctxt != NULL) {
97             xmlCtxtSetErrorHandler(ctxt, xmlFuzzSErrorFunc, NULL);
98             xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
99             xmlCtxtUseOptions(ctxt, opts);
100 
101             for (consumed = 0; consumed < docSize; consumed += chunkSize) {
102                 chunkSize = docSize - consumed;
103                 if (chunkSize > maxChunkSize)
104                     chunkSize = maxChunkSize;
105                 xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0);
106             }
107 
108             xmlParseChunk(ctxt, NULL, 0, 1);
109             xmlFuzzCheckMallocFailure("xmlParseChunk",
110                                       ctxt->errNo == XML_ERR_NO_MEMORY);
111             xmlFreeDoc(ctxt->myDoc);
112             xmlFreeParserCtxt(ctxt);
113         }
114     }
115 #endif
116 
117 exit:
118     xmlFuzzMemSetLimit(0);
119     xmlFuzzDataCleanup();
120     xmlResetLastError();
121     return(0);
122 }
123 
124