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