• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>&#0;</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>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</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>&#233;&#232;&#224;&#231;&#234;&#200;</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 &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; >'\n"
392         "  >\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#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 '&#38;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