xref: /aosp_15_r20/external/libxml2/fuzz/lint.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker  * xml.c: a libFuzzer target to test several XML parser interfaces.
3*7c568831SAndroid Build Coastguard Worker  *
4*7c568831SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
5*7c568831SAndroid Build Coastguard Worker  */
6*7c568831SAndroid Build Coastguard Worker 
7*7c568831SAndroid Build Coastguard Worker #include <fcntl.h>
8*7c568831SAndroid Build Coastguard Worker #include <stdlib.h>
9*7c568831SAndroid Build Coastguard Worker #include <stdio.h>
10*7c568831SAndroid Build Coastguard Worker #include <unistd.h>
11*7c568831SAndroid Build Coastguard Worker 
12*7c568831SAndroid Build Coastguard Worker #include <libxml/catalog.h>
13*7c568831SAndroid Build Coastguard Worker #include <libxml/parser.h>
14*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
15*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
16*7c568831SAndroid Build Coastguard Worker 
17*7c568831SAndroid Build Coastguard Worker #include "fuzz.h"
18*7c568831SAndroid Build Coastguard Worker 
19*7c568831SAndroid Build Coastguard Worker #define XMLLINT_FUZZ
20*7c568831SAndroid Build Coastguard Worker #include "../xmllint.c"
21*7c568831SAndroid Build Coastguard Worker 
22*7c568831SAndroid Build Coastguard Worker static const char *const switches[] = {
23*7c568831SAndroid Build Coastguard Worker     "--auto",
24*7c568831SAndroid Build Coastguard Worker     "--c14n",
25*7c568831SAndroid Build Coastguard Worker     "--c14n11",
26*7c568831SAndroid Build Coastguard Worker     "--compress",
27*7c568831SAndroid Build Coastguard Worker     "--copy",
28*7c568831SAndroid Build Coastguard Worker     "--debug",
29*7c568831SAndroid Build Coastguard Worker     "--debugent",
30*7c568831SAndroid Build Coastguard Worker     "--dropdtd",
31*7c568831SAndroid Build Coastguard Worker     "--dtdattr",
32*7c568831SAndroid Build Coastguard Worker     "--exc-c14n",
33*7c568831SAndroid Build Coastguard Worker     "--format",
34*7c568831SAndroid Build Coastguard Worker     "--htmlout",
35*7c568831SAndroid Build Coastguard Worker     "--huge",
36*7c568831SAndroid Build Coastguard Worker     "--insert",
37*7c568831SAndroid Build Coastguard Worker     "--loaddtd",
38*7c568831SAndroid Build Coastguard Worker     "--load-trace",
39*7c568831SAndroid Build Coastguard Worker     "--memory",
40*7c568831SAndroid Build Coastguard Worker     "--noblanks",
41*7c568831SAndroid Build Coastguard Worker     "--nocdata",
42*7c568831SAndroid Build Coastguard Worker     "--nocompact",
43*7c568831SAndroid Build Coastguard Worker     "--nodefdtd",
44*7c568831SAndroid Build Coastguard Worker     "--nodict",
45*7c568831SAndroid Build Coastguard Worker     "--noenc",
46*7c568831SAndroid Build Coastguard Worker     "--noent",
47*7c568831SAndroid Build Coastguard Worker     "--nofixup-base-uris",
48*7c568831SAndroid Build Coastguard Worker     "--nonet",
49*7c568831SAndroid Build Coastguard Worker     "--noout",
50*7c568831SAndroid Build Coastguard Worker     "--nowarning",
51*7c568831SAndroid Build Coastguard Worker     "--nowrap",
52*7c568831SAndroid Build Coastguard Worker     "--noxincludenode",
53*7c568831SAndroid Build Coastguard Worker     "--nsclean",
54*7c568831SAndroid Build Coastguard Worker     "--oldxml10",
55*7c568831SAndroid Build Coastguard Worker     "--pedantic",
56*7c568831SAndroid Build Coastguard Worker     "--postvalid",
57*7c568831SAndroid Build Coastguard Worker     "--push",
58*7c568831SAndroid Build Coastguard Worker     "--pushsmall",
59*7c568831SAndroid Build Coastguard Worker     "--quiet",
60*7c568831SAndroid Build Coastguard Worker     "--recover",
61*7c568831SAndroid Build Coastguard Worker     "--sax1",
62*7c568831SAndroid Build Coastguard Worker     "--testIO",
63*7c568831SAndroid Build Coastguard Worker     "--timing",
64*7c568831SAndroid Build Coastguard Worker     "--valid",
65*7c568831SAndroid Build Coastguard Worker     "--version",
66*7c568831SAndroid Build Coastguard Worker     "--walker",
67*7c568831SAndroid Build Coastguard Worker     "--xinclude",
68*7c568831SAndroid Build Coastguard Worker     "--xmlout"
69*7c568831SAndroid Build Coastguard Worker };
70*7c568831SAndroid Build Coastguard Worker static const size_t numSwitches = sizeof(switches) / sizeof(switches[0]);
71*7c568831SAndroid Build Coastguard Worker 
72*7c568831SAndroid Build Coastguard Worker struct {
73*7c568831SAndroid Build Coastguard Worker     const char **argv;
74*7c568831SAndroid Build Coastguard Worker     size_t argi;
75*7c568831SAndroid Build Coastguard Worker } vars;
76*7c568831SAndroid Build Coastguard Worker 
77*7c568831SAndroid Build Coastguard Worker static void
pushArg(const char * str)78*7c568831SAndroid Build Coastguard Worker pushArg(const char *str) {
79*7c568831SAndroid Build Coastguard Worker     vars.argv[vars.argi++] = str;
80*7c568831SAndroid Build Coastguard Worker }
81*7c568831SAndroid Build Coastguard Worker 
82*7c568831SAndroid Build Coastguard Worker int
LLVMFuzzerInitialize(int * argc ATTRIBUTE_UNUSED,char *** argv ATTRIBUTE_UNUSED)83*7c568831SAndroid Build Coastguard Worker LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
84*7c568831SAndroid Build Coastguard Worker                      char ***argv ATTRIBUTE_UNUSED) {
85*7c568831SAndroid Build Coastguard Worker     int fd;
86*7c568831SAndroid Build Coastguard Worker 
87*7c568831SAndroid Build Coastguard Worker     /* Redirect stdout to /dev/null */
88*7c568831SAndroid Build Coastguard Worker     fd = open("/dev/null", O_WRONLY);
89*7c568831SAndroid Build Coastguard Worker     if (fd == -1) {
90*7c568831SAndroid Build Coastguard Worker         perror("/dev/null");
91*7c568831SAndroid Build Coastguard Worker         abort();
92*7c568831SAndroid Build Coastguard Worker     }
93*7c568831SAndroid Build Coastguard Worker     if (dup2(fd, STDOUT_FILENO) == -1) {
94*7c568831SAndroid Build Coastguard Worker         perror("dup2");
95*7c568831SAndroid Build Coastguard Worker         abort();
96*7c568831SAndroid Build Coastguard Worker     }
97*7c568831SAndroid Build Coastguard Worker     close(fd);
98*7c568831SAndroid Build Coastguard Worker 
99*7c568831SAndroid Build Coastguard Worker     return 0;
100*7c568831SAndroid Build Coastguard Worker }
101*7c568831SAndroid Build Coastguard Worker 
102*7c568831SAndroid Build Coastguard Worker int
LLVMFuzzerTestOneInput(const char * data,size_t size)103*7c568831SAndroid Build Coastguard Worker LLVMFuzzerTestOneInput(const char *data, size_t size) {
104*7c568831SAndroid Build Coastguard Worker     char maxmemBuf[20];
105*7c568831SAndroid Build Coastguard Worker     char maxAmplBuf[20];
106*7c568831SAndroid Build Coastguard Worker     char prettyBuf[20];
107*7c568831SAndroid Build Coastguard Worker     const char *sval, *docBuffer, *docUrl;
108*7c568831SAndroid Build Coastguard Worker     size_t ssize, docSize, i;
109*7c568831SAndroid Build Coastguard Worker     unsigned uval;
110*7c568831SAndroid Build Coastguard Worker     int ival;
111*7c568831SAndroid Build Coastguard Worker 
112*7c568831SAndroid Build Coastguard Worker     vars.argv = malloc((numSwitches + 5 + 6 * 2) * sizeof(vars.argv[0]));
113*7c568831SAndroid Build Coastguard Worker     vars.argi = 0;
114*7c568831SAndroid Build Coastguard Worker     pushArg("xmllint"),
115*7c568831SAndroid Build Coastguard Worker     pushArg("--nocatalogs");
116*7c568831SAndroid Build Coastguard Worker 
117*7c568831SAndroid Build Coastguard Worker     xmlFuzzDataInit(data, size);
118*7c568831SAndroid Build Coastguard Worker 
119*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < numSwitches; i++) {
120*7c568831SAndroid Build Coastguard Worker         if (i % 32 == 0)
121*7c568831SAndroid Build Coastguard Worker             uval = xmlFuzzReadInt(4);
122*7c568831SAndroid Build Coastguard Worker         if ((uval & 1) && (switches[i] != NULL))
123*7c568831SAndroid Build Coastguard Worker             pushArg(switches[i]);
124*7c568831SAndroid Build Coastguard Worker         uval >>= 1;
125*7c568831SAndroid Build Coastguard Worker     }
126*7c568831SAndroid Build Coastguard Worker 
127*7c568831SAndroid Build Coastguard Worker     /*
128*7c568831SAndroid Build Coastguard Worker      * Use four main parsing modes with equal probability
129*7c568831SAndroid Build Coastguard Worker      */
130*7c568831SAndroid Build Coastguard Worker     switch (uval & 3) {
131*7c568831SAndroid Build Coastguard Worker         case 0:
132*7c568831SAndroid Build Coastguard Worker             /* XML parser */
133*7c568831SAndroid Build Coastguard Worker             break;
134*7c568831SAndroid Build Coastguard Worker         case 1:
135*7c568831SAndroid Build Coastguard Worker             /* HTML parser */
136*7c568831SAndroid Build Coastguard Worker             pushArg("--html");
137*7c568831SAndroid Build Coastguard Worker             break;
138*7c568831SAndroid Build Coastguard Worker         case 2:
139*7c568831SAndroid Build Coastguard Worker             /* XML reader */
140*7c568831SAndroid Build Coastguard Worker             pushArg("--stream");
141*7c568831SAndroid Build Coastguard Worker             break;
142*7c568831SAndroid Build Coastguard Worker         case 3:
143*7c568831SAndroid Build Coastguard Worker             /* SAX parser */
144*7c568831SAndroid Build Coastguard Worker             pushArg("--sax");
145*7c568831SAndroid Build Coastguard Worker             break;
146*7c568831SAndroid Build Coastguard Worker     }
147*7c568831SAndroid Build Coastguard Worker 
148*7c568831SAndroid Build Coastguard Worker     uval = xmlFuzzReadInt(4);
149*7c568831SAndroid Build Coastguard Worker     if (uval > 0) {
150*7c568831SAndroid Build Coastguard Worker         if (size <= (INT_MAX - 2000) / 20)
151*7c568831SAndroid Build Coastguard Worker             uval %= size * 20 + 2000;
152*7c568831SAndroid Build Coastguard Worker         else
153*7c568831SAndroid Build Coastguard Worker             uval %= INT_MAX;
154*7c568831SAndroid Build Coastguard Worker         snprintf(maxmemBuf, 20, "%u", uval);
155*7c568831SAndroid Build Coastguard Worker         pushArg("--maxmem");
156*7c568831SAndroid Build Coastguard Worker         pushArg(maxmemBuf);
157*7c568831SAndroid Build Coastguard Worker     }
158*7c568831SAndroid Build Coastguard Worker 
159*7c568831SAndroid Build Coastguard Worker     ival = xmlFuzzReadInt(1);
160*7c568831SAndroid Build Coastguard Worker     if (ival >= 1 && ival <= 5) {
161*7c568831SAndroid Build Coastguard Worker         snprintf(maxAmplBuf, 20, "%d", ival);
162*7c568831SAndroid Build Coastguard Worker         pushArg("--max-ampl");
163*7c568831SAndroid Build Coastguard Worker         pushArg(maxAmplBuf);
164*7c568831SAndroid Build Coastguard Worker     }
165*7c568831SAndroid Build Coastguard Worker 
166*7c568831SAndroid Build Coastguard Worker     ival = xmlFuzzReadInt(1);
167*7c568831SAndroid Build Coastguard Worker     if (ival != 0) {
168*7c568831SAndroid Build Coastguard Worker         snprintf(prettyBuf, 20, "%d", ival - 128);
169*7c568831SAndroid Build Coastguard Worker         pushArg("--pretty");
170*7c568831SAndroid Build Coastguard Worker         pushArg(prettyBuf);
171*7c568831SAndroid Build Coastguard Worker     }
172*7c568831SAndroid Build Coastguard Worker 
173*7c568831SAndroid Build Coastguard Worker     sval = xmlFuzzReadString(&ssize);
174*7c568831SAndroid Build Coastguard Worker     if (ssize > 0) {
175*7c568831SAndroid Build Coastguard Worker         pushArg("--encode");
176*7c568831SAndroid Build Coastguard Worker         pushArg(sval);
177*7c568831SAndroid Build Coastguard Worker     }
178*7c568831SAndroid Build Coastguard Worker 
179*7c568831SAndroid Build Coastguard Worker     sval = xmlFuzzReadString(&ssize);
180*7c568831SAndroid Build Coastguard Worker     if (ssize > 0) {
181*7c568831SAndroid Build Coastguard Worker         pushArg("--pattern");
182*7c568831SAndroid Build Coastguard Worker         pushArg(sval);
183*7c568831SAndroid Build Coastguard Worker     }
184*7c568831SAndroid Build Coastguard Worker 
185*7c568831SAndroid Build Coastguard Worker     sval = xmlFuzzReadString(&ssize);
186*7c568831SAndroid Build Coastguard Worker     if (ssize > 0) {
187*7c568831SAndroid Build Coastguard Worker         pushArg("--xpath");
188*7c568831SAndroid Build Coastguard Worker         pushArg(sval);
189*7c568831SAndroid Build Coastguard Worker     }
190*7c568831SAndroid Build Coastguard Worker 
191*7c568831SAndroid Build Coastguard Worker     xmlFuzzReadEntities();
192*7c568831SAndroid Build Coastguard Worker     docBuffer = xmlFuzzMainEntity(&docSize);
193*7c568831SAndroid Build Coastguard Worker     docUrl = xmlFuzzMainUrl();
194*7c568831SAndroid Build Coastguard Worker     if (docBuffer == NULL || docUrl[0] == '-')
195*7c568831SAndroid Build Coastguard Worker         goto exit;
196*7c568831SAndroid Build Coastguard Worker     pushArg(docUrl);
197*7c568831SAndroid Build Coastguard Worker 
198*7c568831SAndroid Build Coastguard Worker     pushArg(NULL);
199*7c568831SAndroid Build Coastguard Worker 
200*7c568831SAndroid Build Coastguard Worker     xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
201*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_CATALOG_ENABLED
202*7c568831SAndroid Build Coastguard Worker     xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
203*7c568831SAndroid Build Coastguard Worker #endif
204*7c568831SAndroid Build Coastguard Worker 
205*7c568831SAndroid Build Coastguard Worker     xmllintMain(vars.argi - 1, vars.argv, xmlFuzzResourceLoader);
206*7c568831SAndroid Build Coastguard Worker 
207*7c568831SAndroid Build Coastguard Worker     xmlMemSetup(free, malloc, realloc, xmlMemStrdup);
208*7c568831SAndroid Build Coastguard Worker 
209*7c568831SAndroid Build Coastguard Worker exit:
210*7c568831SAndroid Build Coastguard Worker     xmlFuzzDataCleanup();
211*7c568831SAndroid Build Coastguard Worker     free(vars.argv);
212*7c568831SAndroid Build Coastguard Worker     return(0);
213*7c568831SAndroid Build Coastguard Worker }
214