• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * testparser.c: Additional parser tests
3  *
4  * See Copyright for the status of this software.
5  */
6 
7 #include <libxml/parser.h>
8 #include <libxml/xmlreader.h>
9 #include <libxml/xmlwriter.h>
10 #include <libxml/HTMLparser.h>
11 
12 #include <string.h>
13 
14 static int
testStandaloneWithEncoding(void)15 testStandaloneWithEncoding(void) {
16     xmlDocPtr doc;
17     const char *str =
18         "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
19         "<doc></doc>\n";
20     int err = 0;
21 
22     xmlResetLastError();
23 
24     doc = xmlReadDoc(BAD_CAST str, NULL, "UTF-8", 0);
25     if (doc == NULL) {
26         fprintf(stderr, "xmlReadDoc failed\n");
27         err = 1;
28     }
29     xmlFreeDoc(doc);
30 
31     return err;
32 }
33 
34 static int
testUnsupportedEncoding(void)35 testUnsupportedEncoding(void) {
36     xmlDocPtr doc;
37     const xmlError *error;
38     int err = 0;
39 
40     xmlResetLastError();
41 
42     doc = xmlReadDoc(BAD_CAST "<doc/>", NULL, "#unsupported",
43                      XML_PARSE_NOWARNING);
44     if (doc == NULL) {
45         fprintf(stderr, "xmlReadDoc failed with unsupported encoding\n");
46         err = 1;
47     }
48     xmlFreeDoc(doc);
49 
50     error = xmlGetLastError();
51     if (error->code != XML_ERR_UNSUPPORTED_ENCODING ||
52         error->level != XML_ERR_WARNING ||
53         strcmp(error->message, "Unsupported encoding: #unsupported\n") != 0)
54     {
55         fprintf(stderr, "xmlReadDoc failed to raise correct error\n");
56         err = 1;
57     }
58 
59     return err;
60 }
61 
62 static int
testNodeGetContent(void)63 testNodeGetContent(void) {
64     xmlDocPtr doc;
65     xmlChar *content;
66     int err = 0;
67 
68     doc = xmlReadDoc(BAD_CAST "<doc/>", NULL, NULL, 0);
69     xmlAddChild(doc->children, xmlNewReference(doc, BAD_CAST "lt"));
70     content = xmlNodeGetContent((xmlNodePtr) doc);
71     if (strcmp((char *) content, "<") != 0) {
72         fprintf(stderr, "xmlNodeGetContent failed\n");
73         err = 1;
74     }
75     xmlFree(content);
76     xmlFreeDoc(doc);
77 
78     return err;
79 }
80 
81 #ifdef LIBXML_SAX1_ENABLED
82 static int
testBalancedChunk(void)83 testBalancedChunk(void) {
84     xmlNodePtr list;
85     xmlNodePtr elem;
86     int ret;
87     int err = 0;
88 
89     ret = xmlParseBalancedChunkMemory(NULL, NULL, NULL, 0,
90             BAD_CAST "start <node xml:lang='en'>abc</node> end", &list);
91 
92     if ((ret != XML_ERR_OK) ||
93         (list == NULL) ||
94         ((elem = list->next) == NULL) ||
95         (elem->type != XML_ELEMENT_NODE) ||
96         (elem->nsDef == NULL) ||
97         (!xmlStrEqual(elem->nsDef->href, XML_XML_NAMESPACE))) {
98         fprintf(stderr, "xmlParseBalancedChunkMemory failed\n");
99         err = 1;
100     }
101 
102     xmlFreeNodeList(list);
103 
104     return(err);
105 }
106 #endif
107 
108 #ifdef LIBXML_PUSH_ENABLED
109 static int
testHugePush(void)110 testHugePush(void) {
111     xmlParserCtxtPtr ctxt;
112     int err, i;
113 
114     ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
115 
116     /*
117      * Push parse a document larger than XML_MAX_LOOKUP_LIMIT
118      * (10,000,000 bytes). This mainly tests whether shrinking the
119      * buffer works when push parsing.
120      */
121     xmlParseChunk(ctxt, "<doc>", 5, 0);
122     for (i = 0; i < 1000000; i++)
123         xmlParseChunk(ctxt, "<elem>text</elem>", 17, 0);
124     xmlParseChunk(ctxt, "</doc>", 6, 1);
125 
126     err = ctxt->wellFormed ? 0 : 1;
127     xmlFreeDoc(ctxt->myDoc);
128     xmlFreeParserCtxt(ctxt);
129 
130     return err;
131 }
132 
133 static int
testHugeEncodedChunk(void)134 testHugeEncodedChunk(void) {
135     xmlBufferPtr buf;
136     xmlChar *chunk;
137     xmlParserCtxtPtr ctxt;
138     int err, i;
139 
140     /*
141      * Test the push parser with a built-in encoding handler like ISO-8859-1
142      * and a chunk larger than the initial decoded buffer (currently 4 KB).
143      */
144     buf = xmlBufferCreate();
145     xmlBufferCat(buf,
146             BAD_CAST "<?xml version='1.0' encoding='ISO-8859-1'?>\n");
147     xmlBufferCat(buf, BAD_CAST "<doc><!-- ");
148     for (i = 0; i < 2000; i++)
149         xmlBufferCat(buf, BAD_CAST "0123456789");
150     xmlBufferCat(buf, BAD_CAST " --></doc>");
151     chunk = xmlBufferDetach(buf);
152     xmlBufferFree(buf);
153 
154     ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
155 
156     xmlParseChunk(ctxt, (char *) chunk, xmlStrlen(chunk), 0);
157     xmlParseChunk(ctxt, NULL, 0, 1);
158 
159     err = ctxt->wellFormed ? 0 : 1;
160     xmlFreeDoc(ctxt->myDoc);
161     xmlFreeParserCtxt(ctxt);
162     xmlFree(chunk);
163 
164     return err;
165 }
166 
167 #ifdef LIBXML_HTML_ENABLED
168 static int
testHtmlPushWithEncoding(void)169 testHtmlPushWithEncoding(void) {
170     htmlParserCtxtPtr ctxt;
171     htmlDocPtr doc;
172     htmlNodePtr node;
173     int err = 0;
174 
175     ctxt = htmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL,
176                                     XML_CHAR_ENCODING_UTF8);
177     htmlParseChunk(ctxt, "-\xC3\xA4-", 4, 1);
178 
179     doc = ctxt->myDoc;
180     if (!xmlStrEqual(doc->encoding, BAD_CAST "UTF-8")) {
181         fprintf(stderr, "testHtmlPushWithEncoding failed\n");
182         err = 1;
183     }
184 
185     node = xmlDocGetRootElement(doc)->children->children->children;
186     if (!xmlStrEqual(node->content, BAD_CAST "-\xC3\xA4-")) {
187         fprintf(stderr, "testHtmlPushWithEncoding failed\n");
188         err = 1;
189     }
190 
191     xmlFreeDoc(doc);
192     htmlFreeParserCtxt(ctxt);
193     return err;
194 }
195 #endif
196 #endif
197 
198 #ifdef LIBXML_READER_ENABLED
199 static int
testReaderEncoding(void)200 testReaderEncoding(void) {
201     xmlBuffer *buf;
202     xmlTextReader *reader;
203     xmlChar *xml;
204     const xmlChar *encoding;
205     int err = 0;
206     int i;
207 
208     buf = xmlBufferCreate();
209     xmlBufferCCat(buf, "<?xml version='1.0' encoding='ISO-8859-1'?>\n");
210     xmlBufferCCat(buf, "<doc>");
211     for (i = 0; i < 8192; i++)
212         xmlBufferCCat(buf, "x");
213     xmlBufferCCat(buf, "</doc>");
214     xml = xmlBufferDetach(buf);
215     xmlBufferFree(buf);
216 
217     reader = xmlReaderForDoc(BAD_CAST xml, NULL, NULL, 0);
218     xmlTextReaderRead(reader);
219     encoding = xmlTextReaderConstEncoding(reader);
220 
221     if (!xmlStrEqual(encoding, BAD_CAST "ISO-8859-1")) {
222         fprintf(stderr, "testReaderEncoding failed\n");
223         err = 1;
224     }
225 
226     xmlFreeTextReader(reader);
227     xmlFree(xml);
228     return err;
229 }
230 
231 static int
testReaderContent(void)232 testReaderContent(void) {
233     xmlTextReader *reader;
234     const xmlChar *xml = BAD_CAST "<d>x<e>y</e><f>z</f></d>";
235     xmlChar *string;
236     int err = 0;
237 
238     reader = xmlReaderForDoc(xml, NULL, NULL, 0);
239     xmlTextReaderRead(reader);
240 
241     string = xmlTextReaderReadOuterXml(reader);
242     if (!xmlStrEqual(string, xml)) {
243         fprintf(stderr, "xmlTextReaderReadOuterXml failed\n");
244         err = 1;
245     }
246     xmlFree(string);
247 
248     string = xmlTextReaderReadInnerXml(reader);
249     if (!xmlStrEqual(string, BAD_CAST "x<e>y</e><f>z</f>")) {
250         fprintf(stderr, "xmlTextReaderReadInnerXml failed\n");
251         err = 1;
252     }
253     xmlFree(string);
254 
255     string = xmlTextReaderReadString(reader);
256     if (!xmlStrEqual(string, BAD_CAST "xyz")) {
257         fprintf(stderr, "xmlTextReaderReadString failed\n");
258         err = 1;
259     }
260     xmlFree(string);
261 
262     xmlFreeTextReader(reader);
263     return err;
264 }
265 
266 #ifdef LIBXML_XINCLUDE_ENABLED
267 typedef struct {
268     char *message;
269     int code;
270 } testReaderErrorCtxt;
271 
272 static void
testReaderError(void * arg,const char * msg,xmlParserSeverities severity ATTRIBUTE_UNUSED,xmlTextReaderLocatorPtr locator ATTRIBUTE_UNUSED)273 testReaderError(void *arg, const char *msg,
274                 xmlParserSeverities severity ATTRIBUTE_UNUSED,
275                 xmlTextReaderLocatorPtr locator ATTRIBUTE_UNUSED) {
276     testReaderErrorCtxt *ctxt = arg;
277 
278     if (ctxt->message != NULL)
279         xmlFree(ctxt->message);
280     ctxt->message = xmlMemStrdup(msg);
281 }
282 
283 static void
testStructuredReaderError(void * arg,const xmlError * error)284 testStructuredReaderError(void *arg, const xmlError *error) {
285     testReaderErrorCtxt *ctxt = arg;
286 
287     if (ctxt->message != NULL)
288         xmlFree(ctxt->message);
289     ctxt->message = xmlMemStrdup(error->message);
290     ctxt->code = error->code;
291 }
292 
293 static int
testReaderXIncludeError(void)294 testReaderXIncludeError(void) {
295     /*
296      * Test whether XInclude errors are reported to the custom error
297      * handler of a reader.
298      */
299     const char *doc =
300         "<doc xmlns:xi='http://www.w3.org/2001/XInclude'>\n"
301         "  <xi:include/>\n"
302         "</doc>\n";
303     xmlTextReader *reader;
304     testReaderErrorCtxt errorCtxt;
305     int err = 0;
306 
307     reader = xmlReaderForDoc(BAD_CAST doc, NULL, NULL, XML_PARSE_XINCLUDE);
308     xmlTextReaderSetErrorHandler(reader, testReaderError, &errorCtxt);
309     errorCtxt.message = NULL;
310     errorCtxt.code = 0;
311     while (xmlTextReaderRead(reader) > 0)
312         ;
313 
314     if (errorCtxt.message == NULL ||
315         strstr(errorCtxt.message, "href or xpointer") == NULL) {
316         fprintf(stderr, "xmlTextReaderSetErrorHandler failed\n");
317         err = 1;
318     }
319 
320     xmlFree(errorCtxt.message);
321     xmlFreeTextReader(reader);
322 
323     reader = xmlReaderForDoc(BAD_CAST doc, NULL, NULL, XML_PARSE_XINCLUDE);
324     xmlTextReaderSetStructuredErrorHandler(reader, testStructuredReaderError,
325                                            &errorCtxt);
326     errorCtxt.message = NULL;
327     errorCtxt.code = 0;
328     while (xmlTextReaderRead(reader) > 0)
329         ;
330 
331     if (errorCtxt.code != XML_XINCLUDE_NO_HREF ||
332         errorCtxt.message == NULL ||
333         strstr(errorCtxt.message, "href or xpointer") == NULL) {
334         fprintf(stderr, "xmlTextReaderSetStructuredErrorHandler failed\n");
335         err = 1;
336     }
337 
338     xmlFree(errorCtxt.message);
339     xmlFreeTextReader(reader);
340 
341     return err;
342 }
343 #endif
344 #endif
345 
346 #ifdef LIBXML_WRITER_ENABLED
347 static int
testWriterIOWrite(void * ctxt,const char * data,int len)348 testWriterIOWrite(void *ctxt, const char *data, int len) {
349     (void) ctxt;
350     (void) data;
351 
352     return len;
353 }
354 
355 static int
testWriterIOClose(void * ctxt)356 testWriterIOClose(void *ctxt) {
357     (void) ctxt;
358 
359     return XML_IO_ENAMETOOLONG;
360 }
361 
362 static int
testWriterClose(void)363 testWriterClose(void){
364     xmlOutputBufferPtr out;
365     xmlTextWriterPtr writer;
366     int err = 0;
367     int result;
368 
369     out = xmlOutputBufferCreateIO(testWriterIOWrite, testWriterIOClose,
370                                   NULL, NULL);
371     writer = xmlNewTextWriter(out);
372     xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
373     xmlTextWriterStartElement(writer, BAD_CAST "elem");
374     xmlTextWriterEndElement(writer);
375     xmlTextWriterEndDocument(writer);
376     result = xmlTextWriterClose(writer);
377 
378     if (result != XML_IO_ENAMETOOLONG) {
379         fprintf(stderr, "xmlTextWriterClose reported wrong error %d\n",
380                 result);
381         err = 1;
382     }
383 
384     xmlFreeTextWriter(writer);
385     return err;
386 }
387 #endif
388 
389 int
main(void)390 main(void) {
391     int err = 0;
392 
393     err |= testStandaloneWithEncoding();
394     err |= testUnsupportedEncoding();
395     err |= testNodeGetContent();
396 #ifdef LIBXML_SAX1_ENABLED
397     err |= testBalancedChunk();
398 #endif
399 #ifdef LIBXML_PUSH_ENABLED
400     err |= testHugePush();
401     err |= testHugeEncodedChunk();
402 #ifdef LIBXML_HTML_ENABLED
403     err |= testHtmlPushWithEncoding();
404 #endif
405 #endif
406 #ifdef LIBXML_READER_ENABLED
407     err |= testReaderEncoding();
408     err |= testReaderContent();
409 #ifdef LIBXML_XINCLUDE_ENABLED
410     err |= testReaderXIncludeError();
411 #endif
412 #endif
413 #ifdef LIBXML_WRITER_ENABLED
414     err |= testWriterClose();
415 #endif
416 
417     return err;
418 }
419 
420