1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
3
4 runtest.c : run the Expat test suite
5 */
6
7 #ifdef HAVE_EXPAT_CONFIG_H
8 #include <expat_config.h>
9 #endif
10
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 #include "expat.h"
17 #include "chardata.h"
18 #include "minicheck.h"
19
20 #ifdef AMIGA_SHARED_LIB
21 #include <proto/expat.h>
22 #endif
23
24 #ifdef XML_LARGE_SIZE
25 #define XML_FMT_INT_MOD "ll"
26 #else
27 #define XML_FMT_INT_MOD "l"
28 #endif
29
30 static XML_Parser parser;
31
32
33 static void
basic_setup(void)34 basic_setup(void)
35 {
36 parser = XML_ParserCreate(NULL);
37 if (parser == NULL)
38 fail("Parser not created.");
39 }
40
41 static void
basic_teardown(void)42 basic_teardown(void)
43 {
44 if (parser != NULL)
45 XML_ParserFree(parser);
46 }
47
48 /* Generate a failure using the parser state to create an error message;
49 this should be used when the parser reports an error we weren't
50 expecting.
51 */
52 static void
_xml_failure(XML_Parser parser,const char * file,int line)53 _xml_failure(XML_Parser parser, const char *file, int line)
54 {
55 char buffer[1024];
56 sprintf(buffer,
57 "\n %s (line %" XML_FMT_INT_MOD "u, offset %"\
58 XML_FMT_INT_MOD "u)\n reported from %s, line %d",
59 XML_ErrorString(XML_GetErrorCode(parser)),
60 XML_GetCurrentLineNumber(parser),
61 XML_GetCurrentColumnNumber(parser),
62 file, line);
63 _fail_unless(0, file, line, buffer);
64 }
65
66 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
67
68 static void
_expect_failure(char * text,enum XML_Error errorCode,char * errorMessage,char * file,int lineno)69 _expect_failure(char *text, enum XML_Error errorCode, char *errorMessage,
70 char *file, int lineno)
71 {
72 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_OK)
73 /* Hackish use of _fail_unless() macro, but let's us report
74 the right filename and line number. */
75 _fail_unless(0, file, lineno, errorMessage);
76 if (XML_GetErrorCode(parser) != errorCode)
77 _xml_failure(parser, file, lineno);
78 }
79
80 #define expect_failure(text, errorCode, errorMessage) \
81 _expect_failure((text), (errorCode), (errorMessage), \
82 __FILE__, __LINE__)
83
84 /* Dummy handlers for when we need to set a handler to tickle a bug,
85 but it doesn't need to do anything.
86 */
87
88 static void XMLCALL
dummy_start_doctype_handler(void * userData,const XML_Char * doctypeName,const XML_Char * sysid,const XML_Char * pubid,int has_internal_subset)89 dummy_start_doctype_handler(void *userData,
90 const XML_Char *doctypeName,
91 const XML_Char *sysid,
92 const XML_Char *pubid,
93 int has_internal_subset)
94 {}
95
96 static void XMLCALL
dummy_end_doctype_handler(void * userData)97 dummy_end_doctype_handler(void *userData)
98 {}
99
100 static void XMLCALL
dummy_entity_decl_handler(void * userData,const XML_Char * entityName,int is_parameter_entity,const XML_Char * value,int value_length,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId,const XML_Char * notationName)101 dummy_entity_decl_handler(void *userData,
102 const XML_Char *entityName,
103 int is_parameter_entity,
104 const XML_Char *value,
105 int value_length,
106 const XML_Char *base,
107 const XML_Char *systemId,
108 const XML_Char *publicId,
109 const XML_Char *notationName)
110 {}
111
112 static void XMLCALL
dummy_notation_decl_handler(void * userData,const XML_Char * notationName,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)113 dummy_notation_decl_handler(void *userData,
114 const XML_Char *notationName,
115 const XML_Char *base,
116 const XML_Char *systemId,
117 const XML_Char *publicId)
118 {}
119
120 static void XMLCALL
dummy_element_decl_handler(void * userData,const XML_Char * name,XML_Content * model)121 dummy_element_decl_handler(void *userData,
122 const XML_Char *name,
123 XML_Content *model)
124 {}
125
126 static void XMLCALL
dummy_attlist_decl_handler(void * userData,const XML_Char * elname,const XML_Char * attname,const XML_Char * att_type,const XML_Char * dflt,int isrequired)127 dummy_attlist_decl_handler(void *userData,
128 const XML_Char *elname,
129 const XML_Char *attname,
130 const XML_Char *att_type,
131 const XML_Char *dflt,
132 int isrequired)
133 {}
134
135 static void XMLCALL
dummy_comment_handler(void * userData,const XML_Char * data)136 dummy_comment_handler(void *userData, const XML_Char *data)
137 {}
138
139 static void XMLCALL
dummy_pi_handler(void * userData,const XML_Char * target,const XML_Char * data)140 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data)
141 {}
142
143 static void XMLCALL
dummy_start_element(void * userData,const XML_Char * name,const XML_Char ** atts)144 dummy_start_element(void *userData,
145 const XML_Char *name, const XML_Char **atts)
146 {}
147
148
149 /*
150 * Character & encoding tests.
151 */
152
START_TEST(test_nul_byte)153 START_TEST(test_nul_byte)
154 {
155 char text[] = "<doc>\0</doc>";
156
157 /* test that a NUL byte (in US-ASCII data) is an error */
158 if (XML_Parse(parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_OK)
159 fail("Parser did not report error on NUL-byte.");
160 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
161 xml_failure(parser);
162 }
163 END_TEST
164
165
START_TEST(test_u0000_char)166 START_TEST(test_u0000_char)
167 {
168 /* test that a NUL byte (in US-ASCII data) is an error */
169 expect_failure("<doc>�</doc>",
170 XML_ERROR_BAD_CHAR_REF,
171 "Parser did not report error on NUL-byte.");
172 }
173 END_TEST
174
START_TEST(test_bom_utf8)175 START_TEST(test_bom_utf8)
176 {
177 /* This test is really just making sure we don't core on a UTF-8 BOM. */
178 char *text = "\357\273\277<e/>";
179
180 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
181 xml_failure(parser);
182 }
183 END_TEST
184
START_TEST(test_bom_utf16_be)185 START_TEST(test_bom_utf16_be)
186 {
187 char text[] = "\376\377\0<\0e\0/\0>";
188
189 if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
190 xml_failure(parser);
191 }
192 END_TEST
193
START_TEST(test_bom_utf16_le)194 START_TEST(test_bom_utf16_le)
195 {
196 char text[] = "\377\376<\0e\0/\0>\0";
197
198 if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
199 xml_failure(parser);
200 }
201 END_TEST
202
203 static void XMLCALL
accumulate_characters(void * userData,const XML_Char * s,int len)204 accumulate_characters(void *userData, const XML_Char *s, int len)
205 {
206 CharData_AppendXMLChars((CharData *)userData, s, len);
207 }
208
209 static void XMLCALL
accumulate_attribute(void * userData,const XML_Char * name,const XML_Char ** atts)210 accumulate_attribute(void *userData, const XML_Char *name,
211 const XML_Char **atts)
212 {
213 CharData *storage = (CharData *)userData;
214 if (storage->count < 0 && atts != NULL && atts[0] != NULL) {
215 /* "accumulate" the value of the first attribute we see */
216 CharData_AppendXMLChars(storage, atts[1], -1);
217 }
218 }
219
220
221 static void
_run_character_check(XML_Char * text,XML_Char * expected,const char * file,int line)222 _run_character_check(XML_Char *text, XML_Char *expected,
223 const char *file, int line)
224 {
225 CharData storage;
226
227 CharData_Init(&storage);
228 XML_SetUserData(parser, &storage);
229 XML_SetCharacterDataHandler(parser, accumulate_characters);
230 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
231 _xml_failure(parser, file, line);
232 CharData_CheckXMLChars(&storage, expected);
233 }
234
235 #define run_character_check(text, expected) \
236 _run_character_check(text, expected, __FILE__, __LINE__)
237
238 static void
_run_attribute_check(XML_Char * text,XML_Char * expected,const char * file,int line)239 _run_attribute_check(XML_Char *text, XML_Char *expected,
240 const char *file, int line)
241 {
242 CharData storage;
243
244 CharData_Init(&storage);
245 XML_SetUserData(parser, &storage);
246 XML_SetStartElementHandler(parser, accumulate_attribute);
247 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
248 _xml_failure(parser, file, line);
249 CharData_CheckXMLChars(&storage, expected);
250 }
251
252 #define run_attribute_check(text, expected) \
253 _run_attribute_check(text, expected, __FILE__, __LINE__)
254
255 /* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1)256 START_TEST(test_danish_latin1)
257 {
258 char *text =
259 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
260 "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
261 run_character_check(text,
262 "J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
263 }
264 END_TEST
265
266
267 /* Regression test for SF bug #514281. */
START_TEST(test_french_charref_hexidecimal)268 START_TEST(test_french_charref_hexidecimal)
269 {
270 char *text =
271 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
272 "<doc>éèàçêÈ</doc>";
273 run_character_check(text,
274 "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
275 }
276 END_TEST
277
START_TEST(test_french_charref_decimal)278 START_TEST(test_french_charref_decimal)
279 {
280 char *text =
281 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
282 "<doc>éèàçêÈ</doc>";
283 run_character_check(text,
284 "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
285 }
286 END_TEST
287
START_TEST(test_french_latin1)288 START_TEST(test_french_latin1)
289 {
290 char *text =
291 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
292 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
293 run_character_check(text,
294 "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
295 }
296 END_TEST
297
START_TEST(test_french_utf8)298 START_TEST(test_french_utf8)
299 {
300 char *text =
301 "<?xml version='1.0' encoding='utf-8'?>\n"
302 "<doc>\xC3\xA9</doc>";
303 run_character_check(text, "\xC3\xA9");
304 }
305 END_TEST
306
307 /* Regression test for SF bug #600479.
308 XXX There should be a test that exercises all legal XML Unicode
309 characters as PCDATA and attribute value content, and XML Name
310 characters as part of element and attribute names.
311 */
START_TEST(test_utf8_false_rejection)312 START_TEST(test_utf8_false_rejection)
313 {
314 char *text = "<doc>\xEF\xBA\xBF</doc>";
315 run_character_check(text, "\xEF\xBA\xBF");
316 }
317 END_TEST
318
319 /* Regression test for SF bug #477667.
320 This test assures that any 8-bit character followed by a 7-bit
321 character will not be mistakenly interpreted as a valid UTF-8
322 sequence.
323 */
START_TEST(test_illegal_utf8)324 START_TEST(test_illegal_utf8)
325 {
326 char text[100];
327 int i;
328
329 for (i = 128; i <= 255; ++i) {
330 sprintf(text, "<e>%ccd</e>", i);
331 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_OK) {
332 sprintf(text,
333 "expected token error for '%c' (ordinal %d) in UTF-8 text",
334 i, i);
335 fail(text);
336 }
337 else if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
338 xml_failure(parser);
339 /* Reset the parser since we use the same parser repeatedly. */
340 XML_ParserReset(parser, NULL);
341 }
342 }
343 END_TEST
344
START_TEST(test_utf16)345 START_TEST(test_utf16)
346 {
347 /* <?xml version="1.0" encoding="UTF-16"?>
348 <doc a='123'>some text</doc>
349 */
350 char text[] =
351 "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
352 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
353 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
354 "\000'\000?\000>\000\n"
355 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'"
356 "\000>\000s\000o\000m\000e\000 \000t\000e\000x\000t\000<\000/"
357 "\000d\000o\000c\000>";
358 if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
359 xml_failure(parser);
360 }
361 END_TEST
362
START_TEST(test_utf16_le_epilog_newline)363 START_TEST(test_utf16_le_epilog_newline)
364 {
365 int first_chunk_bytes = 17;
366 char text[] =
367 "\xFF\xFE" /* BOM */
368 "<\000e\000/\000>\000" /* document element */
369 "\r\000\n\000\r\000\n\000"; /* epilog */
370
371 if (first_chunk_bytes >= sizeof(text) - 1)
372 fail("bad value of first_chunk_bytes");
373 if ( XML_Parse(parser, text, first_chunk_bytes, XML_FALSE)
374 == XML_STATUS_ERROR)
375 xml_failure(parser);
376 else {
377 enum XML_Status rc;
378 rc = XML_Parse(parser, text + first_chunk_bytes,
379 sizeof(text) - first_chunk_bytes - 1, XML_TRUE);
380 if (rc == XML_STATUS_ERROR)
381 xml_failure(parser);
382 }
383 }
384 END_TEST
385
386 /* Regression test for SF bug #481609, #774028. */
START_TEST(test_latin1_umlauts)387 START_TEST(test_latin1_umlauts)
388 {
389 char *text =
390 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
391 "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n"
392 " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>";
393 char *utf8 =
394 "\xC3\xA4 \xC3\xB6 \xC3\xBC "
395 "\xC3\xA4 \xC3\xB6 \xC3\xBC "
396 "\xC3\xA4 \xC3\xB6 \xC3\xBC >";
397 run_character_check(text, utf8);
398 XML_ParserReset(parser, NULL);
399 run_attribute_check(text, utf8);
400 }
401 END_TEST
402
403 /* Regression test #1 for SF bug #653180. */
START_TEST(test_line_number_after_parse)404 START_TEST(test_line_number_after_parse)
405 {
406 char *text =
407 "<tag>\n"
408 "\n"
409 "\n</tag>";
410 XML_Size lineno;
411
412 if (XML_Parse(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
413 xml_failure(parser);
414 lineno = XML_GetCurrentLineNumber(parser);
415 if (lineno != 4) {
416 char buffer[100];
417 sprintf(buffer,
418 "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
419 fail(buffer);
420 }
421 }
422 END_TEST
423
424 /* Regression test #2 for SF bug #653180. */
START_TEST(test_column_number_after_parse)425 START_TEST(test_column_number_after_parse)
426 {
427 char *text = "<tag></tag>";
428 XML_Size colno;
429
430 if (XML_Parse(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
431 xml_failure(parser);
432 colno = XML_GetCurrentColumnNumber(parser);
433 if (colno != 11) {
434 char buffer[100];
435 sprintf(buffer,
436 "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
437 fail(buffer);
438 }
439 }
440 END_TEST
441
442 static void XMLCALL
start_element_event_handler2(void * userData,const XML_Char * name,const XML_Char ** attr)443 start_element_event_handler2(void *userData, const XML_Char *name,
444 const XML_Char **attr)
445 {
446 CharData *storage = (CharData *) userData;
447 char buffer[100];
448
449 sprintf(buffer,
450 "<%s> at col:%" XML_FMT_INT_MOD "u line:%"\
451 XML_FMT_INT_MOD "u\n", name,
452 XML_GetCurrentColumnNumber(parser),
453 XML_GetCurrentLineNumber(parser));
454 CharData_AppendString(storage, buffer);
455 }
456
457 static void XMLCALL
end_element_event_handler2(void * userData,const XML_Char * name)458 end_element_event_handler2(void *userData, const XML_Char *name)
459 {
460 CharData *storage = (CharData *) userData;
461 char buffer[100];
462
463 sprintf(buffer,
464 "</%s> at col:%" XML_FMT_INT_MOD "u line:%"\
465 XML_FMT_INT_MOD "u\n", name,
466 XML_GetCurrentColumnNumber(parser),
467 XML_GetCurrentLineNumber(parser));
468 CharData_AppendString(storage, buffer);
469 }
470
471 /* Regression test #3 for SF bug #653180. */
START_TEST(test_line_and_column_numbers_inside_handlers)472 START_TEST(test_line_and_column_numbers_inside_handlers)
473 {
474 char *text =
475 "<a>\n" /* Unix end-of-line */
476 " <b>\r\n" /* Windows end-of-line */
477 " <c/>\r" /* Mac OS end-of-line */
478 " </b>\n"
479 " <d>\n"
480 " <f/>\n"
481 " </d>\n"
482 "</a>";
483 char *expected =
484 "<a> at col:0 line:1\n"
485 "<b> at col:2 line:2\n"
486 "<c> at col:4 line:3\n"
487 "</c> at col:8 line:3\n"
488 "</b> at col:2 line:4\n"
489 "<d> at col:2 line:5\n"
490 "<f> at col:4 line:6\n"
491 "</f> at col:8 line:6\n"
492 "</d> at col:2 line:7\n"
493 "</a> at col:0 line:8\n";
494 CharData storage;
495
496 CharData_Init(&storage);
497 XML_SetUserData(parser, &storage);
498 XML_SetStartElementHandler(parser, start_element_event_handler2);
499 XML_SetEndElementHandler(parser, end_element_event_handler2);
500 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
501 xml_failure(parser);
502
503 CharData_CheckString(&storage, expected);
504 }
505 END_TEST
506
507 /* Regression test #4 for SF bug #653180. */
START_TEST(test_line_number_after_error)508 START_TEST(test_line_number_after_error)
509 {
510 char *text =
511 "<a>\n"
512 " <b>\n"
513 " </a>"; /* missing </b> */
514 XML_Size lineno;
515 if (XML_Parse(parser, text, strlen(text), XML_FALSE) != XML_STATUS_ERROR)
516 fail("Expected a parse error");
517
518 lineno = XML_GetCurrentLineNumber(parser);
519 if (lineno != 3) {
520 char buffer[100];
521 sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
522 fail(buffer);
523 }
524 }
525 END_TEST
526
527 /* Regression test #5 for SF bug #653180. */
START_TEST(test_column_number_after_error)528 START_TEST(test_column_number_after_error)
529 {
530 char *text =
531 "<a>\n"
532 " <b>\n"
533 " </a>"; /* missing </b> */
534 XML_Size colno;
535 if (XML_Parse(parser, text, strlen(text), XML_FALSE) != XML_STATUS_ERROR)
536 fail("Expected a parse error");
537
538 colno = XML_GetCurrentColumnNumber(parser);
539 if (colno != 4) {
540 char buffer[100];
541 sprintf(buffer,
542 "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
543 fail(buffer);
544 }
545 }
546 END_TEST
547
548 /* Regression test for SF bug #478332. */
START_TEST(test_really_long_lines)549 START_TEST(test_really_long_lines)
550 {
551 /* This parses an input line longer than INIT_DATA_BUF_SIZE
552 characters long (defined to be 1024 in xmlparse.c). We take a
553 really cheesy approach to building the input buffer, because
554 this avoids writing bugs in buffer-filling code.
555 */
556 char *text =
557 "<e>"
558 /* 64 chars */
559 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
560 /* until we have at least 1024 characters on the line: */
561 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
562 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
563 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
564 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
565 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
566 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
567 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
568 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
569 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
570 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
571 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
572 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
573 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
574 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
575 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
576 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
577 "</e>";
578 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
579 xml_failure(parser);
580 }
581 END_TEST
582
583
584 /*
585 * Element event tests.
586 */
587
588 static void XMLCALL
end_element_event_handler(void * userData,const XML_Char * name)589 end_element_event_handler(void *userData, const XML_Char *name)
590 {
591 CharData *storage = (CharData *) userData;
592 CharData_AppendString(storage, "/");
593 CharData_AppendXMLChars(storage, name, -1);
594 }
595
START_TEST(test_end_element_events)596 START_TEST(test_end_element_events)
597 {
598 char *text = "<a><b><c/></b><d><f/></d></a>";
599 char *expected = "/c/b/f/d/a";
600 CharData storage;
601
602 CharData_Init(&storage);
603 XML_SetUserData(parser, &storage);
604 XML_SetEndElementHandler(parser, end_element_event_handler);
605 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
606 xml_failure(parser);
607 CharData_CheckString(&storage, expected);
608 }
609 END_TEST
610
611
612 /*
613 * Attribute tests.
614 */
615
616 /* Helpers used by the following test; this checks any "attr" and "refs"
617 attributes to make sure whitespace has been normalized.
618
619 Return true if whitespace has been normalized in a string, using
620 the rules for attribute value normalization. The 'is_cdata' flag
621 is needed since CDATA attributes don't need to have multiple
622 whitespace characters collapsed to a single space, while other
623 attribute data types do. (Section 3.3.3 of the recommendation.)
624 */
625 static int
is_whitespace_normalized(const XML_Char * s,int is_cdata)626 is_whitespace_normalized(const XML_Char *s, int is_cdata)
627 {
628 int blanks = 0;
629 int at_start = 1;
630 while (*s) {
631 if (*s == ' ')
632 ++blanks;
633 else if (*s == '\t' || *s == '\n' || *s == '\r')
634 return 0;
635 else {
636 if (at_start) {
637 at_start = 0;
638 if (blanks && !is_cdata)
639 /* illegal leading blanks */
640 return 0;
641 }
642 else if (blanks > 1 && !is_cdata)
643 return 0;
644 blanks = 0;
645 }
646 ++s;
647 }
648 if (blanks && !is_cdata)
649 return 0;
650 return 1;
651 }
652
653 /* Check the attribute whitespace checker: */
654 static void
testhelper_is_whitespace_normalized(void)655 testhelper_is_whitespace_normalized(void)
656 {
657 assert(is_whitespace_normalized("abc", 0));
658 assert(is_whitespace_normalized("abc", 1));
659 assert(is_whitespace_normalized("abc def ghi", 0));
660 assert(is_whitespace_normalized("abc def ghi", 1));
661 assert(!is_whitespace_normalized(" abc def ghi", 0));
662 assert(is_whitespace_normalized(" abc def ghi", 1));
663 assert(!is_whitespace_normalized("abc def ghi", 0));
664 assert(is_whitespace_normalized("abc def ghi", 1));
665 assert(!is_whitespace_normalized("abc def ghi ", 0));
666 assert(is_whitespace_normalized("abc def ghi ", 1));
667 assert(!is_whitespace_normalized(" ", 0));
668 assert(is_whitespace_normalized(" ", 1));
669 assert(!is_whitespace_normalized("\t", 0));
670 assert(!is_whitespace_normalized("\t", 1));
671 assert(!is_whitespace_normalized("\n", 0));
672 assert(!is_whitespace_normalized("\n", 1));
673 assert(!is_whitespace_normalized("\r", 0));
674 assert(!is_whitespace_normalized("\r", 1));
675 assert(!is_whitespace_normalized("abc\t def", 1));
676 }
677
678 static void XMLCALL
check_attr_contains_normalized_whitespace(void * userData,const XML_Char * name,const XML_Char ** atts)679 check_attr_contains_normalized_whitespace(void *userData,
680 const XML_Char *name,
681 const XML_Char **atts)
682 {
683 int i;
684 for (i = 0; atts[i] != NULL; i += 2) {
685 const XML_Char *attrname = atts[i];
686 const XML_Char *value = atts[i + 1];
687 if (strcmp("attr", attrname) == 0
688 || strcmp("ents", attrname) == 0
689 || strcmp("refs", attrname) == 0) {
690 if (!is_whitespace_normalized(value, 0)) {
691 char buffer[256];
692 sprintf(buffer, "attribute value not normalized: %s='%s'",
693 attrname, value);
694 fail(buffer);
695 }
696 }
697 }
698 }
699
START_TEST(test_attr_whitespace_normalization)700 START_TEST(test_attr_whitespace_normalization)
701 {
702 char *text =
703 "<!DOCTYPE doc [\n"
704 " <!ATTLIST doc\n"
705 " attr NMTOKENS #REQUIRED\n"
706 " ents ENTITIES #REQUIRED\n"
707 " refs IDREFS #REQUIRED>\n"
708 "]>\n"
709 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n"
710 " ents=' ent-1 \t\r\n"
711 " ent-2 ' >\n"
712 " <e id='id-1'/>\n"
713 " <e id='id-2'/>\n"
714 "</doc>";
715
716 XML_SetStartElementHandler(parser,
717 check_attr_contains_normalized_whitespace);
718 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
719 xml_failure(parser);
720 }
721 END_TEST
722
723
724 /*
725 * XML declaration tests.
726 */
727
START_TEST(test_xmldecl_misplaced)728 START_TEST(test_xmldecl_misplaced)
729 {
730 expect_failure("\n"
731 "<?xml version='1.0'?>\n"
732 "<a/>",
733 XML_ERROR_MISPLACED_XML_PI,
734 "failed to report misplaced XML declaration");
735 }
736 END_TEST
737
738 /* Regression test for SF bug #584832. */
739 static int XMLCALL
UnknownEncodingHandler(void * data,const XML_Char * encoding,XML_Encoding * info)740 UnknownEncodingHandler(void *data,const XML_Char *encoding,XML_Encoding *info)
741 {
742 if (strcmp(encoding,"unsupported-encoding") == 0) {
743 int i;
744 for (i = 0; i < 256; ++i)
745 info->map[i] = i;
746 info->data = NULL;
747 info->convert = NULL;
748 info->release = NULL;
749 return XML_STATUS_OK;
750 }
751 return XML_STATUS_ERROR;
752 }
753
START_TEST(test_unknown_encoding_internal_entity)754 START_TEST(test_unknown_encoding_internal_entity)
755 {
756 char *text =
757 "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
758 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
759 "<test a='&foo;'/>";
760
761 XML_SetUnknownEncodingHandler(parser, UnknownEncodingHandler, NULL);
762 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
763 xml_failure(parser);
764 }
765 END_TEST
766
767 /* Regression test for SF bug #620106. */
768 static int XMLCALL
external_entity_loader_set_encoding(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)769 external_entity_loader_set_encoding(XML_Parser parser,
770 const XML_Char *context,
771 const XML_Char *base,
772 const XML_Char *systemId,
773 const XML_Char *publicId)
774 {
775 /* This text says it's an unsupported encoding, but it's really
776 UTF-8, which we tell Expat using XML_SetEncoding().
777 */
778 char *text =
779 "<?xml encoding='iso-8859-3'?>"
780 "\xC3\xA9";
781 XML_Parser extparser;
782
783 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
784 if (extparser == NULL)
785 fail("Could not create external entity parser.");
786 if (!XML_SetEncoding(extparser, "utf-8"))
787 fail("XML_SetEncoding() ignored for external entity");
788 if ( XML_Parse(extparser, text, strlen(text), XML_TRUE)
789 == XML_STATUS_ERROR) {
790 xml_failure(parser);
791 return 0;
792 }
793 return 1;
794 }
795
START_TEST(test_ext_entity_set_encoding)796 START_TEST(test_ext_entity_set_encoding)
797 {
798 char *text =
799 "<!DOCTYPE doc [\n"
800 " <!ENTITY en SYSTEM 'http://xml.libexpat.org/dummy.ent'>\n"
801 "]>\n"
802 "<doc>&en;</doc>";
803
804 XML_SetExternalEntityRefHandler(parser,
805 external_entity_loader_set_encoding);
806 run_character_check(text, "\xC3\xA9");
807 }
808 END_TEST
809
810 /* Test that no error is reported for unknown entities if we don't
811 read an external subset. This was fixed in Expat 1.95.5.
812 */
START_TEST(test_wfc_undeclared_entity_unread_external_subset)813 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
814 char *text =
815 "<!DOCTYPE doc SYSTEM 'foo'>\n"
816 "<doc>&entity;</doc>";
817
818 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
819 xml_failure(parser);
820 }
821 END_TEST
822
823 /* Test that an error is reported for unknown entities if we don't
824 have an external subset.
825 */
START_TEST(test_wfc_undeclared_entity_no_external_subset)826 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
827 expect_failure("<doc>&entity;</doc>",
828 XML_ERROR_UNDEFINED_ENTITY,
829 "Parser did not report undefined entity w/out a DTD.");
830 }
831 END_TEST
832
833 /* Test that an error is reported for unknown entities if we don't
834 read an external subset, but have been declared standalone.
835 */
START_TEST(test_wfc_undeclared_entity_standalone)836 START_TEST(test_wfc_undeclared_entity_standalone) {
837 char *text =
838 "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
839 "<!DOCTYPE doc SYSTEM 'foo'>\n"
840 "<doc>&entity;</doc>";
841
842 expect_failure(text,
843 XML_ERROR_UNDEFINED_ENTITY,
844 "Parser did not report undefined entity (standalone).");
845 }
846 END_TEST
847
848 static int XMLCALL
external_entity_loader(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)849 external_entity_loader(XML_Parser parser,
850 const XML_Char *context,
851 const XML_Char *base,
852 const XML_Char *systemId,
853 const XML_Char *publicId)
854 {
855 char *text = (char *)XML_GetUserData(parser);
856 XML_Parser extparser;
857
858 extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
859 if (extparser == NULL)
860 fail("Could not create external entity parser.");
861 if ( XML_Parse(extparser, text, strlen(text), XML_TRUE)
862 == XML_STATUS_ERROR) {
863 xml_failure(parser);
864 return XML_STATUS_ERROR;
865 }
866 return XML_STATUS_OK;
867 }
868
869 /* Test that an error is reported for unknown entities if we have read
870 an external subset, and standalone is true.
871 */
START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone)872 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
873 char *text =
874 "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
875 "<!DOCTYPE doc SYSTEM 'foo'>\n"
876 "<doc>&entity;</doc>";
877 char *foo_text =
878 "<!ELEMENT doc (#PCDATA)*>";
879
880 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
881 XML_SetUserData(parser, foo_text);
882 XML_SetExternalEntityRefHandler(parser, external_entity_loader);
883 expect_failure(text,
884 XML_ERROR_UNDEFINED_ENTITY,
885 "Parser did not report undefined entity (external DTD).");
886 }
887 END_TEST
888
889 /* Test that no error is reported for unknown entities if we have read
890 an external subset, and standalone is false.
891 */
START_TEST(test_wfc_undeclared_entity_with_external_subset)892 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
893 char *text =
894 "<?xml version='1.0' encoding='us-ascii'?>\n"
895 "<!DOCTYPE doc SYSTEM 'foo'>\n"
896 "<doc>&entity;</doc>";
897 char *foo_text =
898 "<!ELEMENT doc (#PCDATA)*>";
899
900 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
901 XML_SetUserData(parser, foo_text);
902 XML_SetExternalEntityRefHandler(parser, external_entity_loader);
903 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
904 xml_failure(parser);
905 }
906 END_TEST
907
START_TEST(test_wfc_no_recursive_entity_refs)908 START_TEST(test_wfc_no_recursive_entity_refs)
909 {
910 char *text =
911 "<!DOCTYPE doc [\n"
912 " <!ENTITY entity '&entity;'>\n"
913 "]>\n"
914 "<doc>&entity;</doc>";
915
916 expect_failure(text,
917 XML_ERROR_RECURSIVE_ENTITY_REF,
918 "Parser did not report recursive entity reference.");
919 }
920 END_TEST
921
922 /* Regression test for SF bug #483514. */
START_TEST(test_dtd_default_handling)923 START_TEST(test_dtd_default_handling)
924 {
925 char *text =
926 "<!DOCTYPE doc [\n"
927 "<!ENTITY e SYSTEM 'http://xml.libexpat.org/e'>\n"
928 "<!NOTATION n SYSTEM 'http://xml.libexpat.org/n'>\n"
929 "<!ELEMENT doc EMPTY>\n"
930 "<!ATTLIST doc a CDATA #IMPLIED>\n"
931 "<?pi in dtd?>\n"
932 "<!--comment in dtd-->\n"
933 "]><doc/>";
934
935 XML_SetDefaultHandler(parser, accumulate_characters);
936 XML_SetDoctypeDeclHandler(parser,
937 dummy_start_doctype_handler,
938 dummy_end_doctype_handler);
939 XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
940 XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
941 XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
942 XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
943 XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
944 XML_SetCommentHandler(parser, dummy_comment_handler);
945 run_character_check(text, "\n\n\n\n\n\n\n<doc/>");
946 }
947 END_TEST
948
949 /* See related SF bug #673791.
950 When namespace processing is enabled, setting the namespace URI for
951 a prefix is not allowed; this test ensures that it *is* allowed
952 when namespace processing is not enabled.
953 (See Namespaces in XML, section 2.)
954 */
START_TEST(test_empty_ns_without_namespaces)955 START_TEST(test_empty_ns_without_namespaces)
956 {
957 char *text =
958 "<doc xmlns:prefix='http://www.example.com/'>\n"
959 " <e xmlns:prefix=''/>\n"
960 "</doc>";
961
962 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
963 xml_failure(parser);
964 }
965 END_TEST
966
967 /* Regression test for SF bug #824420.
968 Checks that an xmlns:prefix attribute set in an attribute's default
969 value isn't misinterpreted.
970 */
START_TEST(test_ns_in_attribute_default_without_namespaces)971 START_TEST(test_ns_in_attribute_default_without_namespaces)
972 {
973 char *text =
974 "<!DOCTYPE e:element [\n"
975 " <!ATTLIST e:element\n"
976 " xmlns:e CDATA 'http://example.com/'>\n"
977 " ]>\n"
978 "<e:element/>";
979
980 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
981 xml_failure(parser);
982 }
983 END_TEST
984
985
986 /*
987 * Namespaces tests.
988 */
989
990 static void
namespace_setup(void)991 namespace_setup(void)
992 {
993 parser = XML_ParserCreateNS(NULL, ' ');
994 if (parser == NULL)
995 fail("Parser not created.");
996 }
997
998 static void
namespace_teardown(void)999 namespace_teardown(void)
1000 {
1001 basic_teardown();
1002 }
1003
1004 /* Check that an element name and attribute name match the expected values.
1005 The expected values are passed as an array reference of string pointers
1006 provided as the userData argument; the first is the expected
1007 element name, and the second is the expected attribute name.
1008 */
1009 static void XMLCALL
triplet_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)1010 triplet_start_checker(void *userData, const XML_Char *name,
1011 const XML_Char **atts)
1012 {
1013 char **elemstr = (char **)userData;
1014 char buffer[1024];
1015 if (strcmp(elemstr[0], name) != 0) {
1016 sprintf(buffer, "unexpected start string: '%s'", name);
1017 fail(buffer);
1018 }
1019 if (strcmp(elemstr[1], atts[0]) != 0) {
1020 sprintf(buffer, "unexpected attribute string: '%s'", atts[0]);
1021 fail(buffer);
1022 }
1023 }
1024
1025 /* Check that the element name passed to the end-element handler matches
1026 the expected value. The expected value is passed as the first element
1027 in an array of strings passed as the userData argument.
1028 */
1029 static void XMLCALL
triplet_end_checker(void * userData,const XML_Char * name)1030 triplet_end_checker(void *userData, const XML_Char *name)
1031 {
1032 char **elemstr = (char **)userData;
1033 if (strcmp(elemstr[0], name) != 0) {
1034 char buffer[1024];
1035 sprintf(buffer, "unexpected end string: '%s'", name);
1036 fail(buffer);
1037 }
1038 }
1039
START_TEST(test_return_ns_triplet)1040 START_TEST(test_return_ns_triplet)
1041 {
1042 char *text =
1043 "<foo:e xmlns:foo='http://expat.sf.net/' bar:a='12'\n"
1044 " xmlns:bar='http://expat.sf.net/'></foo:e>";
1045 char *elemstr[] = {
1046 "http://expat.sf.net/ e foo",
1047 "http://expat.sf.net/ a bar"
1048 };
1049 XML_SetReturnNSTriplet(parser, XML_TRUE);
1050 XML_SetUserData(parser, elemstr);
1051 XML_SetElementHandler(parser, triplet_start_checker, triplet_end_checker);
1052 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1053 xml_failure(parser);
1054 }
1055 END_TEST
1056
1057 static void XMLCALL
overwrite_start_checker(void * userData,const XML_Char * name,const XML_Char ** atts)1058 overwrite_start_checker(void *userData, const XML_Char *name,
1059 const XML_Char **atts)
1060 {
1061 CharData *storage = (CharData *) userData;
1062 CharData_AppendString(storage, "start ");
1063 CharData_AppendXMLChars(storage, name, -1);
1064 while (*atts != NULL) {
1065 CharData_AppendString(storage, "\nattribute ");
1066 CharData_AppendXMLChars(storage, *atts, -1);
1067 atts += 2;
1068 }
1069 CharData_AppendString(storage, "\n");
1070 }
1071
1072 static void XMLCALL
overwrite_end_checker(void * userData,const XML_Char * name)1073 overwrite_end_checker(void *userData, const XML_Char *name)
1074 {
1075 CharData *storage = (CharData *) userData;
1076 CharData_AppendString(storage, "end ");
1077 CharData_AppendXMLChars(storage, name, -1);
1078 CharData_AppendString(storage, "\n");
1079 }
1080
1081 static void
run_ns_tagname_overwrite_test(char * text,char * result)1082 run_ns_tagname_overwrite_test(char *text, char *result)
1083 {
1084 CharData storage;
1085 CharData_Init(&storage);
1086 XML_SetUserData(parser, &storage);
1087 XML_SetElementHandler(parser,
1088 overwrite_start_checker, overwrite_end_checker);
1089 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1090 xml_failure(parser);
1091 CharData_CheckString(&storage, result);
1092 }
1093
1094 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite)1095 START_TEST(test_ns_tagname_overwrite)
1096 {
1097 char *text =
1098 "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
1099 " <n:f n:attr='foo'/>\n"
1100 " <n:g n:attr2='bar'/>\n"
1101 "</n:e>";
1102 char *result =
1103 "start http://xml.libexpat.org/ e\n"
1104 "start http://xml.libexpat.org/ f\n"
1105 "attribute http://xml.libexpat.org/ attr\n"
1106 "end http://xml.libexpat.org/ f\n"
1107 "start http://xml.libexpat.org/ g\n"
1108 "attribute http://xml.libexpat.org/ attr2\n"
1109 "end http://xml.libexpat.org/ g\n"
1110 "end http://xml.libexpat.org/ e\n";
1111 run_ns_tagname_overwrite_test(text, result);
1112 }
1113 END_TEST
1114
1115 /* Regression test for SF bug #566334. */
START_TEST(test_ns_tagname_overwrite_triplet)1116 START_TEST(test_ns_tagname_overwrite_triplet)
1117 {
1118 char *text =
1119 "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
1120 " <n:f n:attr='foo'/>\n"
1121 " <n:g n:attr2='bar'/>\n"
1122 "</n:e>";
1123 char *result =
1124 "start http://xml.libexpat.org/ e n\n"
1125 "start http://xml.libexpat.org/ f n\n"
1126 "attribute http://xml.libexpat.org/ attr n\n"
1127 "end http://xml.libexpat.org/ f n\n"
1128 "start http://xml.libexpat.org/ g n\n"
1129 "attribute http://xml.libexpat.org/ attr2 n\n"
1130 "end http://xml.libexpat.org/ g n\n"
1131 "end http://xml.libexpat.org/ e n\n";
1132 XML_SetReturnNSTriplet(parser, XML_TRUE);
1133 run_ns_tagname_overwrite_test(text, result);
1134 }
1135 END_TEST
1136
1137
1138 /* Regression test for SF bug #620343. */
1139 static void XMLCALL
start_element_fail(void * userData,const XML_Char * name,const XML_Char ** atts)1140 start_element_fail(void *userData,
1141 const XML_Char *name, const XML_Char **atts)
1142 {
1143 /* We should never get here. */
1144 fail("should never reach start_element_fail()");
1145 }
1146
1147 static void XMLCALL
start_ns_clearing_start_element(void * userData,const XML_Char * prefix,const XML_Char * uri)1148 start_ns_clearing_start_element(void *userData,
1149 const XML_Char *prefix,
1150 const XML_Char *uri)
1151 {
1152 XML_SetStartElementHandler((XML_Parser) userData, NULL);
1153 }
1154
START_TEST(test_start_ns_clears_start_element)1155 START_TEST(test_start_ns_clears_start_element)
1156 {
1157 /* This needs to use separate start/end tags; using the empty tag
1158 syntax doesn't cause the problematic path through Expat to be
1159 taken.
1160 */
1161 char *text = "<e xmlns='http://xml.libexpat.org/'></e>";
1162
1163 XML_SetStartElementHandler(parser, start_element_fail);
1164 XML_SetStartNamespaceDeclHandler(parser, start_ns_clearing_start_element);
1165 XML_UseParserAsHandlerArg(parser);
1166 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1167 xml_failure(parser);
1168 }
1169 END_TEST
1170
1171 /* Regression test for SF bug #616863. */
1172 static int XMLCALL
external_entity_handler(XML_Parser parser,const XML_Char * context,const XML_Char * base,const XML_Char * systemId,const XML_Char * publicId)1173 external_entity_handler(XML_Parser parser,
1174 const XML_Char *context,
1175 const XML_Char *base,
1176 const XML_Char *systemId,
1177 const XML_Char *publicId)
1178 {
1179 int callno = 1 + (int)XML_GetUserData(parser);
1180 char *text;
1181 XML_Parser p2;
1182
1183 if (callno == 1)
1184 text = ("<!ELEMENT doc (e+)>\n"
1185 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1186 "<!ELEMENT e EMPTY>\n");
1187 else
1188 text = ("<?xml version='1.0' encoding='us-ascii'?>"
1189 "<e/>");
1190
1191 XML_SetUserData(parser, (void *) callno);
1192 p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
1193 if (XML_Parse(p2, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) {
1194 xml_failure(p2);
1195 return 0;
1196 }
1197 XML_ParserFree(p2);
1198 return 1;
1199 }
1200
START_TEST(test_default_ns_from_ext_subset_and_ext_ge)1201 START_TEST(test_default_ns_from_ext_subset_and_ext_ge)
1202 {
1203 char *text =
1204 "<?xml version='1.0'?>\n"
1205 "<!DOCTYPE doc SYSTEM 'http://xml.libexpat.org/doc.dtd' [\n"
1206 " <!ENTITY en SYSTEM 'http://xml.libexpat.org/entity.ent'>\n"
1207 "]>\n"
1208 "<doc xmlns='http://xml.libexpat.org/ns1'>\n"
1209 "&en;\n"
1210 "</doc>";
1211
1212 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1213 XML_SetExternalEntityRefHandler(parser, external_entity_handler);
1214 /* We actually need to set this handler to tickle this bug. */
1215 XML_SetStartElementHandler(parser, dummy_start_element);
1216 XML_SetUserData(parser, NULL);
1217 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1218 xml_failure(parser);
1219 }
1220 END_TEST
1221
1222 /* Regression test #1 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_1)1223 START_TEST(test_ns_prefix_with_empty_uri_1)
1224 {
1225 char *text =
1226 "<doc xmlns:prefix='http://xml.libexpat.org/'>\n"
1227 " <e xmlns:prefix=''/>\n"
1228 "</doc>";
1229
1230 expect_failure(text,
1231 XML_ERROR_UNDECLARING_PREFIX,
1232 "Did not report re-setting namespace"
1233 " URI with prefix to ''.");
1234 }
1235 END_TEST
1236
1237 /* Regression test #2 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_2)1238 START_TEST(test_ns_prefix_with_empty_uri_2)
1239 {
1240 char *text =
1241 "<?xml version='1.0'?>\n"
1242 "<docelem xmlns:pre=''/>";
1243
1244 expect_failure(text,
1245 XML_ERROR_UNDECLARING_PREFIX,
1246 "Did not report setting namespace URI with prefix to ''.");
1247 }
1248 END_TEST
1249
1250 /* Regression test #3 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_3)1251 START_TEST(test_ns_prefix_with_empty_uri_3)
1252 {
1253 char *text =
1254 "<!DOCTYPE doc [\n"
1255 " <!ELEMENT doc EMPTY>\n"
1256 " <!ATTLIST doc\n"
1257 " xmlns:prefix CDATA ''>\n"
1258 "]>\n"
1259 "<doc/>";
1260
1261 expect_failure(text,
1262 XML_ERROR_UNDECLARING_PREFIX,
1263 "Didn't report attr default setting NS w/ prefix to ''.");
1264 }
1265 END_TEST
1266
1267 /* Regression test #4 for SF bug #673791. */
START_TEST(test_ns_prefix_with_empty_uri_4)1268 START_TEST(test_ns_prefix_with_empty_uri_4)
1269 {
1270 char *text =
1271 "<!DOCTYPE doc [\n"
1272 " <!ELEMENT prefix:doc EMPTY>\n"
1273 " <!ATTLIST prefix:doc\n"
1274 " xmlns:prefix CDATA 'http://xml.libexpat.org/'>\n"
1275 "]>\n"
1276 "<prefix:doc/>";
1277 /* Packaged info expected by the end element handler;
1278 the weird structuring lets us re-use the triplet_end_checker()
1279 function also used for another test. */
1280 char *elemstr[] = {
1281 "http://xml.libexpat.org/ doc prefix"
1282 };
1283 XML_SetReturnNSTriplet(parser, XML_TRUE);
1284 XML_SetUserData(parser, elemstr);
1285 XML_SetEndElementHandler(parser, triplet_end_checker);
1286 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1287 xml_failure(parser);
1288 }
1289 END_TEST
1290
START_TEST(test_ns_default_with_empty_uri)1291 START_TEST(test_ns_default_with_empty_uri)
1292 {
1293 char *text =
1294 "<doc xmlns='http://xml.libexpat.org/'>\n"
1295 " <e xmlns=''/>\n"
1296 "</doc>";
1297 if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1298 xml_failure(parser);
1299 }
1300 END_TEST
1301
1302 /* Regression test for SF bug #692964: two prefixes for one namespace. */
START_TEST(test_ns_duplicate_attrs_diff_prefixes)1303 START_TEST(test_ns_duplicate_attrs_diff_prefixes)
1304 {
1305 char *text =
1306 "<doc xmlns:a='http://xml.libexpat.org/a'\n"
1307 " xmlns:b='http://xml.libexpat.org/a'\n"
1308 " a:a='v' b:a='v' />";
1309 expect_failure(text,
1310 XML_ERROR_DUPLICATE_ATTRIBUTE,
1311 "did not report multiple attributes with same URI+name");
1312 }
1313 END_TEST
1314
1315 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_attribute)1316 START_TEST(test_ns_unbound_prefix_on_attribute)
1317 {
1318 char *text = "<doc a:attr=''/>";
1319 expect_failure(text,
1320 XML_ERROR_UNBOUND_PREFIX,
1321 "did not report unbound prefix on attribute");
1322 }
1323 END_TEST
1324
1325 /* Regression test for SF bug #695401: unbound prefix. */
START_TEST(test_ns_unbound_prefix_on_element)1326 START_TEST(test_ns_unbound_prefix_on_element)
1327 {
1328 char *text = "<a:doc/>";
1329 expect_failure(text,
1330 XML_ERROR_UNBOUND_PREFIX,
1331 "did not report unbound prefix on element");
1332 }
1333 END_TEST
1334
1335 static Suite *
make_suite(void)1336 make_suite(void)
1337 {
1338 Suite *s = suite_create("basic");
1339 TCase *tc_basic = tcase_create("basic tests");
1340 TCase *tc_namespace = tcase_create("XML namespaces");
1341
1342 suite_add_tcase(s, tc_basic);
1343 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
1344 tcase_add_test(tc_basic, test_nul_byte);
1345 tcase_add_test(tc_basic, test_u0000_char);
1346 tcase_add_test(tc_basic, test_bom_utf8);
1347 tcase_add_test(tc_basic, test_bom_utf16_be);
1348 tcase_add_test(tc_basic, test_bom_utf16_le);
1349 tcase_add_test(tc_basic, test_illegal_utf8);
1350 tcase_add_test(tc_basic, test_utf16);
1351 tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
1352 tcase_add_test(tc_basic, test_latin1_umlauts);
1353 /* Regression test for SF bug #491986. */
1354 tcase_add_test(tc_basic, test_danish_latin1);
1355 /* Regression test for SF bug #514281. */
1356 tcase_add_test(tc_basic, test_french_charref_hexidecimal);
1357 tcase_add_test(tc_basic, test_french_charref_decimal);
1358 tcase_add_test(tc_basic, test_french_latin1);
1359 tcase_add_test(tc_basic, test_french_utf8);
1360 tcase_add_test(tc_basic, test_utf8_false_rejection);
1361 tcase_add_test(tc_basic, test_line_number_after_parse);
1362 tcase_add_test(tc_basic, test_column_number_after_parse);
1363 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
1364 tcase_add_test(tc_basic, test_line_number_after_error);
1365 tcase_add_test(tc_basic, test_column_number_after_error);
1366 tcase_add_test(tc_basic, test_really_long_lines);
1367 tcase_add_test(tc_basic, test_end_element_events);
1368 tcase_add_test(tc_basic, test_attr_whitespace_normalization);
1369 tcase_add_test(tc_basic, test_xmldecl_misplaced);
1370 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
1371 tcase_add_test(tc_basic,
1372 test_wfc_undeclared_entity_unread_external_subset);
1373 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
1374 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
1375 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
1376 tcase_add_test(tc_basic,
1377 test_wfc_undeclared_entity_with_external_subset_standalone);
1378 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
1379 tcase_add_test(tc_basic, test_ext_entity_set_encoding);
1380 tcase_add_test(tc_basic, test_dtd_default_handling);
1381 tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
1382 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
1383
1384 suite_add_tcase(s, tc_namespace);
1385 tcase_add_checked_fixture(tc_namespace,
1386 namespace_setup, namespace_teardown);
1387 tcase_add_test(tc_namespace, test_return_ns_triplet);
1388 tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
1389 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
1390 tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
1391 tcase_add_test(tc_namespace, test_default_ns_from_ext_subset_and_ext_ge);
1392 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
1393 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
1394 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
1395 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
1396 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
1397 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
1398 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
1399 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
1400
1401 return s;
1402 }
1403
1404
1405 #ifdef AMIGA_SHARED_LIB
1406 int
amiga_main(int argc,char * argv[])1407 amiga_main(int argc, char *argv[])
1408 #else
1409 int
1410 main(int argc, char *argv[])
1411 #endif
1412 {
1413 int i, nf;
1414 int forking = 0, forking_set = 0;
1415 int verbosity = CK_NORMAL;
1416 Suite *s = make_suite();
1417 SRunner *sr = srunner_create(s);
1418
1419 /* run the tests for internal helper functions */
1420 testhelper_is_whitespace_normalized();
1421
1422 for (i = 1; i < argc; ++i) {
1423 char *opt = argv[i];
1424 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
1425 verbosity = CK_VERBOSE;
1426 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
1427 verbosity = CK_SILENT;
1428 else if (strcmp(opt, "-f") == 0 || strcmp(opt, "--fork") == 0) {
1429 forking = 1;
1430 forking_set = 1;
1431 }
1432 else if (strcmp(opt, "-n") == 0 || strcmp(opt, "--no-fork") == 0) {
1433 forking = 0;
1434 forking_set = 1;
1435 }
1436 else {
1437 fprintf(stderr, "runtests: unknown option '%s'\n", opt);
1438 return 2;
1439 }
1440 }
1441 if (forking_set)
1442 srunner_set_fork_status(sr, forking ? CK_FORK : CK_NOFORK);
1443 if (verbosity != CK_SILENT)
1444 printf("Expat version: %s\n", XML_ExpatVersion());
1445 srunner_run_all(sr, verbosity);
1446 nf = srunner_ntests_failed(sr);
1447 srunner_free(sr);
1448
1449 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1450 }
1451