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
11 #include <string.h>
12
13 static int
testStandaloneWithEncoding(void)14 testStandaloneWithEncoding(void) {
15 xmlDocPtr doc;
16 const char *str =
17 "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
18 "<doc></doc>\n";
19 int err = 0;
20
21 xmlResetLastError();
22
23 doc = xmlReadDoc(BAD_CAST str, NULL, "UTF-8", 0);
24 if (doc == NULL) {
25 fprintf(stderr, "xmlReadDoc failed\n");
26 err = 1;
27 }
28 xmlFreeDoc(doc);
29
30 return err;
31 }
32
33 static int
testUnsupportedEncoding(void)34 testUnsupportedEncoding(void) {
35 xmlDocPtr doc;
36 const xmlError *error;
37 int err = 0;
38
39 xmlResetLastError();
40
41 doc = xmlReadDoc(BAD_CAST "<doc/>", NULL, "#unsupported",
42 XML_PARSE_NOWARNING);
43 if (doc == NULL) {
44 fprintf(stderr, "xmlReadDoc failed with unsupported encoding\n");
45 err = 1;
46 }
47 xmlFreeDoc(doc);
48
49 error = xmlGetLastError();
50 if (error->code != XML_ERR_UNSUPPORTED_ENCODING ||
51 error->level != XML_ERR_WARNING ||
52 strcmp(error->message, "Unsupported encoding: #unsupported\n") != 0)
53 {
54 fprintf(stderr, "xmlReadDoc failed to raise correct error\n");
55 err = 1;
56 }
57
58 return err;
59 }
60
61 #ifdef LIBXML_SAX1_ENABLED
62 static int
testBalancedChunk(void)63 testBalancedChunk(void) {
64 xmlNodePtr list;
65 xmlNodePtr elem;
66 int ret;
67 int err = 0;
68
69 ret = xmlParseBalancedChunkMemory(NULL, NULL, NULL, 0,
70 BAD_CAST "start <node xml:lang='en'>abc</node> end", &list);
71
72 if ((ret != XML_ERR_OK) ||
73 (list == NULL) ||
74 ((elem = list->next) == NULL) ||
75 (elem->type != XML_ELEMENT_NODE) ||
76 (elem->nsDef == NULL) ||
77 (!xmlStrEqual(elem->nsDef->href, XML_XML_NAMESPACE))) {
78 fprintf(stderr, "xmlParseBalancedChunkMemory failed\n");
79 err = 1;
80 }
81
82 xmlFreeNodeList(list);
83
84 return(err);
85 }
86 #endif
87
88 #ifdef LIBXML_PUSH_ENABLED
89 static int
testHugePush(void)90 testHugePush(void) {
91 xmlParserCtxtPtr ctxt;
92 int err, i;
93
94 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
95
96 /*
97 * Push parse a document larger than XML_MAX_LOOKUP_LIMIT
98 * (10,000,000 bytes). This mainly tests whether shrinking the
99 * buffer works when push parsing.
100 */
101 xmlParseChunk(ctxt, "<doc>", 5, 0);
102 for (i = 0; i < 1000000; i++)
103 xmlParseChunk(ctxt, "<elem>text</elem>", 17, 0);
104 xmlParseChunk(ctxt, "</doc>", 6, 1);
105
106 err = ctxt->wellFormed ? 0 : 1;
107 xmlFreeDoc(ctxt->myDoc);
108 xmlFreeParserCtxt(ctxt);
109
110 return err;
111 }
112
113 static int
testHugeEncodedChunk(void)114 testHugeEncodedChunk(void) {
115 xmlBufferPtr buf;
116 xmlChar *chunk;
117 xmlParserCtxtPtr ctxt;
118 int err, i;
119
120 /*
121 * Test the push parser with a built-in encoding handler like ISO-8859-1
122 * and a chunk larger than the initial decoded buffer (currently 4 KB).
123 */
124 buf = xmlBufferCreate();
125 xmlBufferCat(buf,
126 BAD_CAST "<?xml version='1.0' encoding='ISO-8859-1'?>\n");
127 xmlBufferCat(buf, BAD_CAST "<doc><!-- ");
128 for (i = 0; i < 2000; i++)
129 xmlBufferCat(buf, BAD_CAST "0123456789");
130 xmlBufferCat(buf, BAD_CAST " --></doc>");
131 chunk = xmlBufferDetach(buf);
132 xmlBufferFree(buf);
133
134 ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
135
136 xmlParseChunk(ctxt, (char *) chunk, xmlStrlen(chunk), 0);
137 xmlParseChunk(ctxt, NULL, 0, 1);
138
139 err = ctxt->wellFormed ? 0 : 1;
140 xmlFreeDoc(ctxt->myDoc);
141 xmlFreeParserCtxt(ctxt);
142 xmlFree(chunk);
143
144 return err;
145 }
146 #endif
147
148 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_XINCLUDE_ENABLED)
149 typedef struct {
150 char *message;
151 int code;
152 } testReaderErrorCtxt;
153
154 static void
testReaderError(void * arg,const char * msg,xmlParserSeverities severity ATTRIBUTE_UNUSED,xmlTextReaderLocatorPtr locator ATTRIBUTE_UNUSED)155 testReaderError(void *arg, const char *msg,
156 xmlParserSeverities severity ATTRIBUTE_UNUSED,
157 xmlTextReaderLocatorPtr locator ATTRIBUTE_UNUSED) {
158 testReaderErrorCtxt *ctxt = arg;
159
160 if (ctxt->message != NULL)
161 xmlFree(ctxt->message);
162 ctxt->message = xmlMemStrdup(msg);
163 }
164
165 static void
testStructuredReaderError(void * arg,const xmlError * error)166 testStructuredReaderError(void *arg, const xmlError *error) {
167 testReaderErrorCtxt *ctxt = arg;
168
169 if (ctxt->message != NULL)
170 xmlFree(ctxt->message);
171 ctxt->message = xmlMemStrdup(error->message);
172 ctxt->code = error->code;
173 }
174
175 static int
testReaderXIncludeError(void)176 testReaderXIncludeError(void) {
177 /*
178 * Test whether XInclude errors are reported to the custom error
179 * handler of a reader.
180 */
181 const char *doc =
182 "<doc xmlns:xi='http://www.w3.org/2001/XInclude'>\n"
183 " <xi:include/>\n"
184 "</doc>\n";
185 xmlTextReader *reader;
186 testReaderErrorCtxt errorCtxt;
187 int err = 0;
188
189 reader = xmlReaderForDoc(BAD_CAST doc, NULL, NULL, XML_PARSE_XINCLUDE);
190 xmlTextReaderSetErrorHandler(reader, testReaderError, &errorCtxt);
191 errorCtxt.message = NULL;
192 errorCtxt.code = 0;
193 while (xmlTextReaderRead(reader) > 0)
194 ;
195
196 if (errorCtxt.message == NULL ||
197 strstr(errorCtxt.message, "href or xpointer") == NULL) {
198 fprintf(stderr, "xmlTextReaderSetErrorHandler failed\n");
199 err = 1;
200 }
201
202 xmlFree(errorCtxt.message);
203 xmlFreeTextReader(reader);
204
205 reader = xmlReaderForDoc(BAD_CAST doc, NULL, NULL, XML_PARSE_XINCLUDE);
206 xmlTextReaderSetStructuredErrorHandler(reader, testStructuredReaderError,
207 &errorCtxt);
208 errorCtxt.message = NULL;
209 errorCtxt.code = 0;
210 while (xmlTextReaderRead(reader) > 0)
211 ;
212
213 if (errorCtxt.code != XML_XINCLUDE_NO_HREF ||
214 errorCtxt.message == NULL ||
215 strstr(errorCtxt.message, "href or xpointer") == NULL) {
216 fprintf(stderr, "xmlTextReaderSetStructuredErrorHandler failed\n");
217 err = 1;
218 }
219
220 xmlFree(errorCtxt.message);
221 xmlFreeTextReader(reader);
222
223 return err;
224 }
225 #endif
226
227 #ifdef LIBXML_WRITER_ENABLED
228 static int
testWriterIOWrite(void * ctxt,const char * data,int len)229 testWriterIOWrite(void *ctxt, const char *data, int len) {
230 (void) ctxt;
231 (void) data;
232
233 return len;
234 }
235
236 static int
testWriterIOClose(void * ctxt)237 testWriterIOClose(void *ctxt) {
238 (void) ctxt;
239
240 return XML_IO_ENAMETOOLONG;
241 }
242
243 static int
testWriterClose(void)244 testWriterClose(void){
245 xmlOutputBufferPtr out;
246 xmlTextWriterPtr writer;
247 int err = 0;
248 int result;
249
250 out = xmlOutputBufferCreateIO(testWriterIOWrite, testWriterIOClose,
251 NULL, NULL);
252 writer = xmlNewTextWriter(out);
253 xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
254 xmlTextWriterStartElement(writer, BAD_CAST "elem");
255 xmlTextWriterEndElement(writer);
256 xmlTextWriterEndDocument(writer);
257 result = xmlTextWriterClose(writer);
258
259 if (result != XML_IO_ENAMETOOLONG) {
260 fprintf(stderr, "xmlTextWriterClose reported wrong error %d\n",
261 result);
262 err = 1;
263 }
264
265 xmlFreeTextWriter(writer);
266 return err;
267 }
268 #endif
269
270 int
main(void)271 main(void) {
272 int err = 0;
273
274 err |= testStandaloneWithEncoding();
275 err |= testUnsupportedEncoding();
276 #ifdef LIBXML_SAX1_ENABLED
277 err |= testBalancedChunk();
278 #endif
279 #ifdef LIBXML_PUSH_ENABLED
280 err |= testHugePush();
281 err |= testHugeEncodedChunk();
282 #endif
283 #if defined(LIBXML_READER_ENABLED) && defined(LIBXML_XINCLUDE_ENABLED)
284 err |= testReaderXIncludeError();
285 #endif
286 #ifdef LIBXML_WRITER_ENABLED
287 err |= testWriterClose();
288 #endif
289
290 return err;
291 }
292
293