Line | Count | Source (jump to first uncovered line) |
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/xmlreader.h> |
12 | | #include "fuzz.h" |
13 | | |
14 | | int |
15 | | LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED, |
16 | 50 | char ***argv ATTRIBUTE_UNUSED) { |
17 | 50 | xmlInitParser(); |
18 | 50 | #ifdef LIBXML_CATALOG_ENABLED |
19 | 50 | xmlInitializeCatalog(); |
20 | 50 | #endif |
21 | 50 | xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc); |
22 | 50 | xmlSetExternalEntityLoader(xmlFuzzEntityLoader); |
23 | | |
24 | 50 | return 0; |
25 | 50 | } |
26 | | |
27 | | int |
28 | 51.0k | LLVMFuzzerTestOneInput(const char *data, size_t size) { |
29 | 51.0k | static const size_t maxChunkSize = 128; |
30 | 51.0k | xmlDocPtr doc; |
31 | 51.0k | xmlParserCtxtPtr ctxt; |
32 | 51.0k | xmlTextReaderPtr reader; |
33 | 51.0k | xmlChar *out; |
34 | 51.0k | const char *docBuffer, *docUrl; |
35 | 51.0k | size_t docSize, consumed, chunkSize; |
36 | 51.0k | int opts, outSize; |
37 | | |
38 | 51.0k | xmlFuzzDataInit(data, size); |
39 | 51.0k | opts = xmlFuzzReadInt(); |
40 | 51.0k | opts &= ~XML_PARSE_XINCLUDE; |
41 | | |
42 | 51.0k | xmlFuzzReadEntities(); |
43 | 51.0k | docBuffer = xmlFuzzMainEntity(&docSize); |
44 | 51.0k | docUrl = xmlFuzzMainUrl(); |
45 | 51.0k | if (docBuffer == NULL) |
46 | 31 | goto exit; |
47 | | |
48 | | /* Pull parser */ |
49 | | |
50 | 50.9k | doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts); |
51 | | /* Also test the serializer. */ |
52 | 50.9k | xmlDocDumpMemory(doc, &out, &outSize); |
53 | 50.9k | xmlFree(out); |
54 | 50.9k | xmlFreeDoc(doc); |
55 | | |
56 | | /* Push parser */ |
57 | | |
58 | 50.9k | ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl); |
59 | 50.9k | if (ctxt == NULL) |
60 | 0 | goto exit; |
61 | 50.9k | xmlCtxtUseOptions(ctxt, opts); |
62 | | |
63 | 549k | for (consumed = 0; consumed < docSize; consumed += chunkSize) { |
64 | 498k | chunkSize = docSize - consumed; |
65 | 498k | if (chunkSize > maxChunkSize) |
66 | 448k | chunkSize = maxChunkSize; |
67 | 498k | xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0); |
68 | 498k | } |
69 | | |
70 | 50.9k | xmlParseChunk(ctxt, NULL, 0, 1); |
71 | 50.9k | xmlFreeDoc(ctxt->myDoc); |
72 | 50.9k | xmlFreeParserCtxt(ctxt); |
73 | | |
74 | | /* Reader */ |
75 | | |
76 | 50.9k | reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts); |
77 | 50.9k | if (reader == NULL) |
78 | 0 | goto exit; |
79 | 452k | while (xmlTextReaderRead(reader) == 1) { |
80 | 401k | if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) { |
81 | 138k | int i, n = xmlTextReaderAttributeCount(reader); |
82 | 290k | for (i=0; i<n; i++) { |
83 | 151k | xmlTextReaderMoveToAttributeNo(reader, i); |
84 | 304k | while (xmlTextReaderReadAttributeValue(reader) == 1); |
85 | 151k | } |
86 | 138k | } |
87 | 401k | } |
88 | 50.9k | xmlFreeTextReader(reader); |
89 | | |
90 | 51.0k | exit: |
91 | 51.0k | xmlFuzzDataCleanup(); |
92 | 51.0k | xmlResetLastError(); |
93 | 51.0k | return(0); |
94 | 50.9k | } |
95 | | |