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