1 /* Run the Expat test suite 2 __ __ _ 3 ___\ \/ /_ __ __ _| |_ 4 / _ \\ /| '_ \ / _` | __| 5 | __// \| |_) | (_| | |_ 6 \___/_/\_\ .__/ \__,_|\__| 7 |_| XML parser 8 9 Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> 10 Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> 11 Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> 12 Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> 13 Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org> 14 Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk> 15 Copyright (c) 2017 Joe Orton <jorton@redhat.com> 16 Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> 17 Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it> 18 Copyright (c) 2019 David Loffredo <loffredo@steptools.com> 19 Copyright (c) 2020 Tim Gates <tim.gates@iress.com> 20 Copyright (c) 2021 Dong-hee Na <donghee.na@python.org> 21 Licensed under the MIT license: 22 23 Permission is hereby granted, free of charge, to any person obtaining 24 a copy of this software and associated documentation files (the 25 "Software"), to deal in the Software without restriction, including 26 without limitation the rights to use, copy, modify, merge, publish, 27 distribute, sublicense, and/or sell copies of the Software, and to permit 28 persons to whom the Software is furnished to do so, subject to the 29 following conditions: 30 31 The above copyright notice and this permission notice shall be included 32 in all copies or substantial portions of the Software. 33 34 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 35 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 36 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 37 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 38 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 39 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 40 USE OR OTHER DEALINGS IN THE SOFTWARE. 41 */ 42 43 #include <expat_config.h> 44 45 #if defined(NDEBUG) 46 # undef NDEBUG /* because test suite relies on assert(...) at the moment */ 47 #endif 48 49 #include <assert.h> 50 #include <stdlib.h> 51 #include <stdio.h> 52 #include <string.h> 53 #include <stddef.h> /* ptrdiff_t */ 54 #include <ctype.h> 55 #include <limits.h> 56 #include <stdint.h> /* intptr_t uint64_t */ 57 58 #if ! defined(__cplusplus) 59 # include <stdbool.h> 60 #endif 61 62 #include "expat.h" 63 #include "chardata.h" 64 #include "structdata.h" 65 #include "internal.h" 66 #include "minicheck.h" 67 #include "memcheck.h" 68 #include "siphash.h" 69 #include "ascii.h" /* for ASCII_xxx */ 70 71 #ifdef XML_LARGE_SIZE 72 # define XML_FMT_INT_MOD "ll" 73 #else 74 # define XML_FMT_INT_MOD "l" 75 #endif 76 77 #ifdef XML_UNICODE_WCHAR_T 78 # define XML_FMT_CHAR "lc" 79 # define XML_FMT_STR "ls" 80 # include <wchar.h> 81 # define xcstrlen(s) wcslen(s) 82 # define xcstrcmp(s, t) wcscmp((s), (t)) 83 # define xcstrncmp(s, t, n) wcsncmp((s), (t), (n)) 84 # define XCS(s) _XCS(s) 85 # define _XCS(s) L##s 86 #else 87 # ifdef XML_UNICODE 88 # error "No support for UTF-16 character without wchar_t in tests" 89 # else 90 # define XML_FMT_CHAR "c" 91 # define XML_FMT_STR "s" 92 # define xcstrlen(s) strlen(s) 93 # define xcstrcmp(s, t) strcmp((s), (t)) 94 # define xcstrncmp(s, t, n) strncmp((s), (t), (n)) 95 # define XCS(s) s 96 # endif /* XML_UNICODE */ 97 #endif /* XML_UNICODE_WCHAR_T */ 98 99 static XML_Parser g_parser = NULL; 100 101 static void 102 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) { 103 #ifdef XML_DTD 104 tcase_add_test(tc, test); 105 #else 106 UNUSED_P(tc); 107 UNUSED_P(test); 108 #endif 109 } 110 111 static void 112 basic_setup(void) { 113 g_parser = XML_ParserCreate(NULL); 114 if (g_parser == NULL) 115 fail("Parser not created."); 116 } 117 118 static void 119 basic_teardown(void) { 120 if (g_parser != NULL) { 121 XML_ParserFree(g_parser); 122 g_parser = NULL; 123 } 124 } 125 126 /* Generate a failure using the parser state to create an error message; 127 this should be used when the parser reports an error we weren't 128 expecting. 129 */ 130 static void 131 _xml_failure(XML_Parser parser, const char *file, int line) { 132 char buffer[1024]; 133 enum XML_Error err = XML_GetErrorCode(parser); 134 sprintf(buffer, 135 " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD 136 "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n", 137 err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser), 138 XML_GetCurrentColumnNumber(parser), file, line); 139 _fail_unless(0, file, line, buffer); 140 } 141 142 static enum XML_Status 143 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len, 144 int isFinal) { 145 enum XML_Status res = XML_STATUS_ERROR; 146 int offset = 0; 147 148 if (len == 0) { 149 return XML_Parse(parser, s, len, isFinal); 150 } 151 152 for (; offset < len; offset++) { 153 const int innerIsFinal = (offset == len - 1) && isFinal; 154 const char c = s[offset]; /* to help out-of-bounds detection */ 155 res = XML_Parse(parser, &c, sizeof(char), innerIsFinal); 156 if (res != XML_STATUS_OK) { 157 return res; 158 } 159 } 160 return res; 161 } 162 163 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__) 164 165 static void 166 _expect_failure(const char *text, enum XML_Error errorCode, 167 const char *errorMessage, const char *file, int lineno) { 168 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 169 == XML_STATUS_OK) 170 /* Hackish use of _fail_unless() macro, but let's us report 171 the right filename and line number. */ 172 _fail_unless(0, file, lineno, errorMessage); 173 if (XML_GetErrorCode(g_parser) != errorCode) 174 _xml_failure(g_parser, file, lineno); 175 } 176 177 #define expect_failure(text, errorCode, errorMessage) \ 178 _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__) 179 180 /* Dummy handlers for when we need to set a handler to tickle a bug, 181 but it doesn't need to do anything. 182 */ 183 static unsigned long dummy_handler_flags = 0; 184 185 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0) 186 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1) 187 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2) 188 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3) 189 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4) 190 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5) 191 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6) 192 #define DUMMY_PI_HANDLER_FLAG (1UL << 7) 193 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8) 194 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9) 195 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10) 196 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11) 197 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12) 198 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13) 199 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14) 200 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15) 201 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16) 202 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17) 203 204 static void XMLCALL 205 dummy_xdecl_handler(void *userData, const XML_Char *version, 206 const XML_Char *encoding, int standalone) { 207 UNUSED_P(userData); 208 UNUSED_P(version); 209 UNUSED_P(encoding); 210 UNUSED_P(standalone); 211 } 212 213 static void XMLCALL 214 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName, 215 const XML_Char *sysid, const XML_Char *pubid, 216 int has_internal_subset) { 217 UNUSED_P(userData); 218 UNUSED_P(doctypeName); 219 UNUSED_P(sysid); 220 UNUSED_P(pubid); 221 UNUSED_P(has_internal_subset); 222 dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG; 223 } 224 225 static void XMLCALL 226 dummy_end_doctype_handler(void *userData) { 227 UNUSED_P(userData); 228 dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG; 229 } 230 231 static void XMLCALL 232 dummy_entity_decl_handler(void *userData, const XML_Char *entityName, 233 int is_parameter_entity, const XML_Char *value, 234 int value_length, const XML_Char *base, 235 const XML_Char *systemId, const XML_Char *publicId, 236 const XML_Char *notationName) { 237 UNUSED_P(userData); 238 UNUSED_P(entityName); 239 UNUSED_P(is_parameter_entity); 240 UNUSED_P(value); 241 UNUSED_P(value_length); 242 UNUSED_P(base); 243 UNUSED_P(systemId); 244 UNUSED_P(publicId); 245 UNUSED_P(notationName); 246 dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG; 247 } 248 249 static void XMLCALL 250 dummy_notation_decl_handler(void *userData, const XML_Char *notationName, 251 const XML_Char *base, const XML_Char *systemId, 252 const XML_Char *publicId) { 253 UNUSED_P(userData); 254 UNUSED_P(notationName); 255 UNUSED_P(base); 256 UNUSED_P(systemId); 257 UNUSED_P(publicId); 258 dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG; 259 } 260 261 static void XMLCALL 262 dummy_element_decl_handler(void *userData, const XML_Char *name, 263 XML_Content *model) { 264 UNUSED_P(userData); 265 UNUSED_P(name); 266 /* The content model must be freed by the handler. Unfortunately 267 * we cannot pass the parser as the userData because this is used 268 * with other handlers that require other userData. 269 */ 270 XML_FreeContentModel(g_parser, model); 271 dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG; 272 } 273 274 static void XMLCALL 275 dummy_attlist_decl_handler(void *userData, const XML_Char *elname, 276 const XML_Char *attname, const XML_Char *att_type, 277 const XML_Char *dflt, int isrequired) { 278 UNUSED_P(userData); 279 UNUSED_P(elname); 280 UNUSED_P(attname); 281 UNUSED_P(att_type); 282 UNUSED_P(dflt); 283 UNUSED_P(isrequired); 284 dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG; 285 } 286 287 static void XMLCALL 288 dummy_comment_handler(void *userData, const XML_Char *data) { 289 UNUSED_P(userData); 290 UNUSED_P(data); 291 dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG; 292 } 293 294 static void XMLCALL 295 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) { 296 UNUSED_P(userData); 297 UNUSED_P(target); 298 UNUSED_P(data); 299 dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG; 300 } 301 302 static void XMLCALL 303 dummy_start_element(void *userData, const XML_Char *name, 304 const XML_Char **atts) { 305 UNUSED_P(userData); 306 UNUSED_P(name); 307 UNUSED_P(atts); 308 dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG; 309 } 310 311 static void XMLCALL 312 dummy_end_element(void *userData, const XML_Char *name) { 313 UNUSED_P(userData); 314 UNUSED_P(name); 315 } 316 317 static void XMLCALL 318 dummy_start_cdata_handler(void *userData) { 319 UNUSED_P(userData); 320 dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG; 321 } 322 323 static void XMLCALL 324 dummy_end_cdata_handler(void *userData) { 325 UNUSED_P(userData); 326 dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG; 327 } 328 329 static void XMLCALL 330 dummy_cdata_handler(void *userData, const XML_Char *s, int len) { 331 UNUSED_P(userData); 332 UNUSED_P(s); 333 UNUSED_P(len); 334 } 335 336 static void XMLCALL 337 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix, 338 const XML_Char *uri) { 339 UNUSED_P(userData); 340 UNUSED_P(prefix); 341 UNUSED_P(uri); 342 dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG; 343 } 344 345 static void XMLCALL 346 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) { 347 UNUSED_P(userData); 348 UNUSED_P(prefix); 349 dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG; 350 } 351 352 /* This handler is obsolete, but while the code exists we should 353 * ensure that dealing with the handler is covered by tests. 354 */ 355 static void XMLCALL 356 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName, 357 const XML_Char *base, 358 const XML_Char *systemId, 359 const XML_Char *publicId, 360 const XML_Char *notationName) { 361 UNUSED_P(userData); 362 UNUSED_P(entityName); 363 UNUSED_P(base); 364 UNUSED_P(systemId); 365 UNUSED_P(publicId); 366 UNUSED_P(notationName); 367 dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG; 368 } 369 370 static void XMLCALL 371 dummy_default_handler(void *userData, const XML_Char *s, int len) { 372 UNUSED_P(userData); 373 UNUSED_P(s); 374 UNUSED_P(len); 375 } 376 377 static void XMLCALL 378 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName, 379 const XML_Char *sysid, const XML_Char *pubid, 380 int has_internal_subset) { 381 UNUSED_P(userData); 382 UNUSED_P(doctypeName); 383 UNUSED_P(sysid); 384 UNUSED_P(pubid); 385 UNUSED_P(has_internal_subset); 386 dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG; 387 } 388 389 static void XMLCALL 390 dummy_end_doctype_decl_handler(void *userData) { 391 UNUSED_P(userData); 392 dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG; 393 } 394 395 static void XMLCALL 396 dummy_skip_handler(void *userData, const XML_Char *entityName, 397 int is_parameter_entity) { 398 UNUSED_P(userData); 399 UNUSED_P(entityName); 400 UNUSED_P(is_parameter_entity); 401 dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG; 402 } 403 404 /* Useful external entity handler */ 405 typedef struct ExtOption { 406 const XML_Char *system_id; 407 const char *parse_text; 408 } ExtOption; 409 410 static int XMLCALL 411 external_entity_optioner(XML_Parser parser, const XML_Char *context, 412 const XML_Char *base, const XML_Char *systemId, 413 const XML_Char *publicId) { 414 ExtOption *options = (ExtOption *)XML_GetUserData(parser); 415 XML_Parser ext_parser; 416 417 UNUSED_P(base); 418 UNUSED_P(publicId); 419 while (options->parse_text != NULL) { 420 if (! xcstrcmp(systemId, options->system_id)) { 421 enum XML_Status rc; 422 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 423 if (ext_parser == NULL) 424 return XML_STATUS_ERROR; 425 rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text, 426 (int)strlen(options->parse_text), XML_TRUE); 427 XML_ParserFree(ext_parser); 428 return rc; 429 } 430 options++; 431 } 432 fail("No suitable option found"); 433 return XML_STATUS_ERROR; 434 } 435 436 /* 437 * Parameter entity evaluation support. 438 */ 439 #define ENTITY_MATCH_FAIL (-1) 440 #define ENTITY_MATCH_NOT_FOUND (0) 441 #define ENTITY_MATCH_SUCCESS (1) 442 static const XML_Char *entity_name_to_match = NULL; 443 static const XML_Char *entity_value_to_match = NULL; 444 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND; 445 446 static void XMLCALL 447 param_entity_match_handler(void *userData, const XML_Char *entityName, 448 int is_parameter_entity, const XML_Char *value, 449 int value_length, const XML_Char *base, 450 const XML_Char *systemId, const XML_Char *publicId, 451 const XML_Char *notationName) { 452 UNUSED_P(userData); 453 UNUSED_P(base); 454 UNUSED_P(systemId); 455 UNUSED_P(publicId); 456 UNUSED_P(notationName); 457 if (! is_parameter_entity || entity_name_to_match == NULL 458 || entity_value_to_match == NULL) { 459 return; 460 } 461 if (! xcstrcmp(entityName, entity_name_to_match)) { 462 /* The cast here is safe because we control the horizontal and 463 * the vertical, and we therefore know our strings are never 464 * going to overflow an int. 465 */ 466 if (value_length != (int)xcstrlen(entity_value_to_match) 467 || xcstrncmp(value, entity_value_to_match, value_length)) { 468 entity_match_flag = ENTITY_MATCH_FAIL; 469 } else { 470 entity_match_flag = ENTITY_MATCH_SUCCESS; 471 } 472 } 473 /* Else leave the match flag alone */ 474 } 475 476 /* 477 * Character & encoding tests. 478 */ 479 480 START_TEST(test_nul_byte) { 481 char text[] = "<doc>\0</doc>"; 482 483 /* test that a NUL byte (in US-ASCII data) is an error */ 484 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 485 == XML_STATUS_OK) 486 fail("Parser did not report error on NUL-byte."); 487 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 488 xml_failure(g_parser); 489 } 490 END_TEST 491 492 START_TEST(test_u0000_char) { 493 /* test that a NUL byte (in US-ASCII data) is an error */ 494 expect_failure("<doc>�</doc>", XML_ERROR_BAD_CHAR_REF, 495 "Parser did not report error on NUL-byte."); 496 } 497 END_TEST 498 499 START_TEST(test_siphash_self) { 500 if (! sip24_valid()) 501 fail("SipHash self-test failed"); 502 } 503 END_TEST 504 505 START_TEST(test_siphash_spec) { 506 /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */ 507 const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" 508 "\x0a\x0b\x0c\x0d\x0e"; 509 const size_t len = sizeof(message) - 1; 510 const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U); 511 struct siphash state; 512 struct sipkey key; 513 514 sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" 515 "\x0a\x0b\x0c\x0d\x0e\x0f"); 516 sip24_init(&state, &key); 517 518 /* Cover spread across calls */ 519 sip24_update(&state, message, 4); 520 sip24_update(&state, message + 4, len - 4); 521 522 /* Cover null length */ 523 sip24_update(&state, message, 0); 524 525 if (sip24_final(&state) != expected) 526 fail("sip24_final failed spec test\n"); 527 528 /* Cover wrapper */ 529 if (siphash24(message, len, &key) != expected) 530 fail("siphash24 failed spec test\n"); 531 } 532 END_TEST 533 534 START_TEST(test_bom_utf8) { 535 /* This test is really just making sure we don't core on a UTF-8 BOM. */ 536 const char *text = "\357\273\277<e/>"; 537 538 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 539 == XML_STATUS_ERROR) 540 xml_failure(g_parser); 541 } 542 END_TEST 543 544 START_TEST(test_bom_utf16_be) { 545 char text[] = "\376\377\0<\0e\0/\0>"; 546 547 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 548 == XML_STATUS_ERROR) 549 xml_failure(g_parser); 550 } 551 END_TEST 552 553 START_TEST(test_bom_utf16_le) { 554 char text[] = "\377\376<\0e\0/\0>\0"; 555 556 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 557 == XML_STATUS_ERROR) 558 xml_failure(g_parser); 559 } 560 END_TEST 561 562 /* Parse whole buffer at once to exercise a different code path */ 563 START_TEST(test_nobom_utf16_le) { 564 char text[] = " \0<\0e\0/\0>\0"; 565 566 if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR) 567 xml_failure(g_parser); 568 } 569 END_TEST 570 571 static void XMLCALL 572 accumulate_characters(void *userData, const XML_Char *s, int len) { 573 CharData_AppendXMLChars((CharData *)userData, s, len); 574 } 575 576 static void XMLCALL 577 accumulate_attribute(void *userData, const XML_Char *name, 578 const XML_Char **atts) { 579 CharData *storage = (CharData *)userData; 580 UNUSED_P(name); 581 /* Check there are attributes to deal with */ 582 if (atts == NULL) 583 return; 584 585 while (storage->count < 0 && atts[0] != NULL) { 586 /* "accumulate" the value of the first attribute we see */ 587 CharData_AppendXMLChars(storage, atts[1], -1); 588 atts += 2; 589 } 590 } 591 592 static void 593 _run_character_check(const char *text, const XML_Char *expected, 594 const char *file, int line) { 595 CharData storage; 596 597 CharData_Init(&storage); 598 XML_SetUserData(g_parser, &storage); 599 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 600 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 601 == XML_STATUS_ERROR) 602 _xml_failure(g_parser, file, line); 603 CharData_CheckXMLChars(&storage, expected); 604 } 605 606 #define run_character_check(text, expected) \ 607 _run_character_check(text, expected, __FILE__, __LINE__) 608 609 static void 610 _run_attribute_check(const char *text, const XML_Char *expected, 611 const char *file, int line) { 612 CharData storage; 613 614 CharData_Init(&storage); 615 XML_SetUserData(g_parser, &storage); 616 XML_SetStartElementHandler(g_parser, accumulate_attribute); 617 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 618 == XML_STATUS_ERROR) 619 _xml_failure(g_parser, file, line); 620 CharData_CheckXMLChars(&storage, expected); 621 } 622 623 #define run_attribute_check(text, expected) \ 624 _run_attribute_check(text, expected, __FILE__, __LINE__) 625 626 typedef struct ExtTest { 627 const char *parse_text; 628 const XML_Char *encoding; 629 CharData *storage; 630 } ExtTest; 631 632 static void XMLCALL 633 ext_accumulate_characters(void *userData, const XML_Char *s, int len) { 634 ExtTest *test_data = (ExtTest *)userData; 635 accumulate_characters(test_data->storage, s, len); 636 } 637 638 static void 639 _run_ext_character_check(const char *text, ExtTest *test_data, 640 const XML_Char *expected, const char *file, int line) { 641 CharData *const storage = (CharData *)malloc(sizeof(CharData)); 642 643 CharData_Init(storage); 644 test_data->storage = storage; 645 XML_SetUserData(g_parser, test_data); 646 XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters); 647 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 648 == XML_STATUS_ERROR) 649 _xml_failure(g_parser, file, line); 650 CharData_CheckXMLChars(storage, expected); 651 652 free(storage); 653 } 654 655 #define run_ext_character_check(text, test_data, expected) \ 656 _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__) 657 658 /* Regression test for SF bug #491986. */ 659 START_TEST(test_danish_latin1) { 660 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 661 "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>"; 662 #ifdef XML_UNICODE 663 const XML_Char *expected 664 = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5"); 665 #else 666 const XML_Char *expected 667 = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85"); 668 #endif 669 run_character_check(text, expected); 670 } 671 END_TEST 672 673 /* Regression test for SF bug #514281. */ 674 START_TEST(test_french_charref_hexidecimal) { 675 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 676 "<doc>éèàçêÈ</doc>"; 677 #ifdef XML_UNICODE 678 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8"); 679 #else 680 const XML_Char *expected 681 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88"); 682 #endif 683 run_character_check(text, expected); 684 } 685 END_TEST 686 687 START_TEST(test_french_charref_decimal) { 688 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 689 "<doc>éèàçêÈ</doc>"; 690 #ifdef XML_UNICODE 691 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8"); 692 #else 693 const XML_Char *expected 694 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88"); 695 #endif 696 run_character_check(text, expected); 697 } 698 END_TEST 699 700 START_TEST(test_french_latin1) { 701 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 702 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>"; 703 #ifdef XML_UNICODE 704 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8"); 705 #else 706 const XML_Char *expected 707 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88"); 708 #endif 709 run_character_check(text, expected); 710 } 711 END_TEST 712 713 START_TEST(test_french_utf8) { 714 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 715 "<doc>\xC3\xA9</doc>"; 716 #ifdef XML_UNICODE 717 const XML_Char *expected = XCS("\x00e9"); 718 #else 719 const XML_Char *expected = XCS("\xC3\xA9"); 720 #endif 721 run_character_check(text, expected); 722 } 723 END_TEST 724 725 /* Regression test for SF bug #600479. 726 XXX There should be a test that exercises all legal XML Unicode 727 characters as PCDATA and attribute value content, and XML Name 728 characters as part of element and attribute names. 729 */ 730 START_TEST(test_utf8_false_rejection) { 731 const char *text = "<doc>\xEF\xBA\xBF</doc>"; 732 #ifdef XML_UNICODE 733 const XML_Char *expected = XCS("\xfebf"); 734 #else 735 const XML_Char *expected = XCS("\xEF\xBA\xBF"); 736 #endif 737 run_character_check(text, expected); 738 } 739 END_TEST 740 741 /* Regression test for SF bug #477667. 742 This test assures that any 8-bit character followed by a 7-bit 743 character will not be mistakenly interpreted as a valid UTF-8 744 sequence. 745 */ 746 START_TEST(test_illegal_utf8) { 747 char text[100]; 748 int i; 749 750 for (i = 128; i <= 255; ++i) { 751 sprintf(text, "<e>%ccd</e>", i); 752 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 753 == XML_STATUS_OK) { 754 sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text", 755 i, i); 756 fail(text); 757 } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 758 xml_failure(g_parser); 759 /* Reset the parser since we use the same parser repeatedly. */ 760 XML_ParserReset(g_parser, NULL); 761 } 762 } 763 END_TEST 764 765 /* Examples, not masks: */ 766 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */ 767 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */ 768 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */ 769 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */ 770 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */ 771 772 START_TEST(test_utf8_auto_align) { 773 struct TestCase { 774 ptrdiff_t expectedMovementInChars; 775 const char *input; 776 }; 777 778 struct TestCase cases[] = { 779 {00, ""}, 780 781 {00, UTF8_LEAD_1}, 782 783 {-1, UTF8_LEAD_2}, 784 {00, UTF8_LEAD_2 UTF8_FOLLOW}, 785 786 {-1, UTF8_LEAD_3}, 787 {-2, UTF8_LEAD_3 UTF8_FOLLOW}, 788 {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW}, 789 790 {-1, UTF8_LEAD_4}, 791 {-2, UTF8_LEAD_4 UTF8_FOLLOW}, 792 {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW}, 793 {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW}, 794 }; 795 796 size_t i = 0; 797 bool success = true; 798 for (; i < sizeof(cases) / sizeof(*cases); i++) { 799 const char *fromLim = cases[i].input + strlen(cases[i].input); 800 const char *const fromLimInitially = fromLim; 801 ptrdiff_t actualMovementInChars; 802 803 _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim); 804 805 actualMovementInChars = (fromLim - fromLimInitially); 806 if (actualMovementInChars != cases[i].expectedMovementInChars) { 807 size_t j = 0; 808 success = false; 809 printf("[-] UTF-8 case %2u: Expected movement by %2d chars" 810 ", actually moved by %2d chars: \"", 811 (unsigned)(i + 1), (int)cases[i].expectedMovementInChars, 812 (int)actualMovementInChars); 813 for (; j < strlen(cases[i].input); j++) { 814 printf("\\x%02x", (unsigned char)cases[i].input[j]); 815 } 816 printf("\"\n"); 817 } 818 } 819 820 if (! success) { 821 fail("UTF-8 auto-alignment is not bullet-proof\n"); 822 } 823 } 824 END_TEST 825 826 START_TEST(test_utf16) { 827 /* <?xml version="1.0" encoding="UTF-16"?> 828 * <doc a='123'>some {A} text</doc> 829 * 830 * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A 831 */ 832 char text[] 833 = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o" 834 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o" 835 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066" 836 "\000'\000?\000>\000\n" 837 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>" 838 "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000" 839 "<\000/\000d\000o\000c\000>"; 840 #ifdef XML_UNICODE 841 const XML_Char *expected = XCS("some \xff21 text"); 842 #else 843 const XML_Char *expected = XCS("some \357\274\241 text"); 844 #endif 845 CharData storage; 846 847 CharData_Init(&storage); 848 XML_SetUserData(g_parser, &storage); 849 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 850 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 851 == XML_STATUS_ERROR) 852 xml_failure(g_parser); 853 CharData_CheckXMLChars(&storage, expected); 854 } 855 END_TEST 856 857 START_TEST(test_utf16_le_epilog_newline) { 858 unsigned int first_chunk_bytes = 17; 859 char text[] = "\xFF\xFE" /* BOM */ 860 "<\000e\000/\000>\000" /* document element */ 861 "\r\000\n\000\r\000\n\000"; /* epilog */ 862 863 if (first_chunk_bytes >= sizeof(text) - 1) 864 fail("bad value of first_chunk_bytes"); 865 if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE) 866 == XML_STATUS_ERROR) 867 xml_failure(g_parser); 868 else { 869 enum XML_Status rc; 870 rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes, 871 sizeof(text) - first_chunk_bytes - 1, 872 XML_TRUE); 873 if (rc == XML_STATUS_ERROR) 874 xml_failure(g_parser); 875 } 876 } 877 END_TEST 878 879 /* Test that an outright lie in the encoding is faulted */ 880 START_TEST(test_not_utf16) { 881 const char *text = "<?xml version='1.0' encoding='utf-16'?>" 882 "<doc>Hi</doc>"; 883 884 /* Use a handler to provoke the appropriate code paths */ 885 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 886 expect_failure(text, XML_ERROR_INCORRECT_ENCODING, 887 "UTF-16 declared in UTF-8 not faulted"); 888 } 889 END_TEST 890 891 /* Test that an unknown encoding is rejected */ 892 START_TEST(test_bad_encoding) { 893 const char *text = "<doc>Hi</doc>"; 894 895 if (! XML_SetEncoding(g_parser, XCS("unknown-encoding"))) 896 fail("XML_SetEncoding failed"); 897 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 898 "Unknown encoding not faulted"); 899 } 900 END_TEST 901 902 /* Regression test for SF bug #481609, #774028. */ 903 START_TEST(test_latin1_umlauts) { 904 const char *text 905 = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 906 "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n" 907 " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>"; 908 #ifdef XML_UNICODE 909 /* Expected results in UTF-16 */ 910 const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ") 911 XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >"); 912 #else 913 /* Expected results in UTF-8 */ 914 const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") 915 XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >"); 916 #endif 917 918 run_character_check(text, expected); 919 XML_ParserReset(g_parser, NULL); 920 run_attribute_check(text, expected); 921 /* Repeat with a default handler */ 922 XML_ParserReset(g_parser, NULL); 923 XML_SetDefaultHandler(g_parser, dummy_default_handler); 924 run_character_check(text, expected); 925 XML_ParserReset(g_parser, NULL); 926 XML_SetDefaultHandler(g_parser, dummy_default_handler); 927 run_attribute_check(text, expected); 928 } 929 END_TEST 930 931 /* Test that an element name with a 4-byte UTF-8 character is rejected */ 932 START_TEST(test_long_utf8_character) { 933 const char *text 934 = "<?xml version='1.0' encoding='utf-8'?>\n" 935 /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */ 936 "<do\xf0\x90\x80\x80/>"; 937 expect_failure(text, XML_ERROR_INVALID_TOKEN, 938 "4-byte UTF-8 character in element name not faulted"); 939 } 940 END_TEST 941 942 /* Test that a long latin-1 attribute (too long to convert in one go) 943 * is correctly converted 944 */ 945 START_TEST(test_long_latin1_attribute) { 946 const char *text 947 = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 948 "<doc att='" 949 /* 64 characters per line */ 950 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 951 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 952 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 953 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 954 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 955 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 956 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 957 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 958 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 959 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 960 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 961 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 962 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 963 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 964 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 965 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 966 /* Last character splits across a buffer boundary */ 967 "\xe4'>\n</doc>"; 968 969 const XML_Char *expected = 970 /* 64 characters per line */ 971 /* clang-format off */ 972 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 973 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 974 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 975 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 976 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 977 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 978 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 979 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 980 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 981 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 982 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 983 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 984 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 985 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 986 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 987 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO") 988 /* clang-format on */ 989 #ifdef XML_UNICODE 990 XCS("\x00e4"); 991 #else 992 XCS("\xc3\xa4"); 993 #endif 994 995 run_attribute_check(text, expected); 996 } 997 END_TEST 998 999 /* Test that a long ASCII attribute (too long to convert in one go) 1000 * is correctly converted 1001 */ 1002 START_TEST(test_long_ascii_attribute) { 1003 const char *text 1004 = "<?xml version='1.0' encoding='us-ascii'?>\n" 1005 "<doc att='" 1006 /* 64 characters per line */ 1007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1023 "01234'>\n</doc>"; 1024 const XML_Char *expected = 1025 /* 64 characters per line */ 1026 /* clang-format off */ 1027 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1028 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1029 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1030 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1031 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1032 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1033 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1034 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1035 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1036 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1037 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1038 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1039 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1040 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1041 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1042 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1043 XCS("01234"); 1044 /* clang-format on */ 1045 1046 run_attribute_check(text, expected); 1047 } 1048 END_TEST 1049 1050 /* Regression test #1 for SF bug #653180. */ 1051 START_TEST(test_line_number_after_parse) { 1052 const char *text = "<tag>\n" 1053 "\n" 1054 "\n</tag>"; 1055 XML_Size lineno; 1056 1057 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1058 == XML_STATUS_ERROR) 1059 xml_failure(g_parser); 1060 lineno = XML_GetCurrentLineNumber(g_parser); 1061 if (lineno != 4) { 1062 char buffer[100]; 1063 sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno); 1064 fail(buffer); 1065 } 1066 } 1067 END_TEST 1068 1069 /* Regression test #2 for SF bug #653180. */ 1070 START_TEST(test_column_number_after_parse) { 1071 const char *text = "<tag></tag>"; 1072 XML_Size colno; 1073 1074 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1075 == XML_STATUS_ERROR) 1076 xml_failure(g_parser); 1077 colno = XML_GetCurrentColumnNumber(g_parser); 1078 if (colno != 11) { 1079 char buffer[100]; 1080 sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno); 1081 fail(buffer); 1082 } 1083 } 1084 END_TEST 1085 1086 #define STRUCT_START_TAG 0 1087 #define STRUCT_END_TAG 1 1088 static void XMLCALL 1089 start_element_event_handler2(void *userData, const XML_Char *name, 1090 const XML_Char **attr) { 1091 StructData *storage = (StructData *)userData; 1092 UNUSED_P(attr); 1093 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), 1094 XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG); 1095 } 1096 1097 static void XMLCALL 1098 end_element_event_handler2(void *userData, const XML_Char *name) { 1099 StructData *storage = (StructData *)userData; 1100 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), 1101 XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG); 1102 } 1103 1104 /* Regression test #3 for SF bug #653180. */ 1105 START_TEST(test_line_and_column_numbers_inside_handlers) { 1106 const char *text = "<a>\n" /* Unix end-of-line */ 1107 " <b>\r\n" /* Windows end-of-line */ 1108 " <c/>\r" /* Mac OS end-of-line */ 1109 " </b>\n" 1110 " <d>\n" 1111 " <f/>\n" 1112 " </d>\n" 1113 "</a>"; 1114 const StructDataEntry expected[] 1115 = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG}, 1116 {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG}, 1117 {XCS("b"), 2, 4, STRUCT_END_TAG}, {XCS("d"), 2, 5, STRUCT_START_TAG}, 1118 {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG}, 1119 {XCS("d"), 2, 7, STRUCT_END_TAG}, {XCS("a"), 0, 8, STRUCT_END_TAG}}; 1120 const int expected_count = sizeof(expected) / sizeof(StructDataEntry); 1121 StructData storage; 1122 1123 StructData_Init(&storage); 1124 XML_SetUserData(g_parser, &storage); 1125 XML_SetStartElementHandler(g_parser, start_element_event_handler2); 1126 XML_SetEndElementHandler(g_parser, end_element_event_handler2); 1127 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1128 == XML_STATUS_ERROR) 1129 xml_failure(g_parser); 1130 1131 StructData_CheckItems(&storage, expected, expected_count); 1132 StructData_Dispose(&storage); 1133 } 1134 END_TEST 1135 1136 /* Regression test #4 for SF bug #653180. */ 1137 START_TEST(test_line_number_after_error) { 1138 const char *text = "<a>\n" 1139 " <b>\n" 1140 " </a>"; /* missing </b> */ 1141 XML_Size lineno; 1142 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1143 != XML_STATUS_ERROR) 1144 fail("Expected a parse error"); 1145 1146 lineno = XML_GetCurrentLineNumber(g_parser); 1147 if (lineno != 3) { 1148 char buffer[100]; 1149 sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno); 1150 fail(buffer); 1151 } 1152 } 1153 END_TEST 1154 1155 /* Regression test #5 for SF bug #653180. */ 1156 START_TEST(test_column_number_after_error) { 1157 const char *text = "<a>\n" 1158 " <b>\n" 1159 " </a>"; /* missing </b> */ 1160 XML_Size colno; 1161 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1162 != XML_STATUS_ERROR) 1163 fail("Expected a parse error"); 1164 1165 colno = XML_GetCurrentColumnNumber(g_parser); 1166 if (colno != 4) { 1167 char buffer[100]; 1168 sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno); 1169 fail(buffer); 1170 } 1171 } 1172 END_TEST 1173 1174 /* Regression test for SF bug #478332. */ 1175 START_TEST(test_really_long_lines) { 1176 /* This parses an input line longer than INIT_DATA_BUF_SIZE 1177 characters long (defined to be 1024 in xmlparse.c). We take a 1178 really cheesy approach to building the input buffer, because 1179 this avoids writing bugs in buffer-filling code. 1180 */ 1181 const char *text 1182 = "<e>" 1183 /* 64 chars */ 1184 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1185 /* until we have at least 1024 characters on the line: */ 1186 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1187 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1188 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1189 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1190 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1192 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1193 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1194 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1195 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1196 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1197 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1198 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1199 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1200 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1201 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1202 "</e>"; 1203 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1204 == XML_STATUS_ERROR) 1205 xml_failure(g_parser); 1206 } 1207 END_TEST 1208 1209 /* Test cdata processing across a buffer boundary */ 1210 START_TEST(test_really_long_encoded_lines) { 1211 /* As above, except that we want to provoke an output buffer 1212 * overflow with a non-trivial encoding. For this we need to pass 1213 * the whole cdata in one go, not byte-by-byte. 1214 */ 1215 void *buffer; 1216 const char *text 1217 = "<?xml version='1.0' encoding='iso-8859-1'?>" 1218 "<e>" 1219 /* 64 chars */ 1220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1221 /* until we have at least 1024 characters on the line: */ 1222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1233 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1234 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1235 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1236 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1237 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1238 "</e>"; 1239 int parse_len = (int)strlen(text); 1240 1241 /* Need a cdata handler to provoke the code path we want to test */ 1242 XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler); 1243 buffer = XML_GetBuffer(g_parser, parse_len); 1244 if (buffer == NULL) 1245 fail("Could not allocate parse buffer"); 1246 assert(buffer != NULL); 1247 memcpy(buffer, text, parse_len); 1248 if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR) 1249 xml_failure(g_parser); 1250 } 1251 END_TEST 1252 1253 /* 1254 * Element event tests. 1255 */ 1256 1257 static void XMLCALL 1258 start_element_event_handler(void *userData, const XML_Char *name, 1259 const XML_Char **atts) { 1260 UNUSED_P(atts); 1261 CharData_AppendXMLChars((CharData *)userData, name, -1); 1262 } 1263 1264 static void XMLCALL 1265 end_element_event_handler(void *userData, const XML_Char *name) { 1266 CharData *storage = (CharData *)userData; 1267 CharData_AppendXMLChars(storage, XCS("/"), 1); 1268 CharData_AppendXMLChars(storage, name, -1); 1269 } 1270 1271 START_TEST(test_end_element_events) { 1272 const char *text = "<a><b><c/></b><d><f/></d></a>"; 1273 const XML_Char *expected = XCS("/c/b/f/d/a"); 1274 CharData storage; 1275 1276 CharData_Init(&storage); 1277 XML_SetUserData(g_parser, &storage); 1278 XML_SetEndElementHandler(g_parser, end_element_event_handler); 1279 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1280 == XML_STATUS_ERROR) 1281 xml_failure(g_parser); 1282 CharData_CheckXMLChars(&storage, expected); 1283 } 1284 END_TEST 1285 1286 /* 1287 * Attribute tests. 1288 */ 1289 1290 /* Helpers used by the following test; this checks any "attr" and "refs" 1291 attributes to make sure whitespace has been normalized. 1292 1293 Return true if whitespace has been normalized in a string, using 1294 the rules for attribute value normalization. The 'is_cdata' flag 1295 is needed since CDATA attributes don't need to have multiple 1296 whitespace characters collapsed to a single space, while other 1297 attribute data types do. (Section 3.3.3 of the recommendation.) 1298 */ 1299 static int 1300 is_whitespace_normalized(const XML_Char *s, int is_cdata) { 1301 int blanks = 0; 1302 int at_start = 1; 1303 while (*s) { 1304 if (*s == XCS(' ')) 1305 ++blanks; 1306 else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r')) 1307 return 0; 1308 else { 1309 if (at_start) { 1310 at_start = 0; 1311 if (blanks && ! is_cdata) 1312 /* illegal leading blanks */ 1313 return 0; 1314 } else if (blanks > 1 && ! is_cdata) 1315 return 0; 1316 blanks = 0; 1317 } 1318 ++s; 1319 } 1320 if (blanks && ! is_cdata) 1321 return 0; 1322 return 1; 1323 } 1324 1325 /* Check the attribute whitespace checker: */ 1326 static void 1327 testhelper_is_whitespace_normalized(void) { 1328 assert(is_whitespace_normalized(XCS("abc"), 0)); 1329 assert(is_whitespace_normalized(XCS("abc"), 1)); 1330 assert(is_whitespace_normalized(XCS("abc def ghi"), 0)); 1331 assert(is_whitespace_normalized(XCS("abc def ghi"), 1)); 1332 assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0)); 1333 assert(is_whitespace_normalized(XCS(" abc def ghi"), 1)); 1334 assert(! is_whitespace_normalized(XCS("abc def ghi"), 0)); 1335 assert(is_whitespace_normalized(XCS("abc def ghi"), 1)); 1336 assert(! is_whitespace_normalized(XCS("abc def ghi "), 0)); 1337 assert(is_whitespace_normalized(XCS("abc def ghi "), 1)); 1338 assert(! is_whitespace_normalized(XCS(" "), 0)); 1339 assert(is_whitespace_normalized(XCS(" "), 1)); 1340 assert(! is_whitespace_normalized(XCS("\t"), 0)); 1341 assert(! is_whitespace_normalized(XCS("\t"), 1)); 1342 assert(! is_whitespace_normalized(XCS("\n"), 0)); 1343 assert(! is_whitespace_normalized(XCS("\n"), 1)); 1344 assert(! is_whitespace_normalized(XCS("\r"), 0)); 1345 assert(! is_whitespace_normalized(XCS("\r"), 1)); 1346 assert(! is_whitespace_normalized(XCS("abc\t def"), 1)); 1347 } 1348 1349 static void XMLCALL 1350 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name, 1351 const XML_Char **atts) { 1352 int i; 1353 UNUSED_P(userData); 1354 UNUSED_P(name); 1355 for (i = 0; atts[i] != NULL; i += 2) { 1356 const XML_Char *attrname = atts[i]; 1357 const XML_Char *value = atts[i + 1]; 1358 if (xcstrcmp(XCS("attr"), attrname) == 0 1359 || xcstrcmp(XCS("ents"), attrname) == 0 1360 || xcstrcmp(XCS("refs"), attrname) == 0) { 1361 if (! is_whitespace_normalized(value, 0)) { 1362 char buffer[256]; 1363 sprintf(buffer, 1364 "attribute value not normalized: %" XML_FMT_STR 1365 "='%" XML_FMT_STR "'", 1366 attrname, value); 1367 fail(buffer); 1368 } 1369 } 1370 } 1371 } 1372 1373 START_TEST(test_attr_whitespace_normalization) { 1374 const char *text 1375 = "<!DOCTYPE doc [\n" 1376 " <!ATTLIST doc\n" 1377 " attr NMTOKENS #REQUIRED\n" 1378 " ents ENTITIES #REQUIRED\n" 1379 " refs IDREFS #REQUIRED>\n" 1380 "]>\n" 1381 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n" 1382 " ents=' ent-1 \t\r\n" 1383 " ent-2 ' >\n" 1384 " <e id='id-1'/>\n" 1385 " <e id='id-2'/>\n" 1386 "</doc>"; 1387 1388 XML_SetStartElementHandler(g_parser, 1389 check_attr_contains_normalized_whitespace); 1390 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1391 == XML_STATUS_ERROR) 1392 xml_failure(g_parser); 1393 } 1394 END_TEST 1395 1396 /* 1397 * XML declaration tests. 1398 */ 1399 1400 START_TEST(test_xmldecl_misplaced) { 1401 expect_failure("\n" 1402 "<?xml version='1.0'?>\n" 1403 "<a/>", 1404 XML_ERROR_MISPLACED_XML_PI, 1405 "failed to report misplaced XML declaration"); 1406 } 1407 END_TEST 1408 1409 START_TEST(test_xmldecl_invalid) { 1410 expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL, 1411 "Failed to report invalid XML declaration"); 1412 } 1413 END_TEST 1414 1415 START_TEST(test_xmldecl_missing_attr) { 1416 expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL, 1417 "Failed to report missing XML declaration attribute"); 1418 } 1419 END_TEST 1420 1421 START_TEST(test_xmldecl_missing_value) { 1422 expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n" 1423 "<doc/>", 1424 XML_ERROR_XML_DECL, 1425 "Failed to report missing attribute value"); 1426 } 1427 END_TEST 1428 1429 /* Regression test for SF bug #584832. */ 1430 static int XMLCALL 1431 UnknownEncodingHandler(void *data, const XML_Char *encoding, 1432 XML_Encoding *info) { 1433 UNUSED_P(data); 1434 if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) { 1435 int i; 1436 for (i = 0; i < 256; ++i) 1437 info->map[i] = i; 1438 info->data = NULL; 1439 info->convert = NULL; 1440 info->release = NULL; 1441 return XML_STATUS_OK; 1442 } 1443 return XML_STATUS_ERROR; 1444 } 1445 1446 START_TEST(test_unknown_encoding_internal_entity) { 1447 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 1448 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 1449 "<test a='&foo;'/>"; 1450 1451 XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL); 1452 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1453 == XML_STATUS_ERROR) 1454 xml_failure(g_parser); 1455 } 1456 END_TEST 1457 1458 /* Test unrecognised encoding handler */ 1459 static void 1460 dummy_release(void *data) { 1461 UNUSED_P(data); 1462 } 1463 1464 static int XMLCALL 1465 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding, 1466 XML_Encoding *info) { 1467 UNUSED_P(data); 1468 UNUSED_P(encoding); 1469 info->data = NULL; 1470 info->convert = NULL; 1471 info->release = dummy_release; 1472 return XML_STATUS_ERROR; 1473 } 1474 1475 START_TEST(test_unrecognised_encoding_internal_entity) { 1476 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 1477 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 1478 "<test a='&foo;'/>"; 1479 1480 XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL); 1481 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1482 != XML_STATUS_ERROR) 1483 fail("Unrecognised encoding not rejected"); 1484 } 1485 END_TEST 1486 1487 /* Regression test for SF bug #620106. */ 1488 static int XMLCALL 1489 external_entity_loader(XML_Parser parser, const XML_Char *context, 1490 const XML_Char *base, const XML_Char *systemId, 1491 const XML_Char *publicId) { 1492 ExtTest *test_data = (ExtTest *)XML_GetUserData(parser); 1493 XML_Parser extparser; 1494 1495 UNUSED_P(base); 1496 UNUSED_P(systemId); 1497 UNUSED_P(publicId); 1498 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 1499 if (extparser == NULL) 1500 fail("Could not create external entity parser."); 1501 if (test_data->encoding != NULL) { 1502 if (! XML_SetEncoding(extparser, test_data->encoding)) 1503 fail("XML_SetEncoding() ignored for external entity"); 1504 } 1505 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text, 1506 (int)strlen(test_data->parse_text), XML_TRUE) 1507 == XML_STATUS_ERROR) { 1508 xml_failure(extparser); 1509 return XML_STATUS_ERROR; 1510 } 1511 XML_ParserFree(extparser); 1512 return XML_STATUS_OK; 1513 } 1514 1515 START_TEST(test_ext_entity_set_encoding) { 1516 const char *text = "<!DOCTYPE doc [\n" 1517 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1518 "]>\n" 1519 "<doc>&en;</doc>"; 1520 ExtTest test_data 1521 = {/* This text says it's an unsupported encoding, but it's really 1522 UTF-8, which we tell Expat using XML_SetEncoding(). 1523 */ 1524 "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL}; 1525 #ifdef XML_UNICODE 1526 const XML_Char *expected = XCS("\x00e9"); 1527 #else 1528 const XML_Char *expected = XCS("\xc3\xa9"); 1529 #endif 1530 1531 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1532 run_ext_character_check(text, &test_data, expected); 1533 } 1534 END_TEST 1535 1536 /* Test external entities with no handler */ 1537 START_TEST(test_ext_entity_no_handler) { 1538 const char *text = "<!DOCTYPE doc [\n" 1539 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1540 "]>\n" 1541 "<doc>&en;</doc>"; 1542 1543 XML_SetDefaultHandler(g_parser, dummy_default_handler); 1544 run_character_check(text, XCS("")); 1545 } 1546 END_TEST 1547 1548 /* Test UTF-8 BOM is accepted */ 1549 START_TEST(test_ext_entity_set_bom) { 1550 const char *text = "<!DOCTYPE doc [\n" 1551 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1552 "]>\n" 1553 "<doc>&en;</doc>"; 1554 ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */ 1555 "<?xml encoding='iso-8859-3'?>" 1556 "\xC3\xA9", 1557 XCS("utf-8"), NULL}; 1558 #ifdef XML_UNICODE 1559 const XML_Char *expected = XCS("\x00e9"); 1560 #else 1561 const XML_Char *expected = XCS("\xc3\xa9"); 1562 #endif 1563 1564 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1565 run_ext_character_check(text, &test_data, expected); 1566 } 1567 END_TEST 1568 1569 /* Test that bad encodings are faulted */ 1570 typedef struct ext_faults { 1571 const char *parse_text; 1572 const char *fail_text; 1573 const XML_Char *encoding; 1574 enum XML_Error error; 1575 } ExtFaults; 1576 1577 static int XMLCALL 1578 external_entity_faulter(XML_Parser parser, const XML_Char *context, 1579 const XML_Char *base, const XML_Char *systemId, 1580 const XML_Char *publicId) { 1581 XML_Parser ext_parser; 1582 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 1583 1584 UNUSED_P(base); 1585 UNUSED_P(systemId); 1586 UNUSED_P(publicId); 1587 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 1588 if (ext_parser == NULL) 1589 fail("Could not create external entity parser"); 1590 if (fault->encoding != NULL) { 1591 if (! XML_SetEncoding(ext_parser, fault->encoding)) 1592 fail("XML_SetEncoding failed"); 1593 } 1594 if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text, 1595 (int)strlen(fault->parse_text), XML_TRUE) 1596 != XML_STATUS_ERROR) 1597 fail(fault->fail_text); 1598 if (XML_GetErrorCode(ext_parser) != fault->error) 1599 xml_failure(ext_parser); 1600 1601 XML_ParserFree(ext_parser); 1602 return XML_STATUS_ERROR; 1603 } 1604 1605 START_TEST(test_ext_entity_bad_encoding) { 1606 const char *text = "<!DOCTYPE doc [\n" 1607 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1608 "]>\n" 1609 "<doc>&en;</doc>"; 1610 ExtFaults fault 1611 = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted", 1612 XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING}; 1613 1614 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 1615 XML_SetUserData(g_parser, &fault); 1616 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 1617 "Bad encoding should not have been accepted"); 1618 } 1619 END_TEST 1620 1621 /* Try handing an invalid encoding to an external entity parser */ 1622 START_TEST(test_ext_entity_bad_encoding_2) { 1623 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1624 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1625 "<doc>&entity;</doc>"; 1626 ExtFaults fault 1627 = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted", 1628 XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING}; 1629 1630 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1631 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 1632 XML_SetUserData(g_parser, &fault); 1633 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 1634 "Bad encoding not faulted in external entity handler"); 1635 } 1636 END_TEST 1637 1638 /* Test that no error is reported for unknown entities if we don't 1639 read an external subset. This was fixed in Expat 1.95.5. 1640 */ 1641 START_TEST(test_wfc_undeclared_entity_unread_external_subset) { 1642 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 1643 "<doc>&entity;</doc>"; 1644 1645 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1646 == XML_STATUS_ERROR) 1647 xml_failure(g_parser); 1648 } 1649 END_TEST 1650 1651 /* Test that an error is reported for unknown entities if we don't 1652 have an external subset. 1653 */ 1654 START_TEST(test_wfc_undeclared_entity_no_external_subset) { 1655 expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY, 1656 "Parser did not report undefined entity w/out a DTD."); 1657 } 1658 END_TEST 1659 1660 /* Test that an error is reported for unknown entities if we don't 1661 read an external subset, but have been declared standalone. 1662 */ 1663 START_TEST(test_wfc_undeclared_entity_standalone) { 1664 const char *text 1665 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n" 1666 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1667 "<doc>&entity;</doc>"; 1668 1669 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 1670 "Parser did not report undefined entity (standalone)."); 1671 } 1672 END_TEST 1673 1674 /* Test that an error is reported for unknown entities if we have read 1675 an external subset, and standalone is true. 1676 */ 1677 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) { 1678 const char *text 1679 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n" 1680 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1681 "<doc>&entity;</doc>"; 1682 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1683 1684 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1685 XML_SetUserData(g_parser, &test_data); 1686 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1687 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 1688 "Parser did not report undefined entity (external DTD)."); 1689 } 1690 END_TEST 1691 1692 /* Test that external entity handling is not done if the parsing flag 1693 * is set to UNLESS_STANDALONE 1694 */ 1695 START_TEST(test_entity_with_external_subset_unless_standalone) { 1696 const char *text 1697 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n" 1698 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1699 "<doc>&entity;</doc>"; 1700 ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL}; 1701 1702 XML_SetParamEntityParsing(g_parser, 1703 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); 1704 XML_SetUserData(g_parser, &test_data); 1705 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1706 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 1707 "Parser did not report undefined entity"); 1708 } 1709 END_TEST 1710 1711 /* Test that no error is reported for unknown entities if we have read 1712 an external subset, and standalone is false. 1713 */ 1714 START_TEST(test_wfc_undeclared_entity_with_external_subset) { 1715 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1716 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1717 "<doc>&entity;</doc>"; 1718 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1719 1720 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1721 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1722 run_ext_character_check(text, &test_data, XCS("")); 1723 } 1724 END_TEST 1725 1726 /* Test that an error is reported if our NotStandalone handler fails */ 1727 static int XMLCALL 1728 reject_not_standalone_handler(void *userData) { 1729 UNUSED_P(userData); 1730 return XML_STATUS_ERROR; 1731 } 1732 1733 START_TEST(test_not_standalone_handler_reject) { 1734 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1735 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1736 "<doc>&entity;</doc>"; 1737 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1738 1739 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1740 XML_SetUserData(g_parser, &test_data); 1741 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1742 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler); 1743 expect_failure(text, XML_ERROR_NOT_STANDALONE, 1744 "NotStandalone handler failed to reject"); 1745 1746 /* Try again but without external entity handling */ 1747 XML_ParserReset(g_parser, NULL); 1748 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler); 1749 expect_failure(text, XML_ERROR_NOT_STANDALONE, 1750 "NotStandalone handler failed to reject"); 1751 } 1752 END_TEST 1753 1754 /* Test that no error is reported if our NotStandalone handler succeeds */ 1755 static int XMLCALL 1756 accept_not_standalone_handler(void *userData) { 1757 UNUSED_P(userData); 1758 return XML_STATUS_OK; 1759 } 1760 1761 START_TEST(test_not_standalone_handler_accept) { 1762 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1763 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1764 "<doc>&entity;</doc>"; 1765 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1766 1767 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1768 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1769 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler); 1770 run_ext_character_check(text, &test_data, XCS("")); 1771 1772 /* Repeat without the external entity handler */ 1773 XML_ParserReset(g_parser, NULL); 1774 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler); 1775 run_character_check(text, XCS("")); 1776 } 1777 END_TEST 1778 1779 START_TEST(test_wfc_no_recursive_entity_refs) { 1780 const char *text = "<!DOCTYPE doc [\n" 1781 " <!ENTITY entity '&entity;'>\n" 1782 "]>\n" 1783 "<doc>&entity;</doc>"; 1784 1785 expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF, 1786 "Parser did not report recursive entity reference."); 1787 } 1788 END_TEST 1789 1790 /* Test incomplete external entities are faulted */ 1791 START_TEST(test_ext_entity_invalid_parse) { 1792 const char *text = "<!DOCTYPE doc [\n" 1793 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1794 "]>\n" 1795 "<doc>&en;</doc>"; 1796 const ExtFaults faults[] 1797 = {{"<", "Incomplete element declaration not faulted", NULL, 1798 XML_ERROR_UNCLOSED_TOKEN}, 1799 {"<\xe2\x82", /* First two bytes of a three-byte char */ 1800 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR}, 1801 {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL, 1802 XML_ERROR_PARTIAL_CHAR}, 1803 {NULL, NULL, NULL, XML_ERROR_NONE}}; 1804 const ExtFaults *fault = faults; 1805 1806 for (; fault->parse_text != NULL; fault++) { 1807 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1808 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 1809 XML_SetUserData(g_parser, (void *)fault); 1810 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 1811 "Parser did not report external entity error"); 1812 XML_ParserReset(g_parser, NULL); 1813 } 1814 } 1815 END_TEST 1816 1817 /* Regression test for SF bug #483514. */ 1818 START_TEST(test_dtd_default_handling) { 1819 const char *text = "<!DOCTYPE doc [\n" 1820 "<!ENTITY e SYSTEM 'http://example.org/e'>\n" 1821 "<!NOTATION n SYSTEM 'http://example.org/n'>\n" 1822 "<!ELEMENT doc EMPTY>\n" 1823 "<!ATTLIST doc a CDATA #IMPLIED>\n" 1824 "<?pi in dtd?>\n" 1825 "<!--comment in dtd-->\n" 1826 "]><doc/>"; 1827 1828 XML_SetDefaultHandler(g_parser, accumulate_characters); 1829 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 1830 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 1831 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 1832 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 1833 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 1834 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 1835 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 1836 XML_SetCommentHandler(g_parser, dummy_comment_handler); 1837 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler); 1838 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler); 1839 run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>")); 1840 } 1841 END_TEST 1842 1843 /* Test handling of attribute declarations */ 1844 typedef struct AttTest { 1845 const char *definition; 1846 const XML_Char *element_name; 1847 const XML_Char *attr_name; 1848 const XML_Char *attr_type; 1849 const XML_Char *default_value; 1850 int is_required; 1851 } AttTest; 1852 1853 static void XMLCALL 1854 verify_attlist_decl_handler(void *userData, const XML_Char *element_name, 1855 const XML_Char *attr_name, 1856 const XML_Char *attr_type, 1857 const XML_Char *default_value, int is_required) { 1858 AttTest *at = (AttTest *)userData; 1859 1860 if (xcstrcmp(element_name, at->element_name)) 1861 fail("Unexpected element name in attribute declaration"); 1862 if (xcstrcmp(attr_name, at->attr_name)) 1863 fail("Unexpected attribute name in attribute declaration"); 1864 if (xcstrcmp(attr_type, at->attr_type)) 1865 fail("Unexpected attribute type in attribute declaration"); 1866 if ((default_value == NULL && at->default_value != NULL) 1867 || (default_value != NULL && at->default_value == NULL) 1868 || (default_value != NULL && xcstrcmp(default_value, at->default_value))) 1869 fail("Unexpected default value in attribute declaration"); 1870 if (is_required != at->is_required) 1871 fail("Requirement mismatch in attribute declaration"); 1872 } 1873 1874 START_TEST(test_dtd_attr_handling) { 1875 const char *prolog = "<!DOCTYPE doc [\n" 1876 "<!ELEMENT doc EMPTY>\n"; 1877 AttTest attr_data[] 1878 = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n" 1879 "]>" 1880 "<doc a='two'/>", 1881 XCS("doc"), XCS("a"), 1882 XCS("(one|two|three)"), /* Extraneous spaces will be removed */ 1883 NULL, XML_TRUE}, 1884 {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n" 1885 "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n" 1886 "]>" 1887 "<doc/>", 1888 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE}, 1889 {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n" 1890 "]>" 1891 "<doc/>", 1892 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE}, 1893 {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n" 1894 "]>" 1895 "<doc/>", 1896 XCS("doc"), XCS("a"), XCS("CDATA"), 1897 #ifdef XML_UNICODE 1898 XCS("\x06f2"), 1899 #else 1900 XCS("\xdb\xb2"), 1901 #endif 1902 XML_FALSE}, 1903 {NULL, NULL, NULL, NULL, NULL, XML_FALSE}}; 1904 AttTest *test; 1905 1906 for (test = attr_data; test->definition != NULL; test++) { 1907 XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler); 1908 XML_SetUserData(g_parser, test); 1909 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog), 1910 XML_FALSE) 1911 == XML_STATUS_ERROR) 1912 xml_failure(g_parser); 1913 if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition, 1914 (int)strlen(test->definition), XML_TRUE) 1915 == XML_STATUS_ERROR) 1916 xml_failure(g_parser); 1917 XML_ParserReset(g_parser, NULL); 1918 } 1919 } 1920 END_TEST 1921 1922 /* See related SF bug #673791. 1923 When namespace processing is enabled, setting the namespace URI for 1924 a prefix is not allowed; this test ensures that it *is* allowed 1925 when namespace processing is not enabled. 1926 (See Namespaces in XML, section 2.) 1927 */ 1928 START_TEST(test_empty_ns_without_namespaces) { 1929 const char *text = "<doc xmlns:prefix='http://example.org/'>\n" 1930 " <e xmlns:prefix=''/>\n" 1931 "</doc>"; 1932 1933 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1934 == XML_STATUS_ERROR) 1935 xml_failure(g_parser); 1936 } 1937 END_TEST 1938 1939 /* Regression test for SF bug #824420. 1940 Checks that an xmlns:prefix attribute set in an attribute's default 1941 value isn't misinterpreted. 1942 */ 1943 START_TEST(test_ns_in_attribute_default_without_namespaces) { 1944 const char *text = "<!DOCTYPE e:element [\n" 1945 " <!ATTLIST e:element\n" 1946 " xmlns:e CDATA 'http://example.org/'>\n" 1947 " ]>\n" 1948 "<e:element/>"; 1949 1950 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1951 == XML_STATUS_ERROR) 1952 xml_failure(g_parser); 1953 } 1954 END_TEST 1955 1956 static const char *long_character_data_text 1957 = "<?xml version='1.0' encoding='iso-8859-1'?><s>" 1958 "012345678901234567890123456789012345678901234567890123456789" 1959 "012345678901234567890123456789012345678901234567890123456789" 1960 "012345678901234567890123456789012345678901234567890123456789" 1961 "012345678901234567890123456789012345678901234567890123456789" 1962 "012345678901234567890123456789012345678901234567890123456789" 1963 "012345678901234567890123456789012345678901234567890123456789" 1964 "012345678901234567890123456789012345678901234567890123456789" 1965 "012345678901234567890123456789012345678901234567890123456789" 1966 "012345678901234567890123456789012345678901234567890123456789" 1967 "012345678901234567890123456789012345678901234567890123456789" 1968 "012345678901234567890123456789012345678901234567890123456789" 1969 "012345678901234567890123456789012345678901234567890123456789" 1970 "012345678901234567890123456789012345678901234567890123456789" 1971 "012345678901234567890123456789012345678901234567890123456789" 1972 "012345678901234567890123456789012345678901234567890123456789" 1973 "012345678901234567890123456789012345678901234567890123456789" 1974 "012345678901234567890123456789012345678901234567890123456789" 1975 "012345678901234567890123456789012345678901234567890123456789" 1976 "012345678901234567890123456789012345678901234567890123456789" 1977 "012345678901234567890123456789012345678901234567890123456789" 1978 "</s>"; 1979 1980 static XML_Bool resumable = XML_FALSE; 1981 1982 static void 1983 clearing_aborting_character_handler(void *userData, const XML_Char *s, 1984 int len) { 1985 UNUSED_P(userData); 1986 UNUSED_P(s); 1987 UNUSED_P(len); 1988 XML_StopParser(g_parser, resumable); 1989 XML_SetCharacterDataHandler(g_parser, NULL); 1990 } 1991 1992 /* Regression test for SF bug #1515266: missing check of stopped 1993 parser in doContext() 'for' loop. */ 1994 START_TEST(test_stop_parser_between_char_data_calls) { 1995 /* The sample data must be big enough that there are two calls to 1996 the character data handler from within the inner "for" loop of 1997 the XML_TOK_DATA_CHARS case in doContent(), and the character 1998 handler must stop the parser and clear the character data 1999 handler. 2000 */ 2001 const char *text = long_character_data_text; 2002 2003 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2004 resumable = XML_FALSE; 2005 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2006 != XML_STATUS_ERROR) 2007 xml_failure(g_parser); 2008 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED) 2009 xml_failure(g_parser); 2010 } 2011 END_TEST 2012 2013 /* Regression test for SF bug #1515266: missing check of stopped 2014 parser in doContext() 'for' loop. */ 2015 START_TEST(test_suspend_parser_between_char_data_calls) { 2016 /* The sample data must be big enough that there are two calls to 2017 the character data handler from within the inner "for" loop of 2018 the XML_TOK_DATA_CHARS case in doContent(), and the character 2019 handler must stop the parser and clear the character data 2020 handler. 2021 */ 2022 const char *text = long_character_data_text; 2023 2024 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2025 resumable = XML_TRUE; 2026 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2027 != XML_STATUS_SUSPENDED) 2028 xml_failure(g_parser); 2029 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 2030 xml_failure(g_parser); 2031 /* Try parsing directly */ 2032 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 2033 != XML_STATUS_ERROR) 2034 fail("Attempt to continue parse while suspended not faulted"); 2035 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 2036 fail("Suspended parse not faulted with correct error"); 2037 } 2038 END_TEST 2039 2040 static XML_Bool abortable = XML_FALSE; 2041 2042 static void 2043 parser_stop_character_handler(void *userData, const XML_Char *s, int len) { 2044 UNUSED_P(userData); 2045 UNUSED_P(s); 2046 UNUSED_P(len); 2047 XML_StopParser(g_parser, resumable); 2048 XML_SetCharacterDataHandler(g_parser, NULL); 2049 if (! resumable) { 2050 /* Check that aborting an aborted parser is faulted */ 2051 if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR) 2052 fail("Aborting aborted parser not faulted"); 2053 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED) 2054 xml_failure(g_parser); 2055 } else if (abortable) { 2056 /* Check that aborting a suspended parser works */ 2057 if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR) 2058 xml_failure(g_parser); 2059 } else { 2060 /* Check that suspending a suspended parser works */ 2061 if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR) 2062 fail("Suspending suspended parser not faulted"); 2063 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 2064 xml_failure(g_parser); 2065 } 2066 } 2067 2068 /* Test repeated calls to XML_StopParser are handled correctly */ 2069 START_TEST(test_repeated_stop_parser_between_char_data_calls) { 2070 const char *text = long_character_data_text; 2071 2072 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler); 2073 resumable = XML_FALSE; 2074 abortable = XML_FALSE; 2075 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2076 != XML_STATUS_ERROR) 2077 fail("Failed to double-stop parser"); 2078 2079 XML_ParserReset(g_parser, NULL); 2080 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler); 2081 resumable = XML_TRUE; 2082 abortable = XML_FALSE; 2083 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2084 != XML_STATUS_SUSPENDED) 2085 fail("Failed to double-suspend parser"); 2086 2087 XML_ParserReset(g_parser, NULL); 2088 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler); 2089 resumable = XML_TRUE; 2090 abortable = XML_TRUE; 2091 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2092 != XML_STATUS_ERROR) 2093 fail("Failed to suspend-abort parser"); 2094 } 2095 END_TEST 2096 2097 START_TEST(test_good_cdata_ascii) { 2098 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>"; 2099 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>"); 2100 2101 CharData storage; 2102 CharData_Init(&storage); 2103 XML_SetUserData(g_parser, &storage); 2104 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2105 /* Add start and end handlers for coverage */ 2106 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler); 2107 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler); 2108 2109 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2110 == XML_STATUS_ERROR) 2111 xml_failure(g_parser); 2112 CharData_CheckXMLChars(&storage, expected); 2113 2114 /* Try again, this time with a default handler */ 2115 XML_ParserReset(g_parser, NULL); 2116 CharData_Init(&storage); 2117 XML_SetUserData(g_parser, &storage); 2118 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2119 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2120 2121 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2122 == XML_STATUS_ERROR) 2123 xml_failure(g_parser); 2124 CharData_CheckXMLChars(&storage, expected); 2125 } 2126 END_TEST 2127 2128 START_TEST(test_good_cdata_utf16) { 2129 /* Test data is: 2130 * <?xml version='1.0' encoding='utf-16'?> 2131 * <a><![CDATA[hello]]></a> 2132 */ 2133 const char text[] 2134 = "\0<\0?\0x\0m\0l\0" 2135 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2136 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2137 "1\0" 2138 "6\0'" 2139 "\0?\0>\0\n" 2140 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>"; 2141 const XML_Char *expected = XCS("hello"); 2142 2143 CharData storage; 2144 CharData_Init(&storage); 2145 XML_SetUserData(g_parser, &storage); 2146 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2147 2148 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2149 == XML_STATUS_ERROR) 2150 xml_failure(g_parser); 2151 CharData_CheckXMLChars(&storage, expected); 2152 } 2153 END_TEST 2154 2155 START_TEST(test_good_cdata_utf16_le) { 2156 /* Test data is: 2157 * <?xml version='1.0' encoding='utf-16'?> 2158 * <a><![CDATA[hello]]></a> 2159 */ 2160 const char text[] 2161 = "<\0?\0x\0m\0l\0" 2162 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2163 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2164 "1\0" 2165 "6\0'" 2166 "\0?\0>\0\n" 2167 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>\0"; 2168 const XML_Char *expected = XCS("hello"); 2169 2170 CharData storage; 2171 CharData_Init(&storage); 2172 XML_SetUserData(g_parser, &storage); 2173 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2174 2175 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2176 == XML_STATUS_ERROR) 2177 xml_failure(g_parser); 2178 CharData_CheckXMLChars(&storage, expected); 2179 } 2180 END_TEST 2181 2182 /* Test UTF16 conversion of a long cdata string */ 2183 2184 /* 16 characters: handy macro to reduce visual clutter */ 2185 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P" 2186 2187 START_TEST(test_long_cdata_utf16) { 2188 /* Test data is: 2189 * <?xlm version='1.0' encoding='utf-16'?> 2190 * <a><![CDATA[ 2191 * ABCDEFGHIJKLMNOP 2192 * ]]></a> 2193 */ 2194 const char text[] 2195 = "\0<\0?\0x\0m\0l\0 " 2196 "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 " 2197 "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>" 2198 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[" 2199 /* 64 characters per line */ 2200 /* clang-format off */ 2201 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2202 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2203 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2204 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2205 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2206 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2207 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2208 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2209 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2210 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2211 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2212 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2213 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2214 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2215 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2216 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2217 A_TO_P_IN_UTF16 2218 /* clang-format on */ 2219 "\0]\0]\0>\0<\0/\0a\0>"; 2220 const XML_Char *expected = 2221 /* clang-format off */ 2222 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2223 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2224 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2225 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2226 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2227 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2228 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2229 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2230 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2231 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2232 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2233 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2234 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2235 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2236 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2237 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2238 XCS("ABCDEFGHIJKLMNOP"); 2239 /* clang-format on */ 2240 CharData storage; 2241 void *buffer; 2242 2243 CharData_Init(&storage); 2244 XML_SetUserData(g_parser, &storage); 2245 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2246 buffer = XML_GetBuffer(g_parser, sizeof(text) - 1); 2247 if (buffer == NULL) 2248 fail("Could not allocate parse buffer"); 2249 assert(buffer != NULL); 2250 memcpy(buffer, text, sizeof(text) - 1); 2251 if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR) 2252 xml_failure(g_parser); 2253 CharData_CheckXMLChars(&storage, expected); 2254 } 2255 END_TEST 2256 2257 /* Test handling of multiple unit UTF-16 characters */ 2258 START_TEST(test_multichar_cdata_utf16) { 2259 /* Test data is: 2260 * <?xml version='1.0' encoding='utf-16'?> 2261 * <a><![CDATA[{MINIM}{CROTCHET}]]></a> 2262 * 2263 * where {MINIM} is U+1d15e (a minim or half-note) 2264 * UTF-16: 0xd834 0xdd5e 2265 * UTF-8: 0xf0 0x9d 0x85 0x9e 2266 * and {CROTCHET} is U+1d15f (a crotchet or quarter-note) 2267 * UTF-16: 0xd834 0xdd5f 2268 * UTF-8: 0xf0 0x9d 0x85 0x9f 2269 */ 2270 const char text[] = "\0<\0?\0x\0m\0l\0" 2271 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2272 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2273 "1\0" 2274 "6\0'" 2275 "\0?\0>\0\n" 2276 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[" 2277 "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f" 2278 "\0]\0]\0>\0<\0/\0a\0>"; 2279 #ifdef XML_UNICODE 2280 const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f"); 2281 #else 2282 const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f"); 2283 #endif 2284 CharData storage; 2285 2286 CharData_Init(&storage); 2287 XML_SetUserData(g_parser, &storage); 2288 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2289 2290 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2291 == XML_STATUS_ERROR) 2292 xml_failure(g_parser); 2293 CharData_CheckXMLChars(&storage, expected); 2294 } 2295 END_TEST 2296 2297 /* Test that an element name with a UTF-16 surrogate pair is rejected */ 2298 START_TEST(test_utf16_bad_surrogate_pair) { 2299 /* Test data is: 2300 * <?xml version='1.0' encoding='utf-16'?> 2301 * <a><![CDATA[{BADLINB}]]></a> 2302 * 2303 * where {BADLINB} is U+10000 (the first Linear B character) 2304 * with the UTF-16 surrogate pair in the wrong order, i.e. 2305 * 0xdc00 0xd800 2306 */ 2307 const char text[] = "\0<\0?\0x\0m\0l\0" 2308 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2309 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2310 "1\0" 2311 "6\0'" 2312 "\0?\0>\0\n" 2313 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[" 2314 "\xdc\x00\xd8\x00" 2315 "\0]\0]\0>\0<\0/\0a\0>"; 2316 2317 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2318 != XML_STATUS_ERROR) 2319 fail("Reversed UTF-16 surrogate pair not faulted"); 2320 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 2321 xml_failure(g_parser); 2322 } 2323 END_TEST 2324 2325 START_TEST(test_bad_cdata) { 2326 struct CaseData { 2327 const char *text; 2328 enum XML_Error expectedError; 2329 }; 2330 2331 struct CaseData cases[] 2332 = {{"<a><", XML_ERROR_UNCLOSED_TOKEN}, 2333 {"<a><!", XML_ERROR_UNCLOSED_TOKEN}, 2334 {"<a><![", XML_ERROR_UNCLOSED_TOKEN}, 2335 {"<a><![C", XML_ERROR_UNCLOSED_TOKEN}, 2336 {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN}, 2337 {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN}, 2338 {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN}, 2339 {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN}, 2340 2341 {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2342 {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2343 {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2344 2345 {"<a><!<a/>", XML_ERROR_INVALID_TOKEN}, 2346 {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */ 2347 {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */ 2348 {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN}, 2349 {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN}, 2350 {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN}, 2351 {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN}, 2352 2353 {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2354 {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2355 {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}}; 2356 2357 size_t i = 0; 2358 for (; i < sizeof(cases) / sizeof(struct CaseData); i++) { 2359 const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES( 2360 g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE); 2361 const enum XML_Error actualError = XML_GetErrorCode(g_parser); 2362 2363 assert(actualStatus == XML_STATUS_ERROR); 2364 2365 if (actualError != cases[i].expectedError) { 2366 char message[100]; 2367 sprintf(message, 2368 "Expected error %d but got error %d for case %u: \"%s\"\n", 2369 cases[i].expectedError, actualError, (unsigned int)i + 1, 2370 cases[i].text); 2371 fail(message); 2372 } 2373 2374 XML_ParserReset(g_parser, NULL); 2375 } 2376 } 2377 END_TEST 2378 2379 /* Test failures in UTF-16 CDATA */ 2380 START_TEST(test_bad_cdata_utf16) { 2381 struct CaseData { 2382 size_t text_bytes; 2383 const char *text; 2384 enum XML_Error expected_error; 2385 }; 2386 2387 const char prolog[] = "\0<\0?\0x\0m\0l\0" 2388 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2389 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2390 "1\0" 2391 "6\0'" 2392 "\0?\0>\0\n" 2393 "\0<\0a\0>"; 2394 struct CaseData cases[] = { 2395 {1, "\0", XML_ERROR_UNCLOSED_TOKEN}, 2396 {2, "\0<", XML_ERROR_UNCLOSED_TOKEN}, 2397 {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN}, 2398 {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN}, 2399 {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN}, 2400 {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN}, 2401 {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN}, 2402 {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN}, 2403 {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN}, 2404 {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN}, 2405 {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN}, 2406 {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN}, 2407 {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN}, 2408 {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN}, 2409 {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN}, 2410 {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN}, 2411 {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN}, 2412 {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2413 {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2414 {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2415 /* Now add a four-byte UTF-16 character */ 2416 {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8", 2417 XML_ERROR_UNCLOSED_CDATA_SECTION}, 2418 {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR}, 2419 {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd", 2420 XML_ERROR_PARTIAL_CHAR}, 2421 {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e", 2422 XML_ERROR_UNCLOSED_CDATA_SECTION}}; 2423 size_t i; 2424 2425 for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) { 2426 enum XML_Status actual_status; 2427 enum XML_Error actual_error; 2428 2429 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1, 2430 XML_FALSE) 2431 == XML_STATUS_ERROR) 2432 xml_failure(g_parser); 2433 actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text, 2434 (int)cases[i].text_bytes, XML_TRUE); 2435 assert(actual_status == XML_STATUS_ERROR); 2436 actual_error = XML_GetErrorCode(g_parser); 2437 if (actual_error != cases[i].expected_error) { 2438 char message[1024]; 2439 2440 sprintf(message, 2441 "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR 2442 ") for case %lu\n", 2443 cases[i].expected_error, XML_ErrorString(cases[i].expected_error), 2444 actual_error, XML_ErrorString(actual_error), 2445 (long unsigned)(i + 1)); 2446 fail(message); 2447 } 2448 XML_ParserReset(g_parser, NULL); 2449 } 2450 } 2451 END_TEST 2452 2453 static const char *long_cdata_text 2454 = "<s><![CDATA[" 2455 "012345678901234567890123456789012345678901234567890123456789" 2456 "012345678901234567890123456789012345678901234567890123456789" 2457 "012345678901234567890123456789012345678901234567890123456789" 2458 "012345678901234567890123456789012345678901234567890123456789" 2459 "012345678901234567890123456789012345678901234567890123456789" 2460 "012345678901234567890123456789012345678901234567890123456789" 2461 "012345678901234567890123456789012345678901234567890123456789" 2462 "012345678901234567890123456789012345678901234567890123456789" 2463 "012345678901234567890123456789012345678901234567890123456789" 2464 "012345678901234567890123456789012345678901234567890123456789" 2465 "012345678901234567890123456789012345678901234567890123456789" 2466 "012345678901234567890123456789012345678901234567890123456789" 2467 "012345678901234567890123456789012345678901234567890123456789" 2468 "012345678901234567890123456789012345678901234567890123456789" 2469 "012345678901234567890123456789012345678901234567890123456789" 2470 "012345678901234567890123456789012345678901234567890123456789" 2471 "012345678901234567890123456789012345678901234567890123456789" 2472 "012345678901234567890123456789012345678901234567890123456789" 2473 "012345678901234567890123456789012345678901234567890123456789" 2474 "012345678901234567890123456789012345678901234567890123456789" 2475 "]]></s>"; 2476 2477 /* Test stopping the parser in cdata handler */ 2478 START_TEST(test_stop_parser_between_cdata_calls) { 2479 const char *text = long_cdata_text; 2480 2481 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2482 resumable = XML_FALSE; 2483 expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler"); 2484 } 2485 END_TEST 2486 2487 /* Test suspending the parser in cdata handler */ 2488 START_TEST(test_suspend_parser_between_cdata_calls) { 2489 const char *text = long_cdata_text; 2490 enum XML_Status result; 2491 2492 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2493 resumable = XML_TRUE; 2494 result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 2495 if (result != XML_STATUS_SUSPENDED) { 2496 if (result == XML_STATUS_ERROR) 2497 xml_failure(g_parser); 2498 fail("Parse not suspended in CDATA handler"); 2499 } 2500 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 2501 xml_failure(g_parser); 2502 } 2503 END_TEST 2504 2505 /* Test memory allocation functions */ 2506 START_TEST(test_memory_allocation) { 2507 char *buffer = (char *)XML_MemMalloc(g_parser, 256); 2508 char *p; 2509 2510 if (buffer == NULL) { 2511 fail("Allocation failed"); 2512 } else { 2513 /* Try writing to memory; some OSes try to cheat! */ 2514 buffer[0] = 'T'; 2515 buffer[1] = 'E'; 2516 buffer[2] = 'S'; 2517 buffer[3] = 'T'; 2518 buffer[4] = '\0'; 2519 if (strcmp(buffer, "TEST") != 0) { 2520 fail("Memory not writable"); 2521 } else { 2522 p = (char *)XML_MemRealloc(g_parser, buffer, 512); 2523 if (p == NULL) { 2524 fail("Reallocation failed"); 2525 } else { 2526 /* Write again, just to be sure */ 2527 buffer = p; 2528 buffer[0] = 'V'; 2529 if (strcmp(buffer, "VEST") != 0) { 2530 fail("Reallocated memory not writable"); 2531 } 2532 } 2533 } 2534 XML_MemFree(g_parser, buffer); 2535 } 2536 } 2537 END_TEST 2538 2539 static void XMLCALL 2540 record_default_handler(void *userData, const XML_Char *s, int len) { 2541 UNUSED_P(s); 2542 UNUSED_P(len); 2543 CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1); 2544 } 2545 2546 static void XMLCALL 2547 record_cdata_handler(void *userData, const XML_Char *s, int len) { 2548 UNUSED_P(s); 2549 UNUSED_P(len); 2550 CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1); 2551 XML_DefaultCurrent(g_parser); 2552 } 2553 2554 static void XMLCALL 2555 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) { 2556 UNUSED_P(s); 2557 UNUSED_P(len); 2558 CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1); 2559 } 2560 2561 static void XMLCALL 2562 record_skip_handler(void *userData, const XML_Char *entityName, 2563 int is_parameter_entity) { 2564 UNUSED_P(entityName); 2565 CharData_AppendXMLChars((CharData *)userData, 2566 is_parameter_entity ? XCS("E") : XCS("e"), 1); 2567 } 2568 2569 /* Test XML_DefaultCurrent() passes handling on correctly */ 2570 START_TEST(test_default_current) { 2571 const char *text = "<doc>hell]</doc>"; 2572 const char *entity_text = "<!DOCTYPE doc [\n" 2573 "<!ENTITY entity '%'>\n" 2574 "]>\n" 2575 "<doc>&entity;</doc>"; 2576 CharData storage; 2577 2578 XML_SetDefaultHandler(g_parser, record_default_handler); 2579 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2580 CharData_Init(&storage); 2581 XML_SetUserData(g_parser, &storage); 2582 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2583 == XML_STATUS_ERROR) 2584 xml_failure(g_parser); 2585 CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD")); 2586 2587 /* Again, without the defaulting */ 2588 XML_ParserReset(g_parser, NULL); 2589 XML_SetDefaultHandler(g_parser, record_default_handler); 2590 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler); 2591 CharData_Init(&storage); 2592 XML_SetUserData(g_parser, &storage); 2593 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2594 == XML_STATUS_ERROR) 2595 xml_failure(g_parser); 2596 CharData_CheckXMLChars(&storage, XCS("DcccccD")); 2597 2598 /* Now with an internal entity to complicate matters */ 2599 XML_ParserReset(g_parser, NULL); 2600 XML_SetDefaultHandler(g_parser, record_default_handler); 2601 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2602 CharData_Init(&storage); 2603 XML_SetUserData(g_parser, &storage); 2604 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2605 XML_TRUE) 2606 == XML_STATUS_ERROR) 2607 xml_failure(g_parser); 2608 /* The default handler suppresses the entity */ 2609 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD")); 2610 2611 /* Again, with a skip handler */ 2612 XML_ParserReset(g_parser, NULL); 2613 XML_SetDefaultHandler(g_parser, record_default_handler); 2614 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2615 XML_SetSkippedEntityHandler(g_parser, record_skip_handler); 2616 CharData_Init(&storage); 2617 XML_SetUserData(g_parser, &storage); 2618 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2619 XML_TRUE) 2620 == XML_STATUS_ERROR) 2621 xml_failure(g_parser); 2622 /* The default handler suppresses the entity */ 2623 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD")); 2624 2625 /* This time, allow the entity through */ 2626 XML_ParserReset(g_parser, NULL); 2627 XML_SetDefaultHandlerExpand(g_parser, record_default_handler); 2628 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2629 CharData_Init(&storage); 2630 XML_SetUserData(g_parser, &storage); 2631 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2632 XML_TRUE) 2633 == XML_STATUS_ERROR) 2634 xml_failure(g_parser); 2635 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD")); 2636 2637 /* Finally, without passing the cdata to the default handler */ 2638 XML_ParserReset(g_parser, NULL); 2639 XML_SetDefaultHandlerExpand(g_parser, record_default_handler); 2640 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler); 2641 CharData_Init(&storage); 2642 XML_SetUserData(g_parser, &storage); 2643 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2644 XML_TRUE) 2645 == XML_STATUS_ERROR) 2646 xml_failure(g_parser); 2647 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD")); 2648 } 2649 END_TEST 2650 2651 /* Test DTD element parsing code paths */ 2652 START_TEST(test_dtd_elements) { 2653 const char *text = "<!DOCTYPE doc [\n" 2654 "<!ELEMENT doc (chapter)>\n" 2655 "<!ELEMENT chapter (#PCDATA)>\n" 2656 "]>\n" 2657 "<doc><chapter>Wombats are go</chapter></doc>"; 2658 2659 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 2660 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2661 == XML_STATUS_ERROR) 2662 xml_failure(g_parser); 2663 } 2664 END_TEST 2665 2666 static void XMLCALL 2667 element_decl_check_model(void *userData, const XML_Char *name, 2668 XML_Content *model) { 2669 UNUSED_P(userData); 2670 uint32_t errorFlags = 0; 2671 2672 /* Expected model array structure is this: 2673 * [0] (type 6, quant 0) 2674 * [1] (type 5, quant 0) 2675 * [3] (type 4, quant 0, name "bar") 2676 * [4] (type 4, quant 0, name "foo") 2677 * [5] (type 4, quant 3, name "xyz") 2678 * [2] (type 4, quant 2, name "zebra") 2679 */ 2680 errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0)); 2681 errorFlags |= ((model != NULL) ? 0 : (1u << 1)); 2682 2683 errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2)); 2684 errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3)); 2685 errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4)); 2686 errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5)); 2687 errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6)); 2688 2689 errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7)); 2690 errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8)); 2691 errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9)); 2692 errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10)); 2693 errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11)); 2694 2695 errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12)); 2696 errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13)); 2697 errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14)); 2698 errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15)); 2699 errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16)); 2700 2701 errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17)); 2702 errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18)); 2703 errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19)); 2704 errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20)); 2705 errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21)); 2706 2707 errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22)); 2708 errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23)); 2709 errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24)); 2710 errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25)); 2711 errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26)); 2712 2713 errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27)); 2714 errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28)); 2715 errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29)); 2716 errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30)); 2717 errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31)); 2718 2719 XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags); 2720 XML_FreeContentModel(g_parser, model); 2721 } 2722 2723 START_TEST(test_dtd_elements_nesting) { 2724 // Payload inspired by a test in Perl's XML::Parser 2725 const char *text = "<!DOCTYPE foo [\n" 2726 "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n" 2727 "]>\n" 2728 "<foo/>"; 2729 2730 XML_SetUserData(g_parser, (void *)(uintptr_t)-1); 2731 2732 XML_SetElementDeclHandler(g_parser, element_decl_check_model); 2733 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 2734 == XML_STATUS_ERROR) 2735 xml_failure(g_parser); 2736 2737 if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0) 2738 fail("Element declaration model regression detected"); 2739 } 2740 END_TEST 2741 2742 /* Test foreign DTD handling */ 2743 START_TEST(test_set_foreign_dtd) { 2744 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"; 2745 const char *text2 = "<doc>&entity;</doc>"; 2746 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2747 2748 /* Check hash salt is passed through too */ 2749 XML_SetHashSalt(g_parser, 0x12345678); 2750 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2751 XML_SetUserData(g_parser, &test_data); 2752 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2753 /* Add a default handler to exercise more code paths */ 2754 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2755 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2756 fail("Could not set foreign DTD"); 2757 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 2758 == XML_STATUS_ERROR) 2759 xml_failure(g_parser); 2760 2761 /* Ensure that trying to set the DTD after parsing has started 2762 * is faulted, even if it's the same setting. 2763 */ 2764 if (XML_UseForeignDTD(g_parser, XML_TRUE) 2765 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING) 2766 fail("Failed to reject late foreign DTD setting"); 2767 /* Ditto for the hash salt */ 2768 if (XML_SetHashSalt(g_parser, 0x23456789)) 2769 fail("Failed to reject late hash salt change"); 2770 2771 /* Now finish the parse */ 2772 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 2773 == XML_STATUS_ERROR) 2774 xml_failure(g_parser); 2775 } 2776 END_TEST 2777 2778 /* Test foreign DTD handling with a failing NotStandalone handler */ 2779 START_TEST(test_foreign_dtd_not_standalone) { 2780 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2781 "<doc>&entity;</doc>"; 2782 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2783 2784 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2785 XML_SetUserData(g_parser, &test_data); 2786 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2787 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler); 2788 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2789 fail("Could not set foreign DTD"); 2790 expect_failure(text, XML_ERROR_NOT_STANDALONE, 2791 "NotStandalonehandler failed to reject"); 2792 } 2793 END_TEST 2794 2795 /* Test invalid character in a foreign DTD is faulted */ 2796 START_TEST(test_invalid_foreign_dtd) { 2797 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2798 "<doc>&entity;</doc>"; 2799 ExtFaults test_data 2800 = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN}; 2801 2802 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2803 XML_SetUserData(g_parser, &test_data); 2804 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 2805 XML_UseForeignDTD(g_parser, XML_TRUE); 2806 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 2807 "Bad DTD should not have been accepted"); 2808 } 2809 END_TEST 2810 2811 /* Test foreign DTD use with a doctype */ 2812 START_TEST(test_foreign_dtd_with_doctype) { 2813 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 2814 "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n"; 2815 const char *text2 = "<doc>&entity;</doc>"; 2816 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2817 2818 /* Check hash salt is passed through too */ 2819 XML_SetHashSalt(g_parser, 0x12345678); 2820 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2821 XML_SetUserData(g_parser, &test_data); 2822 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2823 /* Add a default handler to exercise more code paths */ 2824 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2825 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2826 fail("Could not set foreign DTD"); 2827 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 2828 == XML_STATUS_ERROR) 2829 xml_failure(g_parser); 2830 2831 /* Ensure that trying to set the DTD after parsing has started 2832 * is faulted, even if it's the same setting. 2833 */ 2834 if (XML_UseForeignDTD(g_parser, XML_TRUE) 2835 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING) 2836 fail("Failed to reject late foreign DTD setting"); 2837 /* Ditto for the hash salt */ 2838 if (XML_SetHashSalt(g_parser, 0x23456789)) 2839 fail("Failed to reject late hash salt change"); 2840 2841 /* Now finish the parse */ 2842 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 2843 == XML_STATUS_ERROR) 2844 xml_failure(g_parser); 2845 } 2846 END_TEST 2847 2848 /* Test XML_UseForeignDTD with no external subset present */ 2849 static int XMLCALL 2850 external_entity_null_loader(XML_Parser parser, const XML_Char *context, 2851 const XML_Char *base, const XML_Char *systemId, 2852 const XML_Char *publicId) { 2853 UNUSED_P(parser); 2854 UNUSED_P(context); 2855 UNUSED_P(base); 2856 UNUSED_P(systemId); 2857 UNUSED_P(publicId); 2858 return XML_STATUS_OK; 2859 } 2860 2861 START_TEST(test_foreign_dtd_without_external_subset) { 2862 const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n" 2863 "<doc>&foo;</doc>"; 2864 2865 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2866 XML_SetUserData(g_parser, NULL); 2867 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 2868 XML_UseForeignDTD(g_parser, XML_TRUE); 2869 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2870 == XML_STATUS_ERROR) 2871 xml_failure(g_parser); 2872 } 2873 END_TEST 2874 2875 START_TEST(test_empty_foreign_dtd) { 2876 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2877 "<doc>&entity;</doc>"; 2878 2879 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2880 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 2881 XML_UseForeignDTD(g_parser, XML_TRUE); 2882 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 2883 "Undefined entity not faulted"); 2884 } 2885 END_TEST 2886 2887 /* Test XML Base is set and unset appropriately */ 2888 START_TEST(test_set_base) { 2889 const XML_Char *old_base; 2890 const XML_Char *new_base = XCS("/local/file/name.xml"); 2891 2892 old_base = XML_GetBase(g_parser); 2893 if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK) 2894 fail("Unable to set base"); 2895 if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0) 2896 fail("Base setting not correct"); 2897 if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK) 2898 fail("Unable to NULL base"); 2899 if (XML_GetBase(g_parser) != NULL) 2900 fail("Base setting not nulled"); 2901 XML_SetBase(g_parser, old_base); 2902 } 2903 END_TEST 2904 2905 /* Test attribute counts, indexing, etc */ 2906 typedef struct attrInfo { 2907 const XML_Char *name; 2908 const XML_Char *value; 2909 } AttrInfo; 2910 2911 typedef struct elementInfo { 2912 const XML_Char *name; 2913 int attr_count; 2914 const XML_Char *id_name; 2915 AttrInfo *attributes; 2916 } ElementInfo; 2917 2918 static void XMLCALL 2919 counting_start_element_handler(void *userData, const XML_Char *name, 2920 const XML_Char **atts) { 2921 ElementInfo *info = (ElementInfo *)userData; 2922 AttrInfo *attr; 2923 int count, id, i; 2924 2925 while (info->name != NULL) { 2926 if (! xcstrcmp(name, info->name)) 2927 break; 2928 info++; 2929 } 2930 if (info->name == NULL) 2931 fail("Element not recognised"); 2932 /* The attribute count is twice what you might expect. It is a 2933 * count of items in atts, an array which contains alternating 2934 * attribute names and attribute values. For the naive user this 2935 * is possibly a little unexpected, but it is what the 2936 * documentation in expat.h tells us to expect. 2937 */ 2938 count = XML_GetSpecifiedAttributeCount(g_parser); 2939 if (info->attr_count * 2 != count) { 2940 fail("Not got expected attribute count"); 2941 return; 2942 } 2943 id = XML_GetIdAttributeIndex(g_parser); 2944 if (id == -1 && info->id_name != NULL) { 2945 fail("ID not present"); 2946 return; 2947 } 2948 if (id != -1 && xcstrcmp(atts[id], info->id_name)) { 2949 fail("ID does not have the correct name"); 2950 return; 2951 } 2952 for (i = 0; i < info->attr_count; i++) { 2953 attr = info->attributes; 2954 while (attr->name != NULL) { 2955 if (! xcstrcmp(atts[0], attr->name)) 2956 break; 2957 attr++; 2958 } 2959 if (attr->name == NULL) { 2960 fail("Attribute not recognised"); 2961 return; 2962 } 2963 if (xcstrcmp(atts[1], attr->value)) { 2964 fail("Attribute has wrong value"); 2965 return; 2966 } 2967 /* Remember, two entries in atts per attribute (see above) */ 2968 atts += 2; 2969 } 2970 } 2971 2972 START_TEST(test_attributes) { 2973 const char *text = "<!DOCTYPE doc [\n" 2974 "<!ELEMENT doc (tag)>\n" 2975 "<!ATTLIST doc id ID #REQUIRED>\n" 2976 "]>" 2977 "<doc a='1' id='one' b='2'>" 2978 "<tag c='3'/>" 2979 "</doc>"; 2980 AttrInfo doc_info[] = {{XCS("a"), XCS("1")}, 2981 {XCS("b"), XCS("2")}, 2982 {XCS("id"), XCS("one")}, 2983 {NULL, NULL}}; 2984 AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}}; 2985 ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL}, 2986 {XCS("tag"), 1, NULL, NULL}, 2987 {NULL, 0, NULL, NULL}}; 2988 info[0].attributes = doc_info; 2989 info[1].attributes = tag_info; 2990 2991 XML_SetStartElementHandler(g_parser, counting_start_element_handler); 2992 XML_SetUserData(g_parser, info); 2993 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2994 == XML_STATUS_ERROR) 2995 xml_failure(g_parser); 2996 } 2997 END_TEST 2998 2999 /* Test reset works correctly in the middle of processing an internal 3000 * entity. Exercises some obscure code in XML_ParserReset(). 3001 */ 3002 START_TEST(test_reset_in_entity) { 3003 const char *text = "<!DOCTYPE doc [\n" 3004 "<!ENTITY wombat 'wom'>\n" 3005 "<!ENTITY entity 'hi &wom; there'>\n" 3006 "]>\n" 3007 "<doc>&entity;</doc>"; 3008 XML_ParsingStatus status; 3009 3010 resumable = XML_TRUE; 3011 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3012 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3013 == XML_STATUS_ERROR) 3014 xml_failure(g_parser); 3015 XML_GetParsingStatus(g_parser, &status); 3016 if (status.parsing != XML_SUSPENDED) 3017 fail("Parsing status not SUSPENDED"); 3018 XML_ParserReset(g_parser, NULL); 3019 XML_GetParsingStatus(g_parser, &status); 3020 if (status.parsing != XML_INITIALIZED) 3021 fail("Parsing status doesn't reset to INITIALIZED"); 3022 } 3023 END_TEST 3024 3025 /* Test that resume correctly passes through parse errors */ 3026 START_TEST(test_resume_invalid_parse) { 3027 const char *text = "<doc>Hello</doc"; /* Missing closing wedge */ 3028 3029 resumable = XML_TRUE; 3030 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3031 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 3032 == XML_STATUS_ERROR) 3033 xml_failure(g_parser); 3034 if (XML_ResumeParser(g_parser) == XML_STATUS_OK) 3035 fail("Resumed invalid parse not faulted"); 3036 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN) 3037 fail("Invalid parse not correctly faulted"); 3038 } 3039 END_TEST 3040 3041 /* Test that re-suspended parses are correctly passed through */ 3042 START_TEST(test_resume_resuspended) { 3043 const char *text = "<doc>Hello<meep/>world</doc>"; 3044 3045 resumable = XML_TRUE; 3046 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3047 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 3048 == XML_STATUS_ERROR) 3049 xml_failure(g_parser); 3050 resumable = XML_TRUE; 3051 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3052 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED) 3053 fail("Resumption not suspended"); 3054 /* This one should succeed and finish up */ 3055 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 3056 xml_failure(g_parser); 3057 } 3058 END_TEST 3059 3060 /* Test that CDATA shows up correctly through a default handler */ 3061 START_TEST(test_cdata_default) { 3062 const char *text = "<doc><![CDATA[Hello\nworld]]></doc>"; 3063 const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>"); 3064 CharData storage; 3065 3066 CharData_Init(&storage); 3067 XML_SetUserData(g_parser, &storage); 3068 XML_SetDefaultHandler(g_parser, accumulate_characters); 3069 3070 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3071 == XML_STATUS_ERROR) 3072 xml_failure(g_parser); 3073 CharData_CheckXMLChars(&storage, expected); 3074 } 3075 END_TEST 3076 3077 /* Test resetting a subordinate parser does exactly nothing */ 3078 static int XMLCALL 3079 external_entity_resetter(XML_Parser parser, const XML_Char *context, 3080 const XML_Char *base, const XML_Char *systemId, 3081 const XML_Char *publicId) { 3082 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3083 XML_Parser ext_parser; 3084 XML_ParsingStatus status; 3085 3086 UNUSED_P(base); 3087 UNUSED_P(systemId); 3088 UNUSED_P(publicId); 3089 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3090 if (ext_parser == NULL) 3091 fail("Could not create external entity parser"); 3092 XML_GetParsingStatus(ext_parser, &status); 3093 if (status.parsing != XML_INITIALIZED) { 3094 fail("Parsing status is not INITIALIZED"); 3095 return XML_STATUS_ERROR; 3096 } 3097 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3098 == XML_STATUS_ERROR) { 3099 xml_failure(parser); 3100 return XML_STATUS_ERROR; 3101 } 3102 XML_GetParsingStatus(ext_parser, &status); 3103 if (status.parsing != XML_FINISHED) { 3104 fail("Parsing status is not FINISHED"); 3105 return XML_STATUS_ERROR; 3106 } 3107 /* Check we can't parse here */ 3108 if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE) 3109 != XML_STATUS_ERROR) 3110 fail("Parsing when finished not faulted"); 3111 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED) 3112 fail("Parsing when finished faulted with wrong code"); 3113 XML_ParserReset(ext_parser, NULL); 3114 XML_GetParsingStatus(ext_parser, &status); 3115 if (status.parsing != XML_FINISHED) { 3116 fail("Parsing status not still FINISHED"); 3117 return XML_STATUS_ERROR; 3118 } 3119 XML_ParserFree(ext_parser); 3120 return XML_STATUS_OK; 3121 } 3122 3123 START_TEST(test_subordinate_reset) { 3124 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3125 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3126 "<doc>&entity;</doc>"; 3127 3128 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3129 XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter); 3130 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3131 == XML_STATUS_ERROR) 3132 xml_failure(g_parser); 3133 } 3134 END_TEST 3135 3136 /* Test suspending a subordinate parser */ 3137 3138 static void XMLCALL 3139 entity_suspending_decl_handler(void *userData, const XML_Char *name, 3140 XML_Content *model) { 3141 XML_Parser ext_parser = (XML_Parser)userData; 3142 3143 UNUSED_P(name); 3144 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR) 3145 fail("Attempting to suspend a subordinate parser not faulted"); 3146 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE) 3147 fail("Suspending subordinate parser get wrong code"); 3148 XML_SetElementDeclHandler(ext_parser, NULL); 3149 XML_FreeContentModel(g_parser, model); 3150 } 3151 3152 static int XMLCALL 3153 external_entity_suspender(XML_Parser parser, const XML_Char *context, 3154 const XML_Char *base, const XML_Char *systemId, 3155 const XML_Char *publicId) { 3156 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3157 XML_Parser ext_parser; 3158 3159 UNUSED_P(base); 3160 UNUSED_P(systemId); 3161 UNUSED_P(publicId); 3162 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3163 if (ext_parser == NULL) 3164 fail("Could not create external entity parser"); 3165 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler); 3166 XML_SetUserData(ext_parser, ext_parser); 3167 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3168 == XML_STATUS_ERROR) { 3169 xml_failure(ext_parser); 3170 return XML_STATUS_ERROR; 3171 } 3172 XML_ParserFree(ext_parser); 3173 return XML_STATUS_OK; 3174 } 3175 3176 START_TEST(test_subordinate_suspend) { 3177 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3178 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3179 "<doc>&entity;</doc>"; 3180 3181 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3182 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender); 3183 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3184 == XML_STATUS_ERROR) 3185 xml_failure(g_parser); 3186 } 3187 END_TEST 3188 3189 /* Test suspending a subordinate parser from an XML declaration */ 3190 /* Increases code coverage of the tests */ 3191 static void XMLCALL 3192 entity_suspending_xdecl_handler(void *userData, const XML_Char *version, 3193 const XML_Char *encoding, int standalone) { 3194 XML_Parser ext_parser = (XML_Parser)userData; 3195 3196 UNUSED_P(version); 3197 UNUSED_P(encoding); 3198 UNUSED_P(standalone); 3199 XML_StopParser(ext_parser, resumable); 3200 XML_SetXmlDeclHandler(ext_parser, NULL); 3201 } 3202 3203 static int XMLCALL 3204 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context, 3205 const XML_Char *base, const XML_Char *systemId, 3206 const XML_Char *publicId) { 3207 const char *text = "<?xml version='1.0' encoding='us-ascii'?>"; 3208 XML_Parser ext_parser; 3209 XML_ParsingStatus status; 3210 enum XML_Status rc; 3211 3212 UNUSED_P(base); 3213 UNUSED_P(systemId); 3214 UNUSED_P(publicId); 3215 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3216 if (ext_parser == NULL) 3217 fail("Could not create external entity parser"); 3218 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 3219 XML_SetUserData(ext_parser, ext_parser); 3220 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 3221 XML_GetParsingStatus(ext_parser, &status); 3222 if (resumable) { 3223 if (rc == XML_STATUS_ERROR) 3224 xml_failure(ext_parser); 3225 if (status.parsing != XML_SUSPENDED) 3226 fail("Ext Parsing status not SUSPENDED"); 3227 } else { 3228 if (rc != XML_STATUS_ERROR) 3229 fail("Ext parsing not aborted"); 3230 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED) 3231 xml_failure(ext_parser); 3232 if (status.parsing != XML_FINISHED) 3233 fail("Ext Parsing status not FINISHED"); 3234 } 3235 3236 XML_ParserFree(ext_parser); 3237 return XML_STATUS_OK; 3238 } 3239 3240 START_TEST(test_subordinate_xdecl_suspend) { 3241 const char *text 3242 = "<!DOCTYPE doc [\n" 3243 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n" 3244 "]>\n" 3245 "<doc>&entity;</doc>"; 3246 3247 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3248 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl); 3249 resumable = XML_TRUE; 3250 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3251 == XML_STATUS_ERROR) 3252 xml_failure(g_parser); 3253 } 3254 END_TEST 3255 3256 START_TEST(test_subordinate_xdecl_abort) { 3257 const char *text 3258 = "<!DOCTYPE doc [\n" 3259 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n" 3260 "]>\n" 3261 "<doc>&entity;</doc>"; 3262 3263 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3264 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl); 3265 resumable = XML_FALSE; 3266 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3267 == XML_STATUS_ERROR) 3268 xml_failure(g_parser); 3269 } 3270 END_TEST 3271 3272 /* Test external entity fault handling with suspension */ 3273 static int XMLCALL 3274 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context, 3275 const XML_Char *base, 3276 const XML_Char *systemId, 3277 const XML_Char *publicId) { 3278 XML_Parser ext_parser; 3279 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 3280 void *buffer; 3281 int parse_len = (int)strlen(fault->parse_text); 3282 3283 UNUSED_P(base); 3284 UNUSED_P(systemId); 3285 UNUSED_P(publicId); 3286 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3287 if (ext_parser == NULL) 3288 fail("Could not create external entity parser"); 3289 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 3290 XML_SetUserData(ext_parser, ext_parser); 3291 resumable = XML_TRUE; 3292 buffer = XML_GetBuffer(ext_parser, parse_len); 3293 if (buffer == NULL) 3294 fail("Could not allocate parse buffer"); 3295 assert(buffer != NULL); 3296 memcpy(buffer, fault->parse_text, parse_len); 3297 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED) 3298 fail("XML declaration did not suspend"); 3299 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK) 3300 xml_failure(ext_parser); 3301 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR) 3302 fail(fault->fail_text); 3303 if (XML_GetErrorCode(ext_parser) != fault->error) 3304 xml_failure(ext_parser); 3305 3306 XML_ParserFree(ext_parser); 3307 return XML_STATUS_ERROR; 3308 } 3309 3310 START_TEST(test_ext_entity_invalid_suspended_parse) { 3311 const char *text = "<!DOCTYPE doc [\n" 3312 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3313 "]>\n" 3314 "<doc>&en;</doc>"; 3315 ExtFaults faults[] 3316 = {{"<?xml version='1.0' encoding='us-ascii'?><", 3317 "Incomplete element declaration not faulted", NULL, 3318 XML_ERROR_UNCLOSED_TOKEN}, 3319 {/* First two bytes of a three-byte char */ 3320 "<?xml version='1.0' encoding='utf-8'?>\xe2\x82", 3321 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR}, 3322 {NULL, NULL, NULL, XML_ERROR_NONE}}; 3323 ExtFaults *fault; 3324 3325 for (fault = &faults[0]; fault->parse_text != NULL; fault++) { 3326 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3327 XML_SetExternalEntityRefHandler(g_parser, 3328 external_entity_suspending_faulter); 3329 XML_SetUserData(g_parser, fault); 3330 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 3331 "Parser did not report external entity error"); 3332 XML_ParserReset(g_parser, NULL); 3333 } 3334 } 3335 END_TEST 3336 3337 /* Test setting an explicit encoding */ 3338 START_TEST(test_explicit_encoding) { 3339 const char *text1 = "<doc>Hello "; 3340 const char *text2 = " World</doc>"; 3341 3342 /* Just check that we can set the encoding to NULL before starting */ 3343 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK) 3344 fail("Failed to initialise encoding to NULL"); 3345 /* Say we are UTF-8 */ 3346 if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK) 3347 fail("Failed to set explicit encoding"); 3348 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 3349 == XML_STATUS_ERROR) 3350 xml_failure(g_parser); 3351 /* Try to switch encodings mid-parse */ 3352 if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR) 3353 fail("Allowed encoding change"); 3354 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 3355 == XML_STATUS_ERROR) 3356 xml_failure(g_parser); 3357 /* Try now the parse is over */ 3358 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK) 3359 fail("Failed to unset encoding"); 3360 } 3361 END_TEST 3362 3363 /* Test handling of trailing CR (rather than newline) */ 3364 static void XMLCALL 3365 cr_cdata_handler(void *userData, const XML_Char *s, int len) { 3366 int *pfound = (int *)userData; 3367 3368 /* Internal processing turns the CR into a newline for the 3369 * character data handler, but not for the default handler 3370 */ 3371 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r'))) 3372 *pfound = 1; 3373 } 3374 3375 START_TEST(test_trailing_cr) { 3376 const char *text = "<doc>\r"; 3377 int found_cr; 3378 3379 /* Try with a character handler, for code coverage */ 3380 XML_SetCharacterDataHandler(g_parser, cr_cdata_handler); 3381 XML_SetUserData(g_parser, &found_cr); 3382 found_cr = 0; 3383 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3384 == XML_STATUS_OK) 3385 fail("Failed to fault unclosed doc"); 3386 if (found_cr == 0) 3387 fail("Did not catch the carriage return"); 3388 XML_ParserReset(g_parser, NULL); 3389 3390 /* Now with a default handler instead */ 3391 XML_SetDefaultHandler(g_parser, cr_cdata_handler); 3392 XML_SetUserData(g_parser, &found_cr); 3393 found_cr = 0; 3394 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3395 == XML_STATUS_OK) 3396 fail("Failed to fault unclosed doc"); 3397 if (found_cr == 0) 3398 fail("Did not catch default carriage return"); 3399 } 3400 END_TEST 3401 3402 /* Test trailing CR in an external entity parse */ 3403 static int XMLCALL 3404 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context, 3405 const XML_Char *base, const XML_Char *systemId, 3406 const XML_Char *publicId) { 3407 const char *text = "\r"; 3408 XML_Parser ext_parser; 3409 3410 UNUSED_P(base); 3411 UNUSED_P(systemId); 3412 UNUSED_P(publicId); 3413 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3414 if (ext_parser == NULL) 3415 fail("Could not create external entity parser"); 3416 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler); 3417 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3418 == XML_STATUS_ERROR) 3419 xml_failure(ext_parser); 3420 XML_ParserFree(ext_parser); 3421 return XML_STATUS_OK; 3422 } 3423 3424 static int XMLCALL 3425 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context, 3426 const XML_Char *base, const XML_Char *systemId, 3427 const XML_Char *publicId) { 3428 const char *text = "<tag>\r"; 3429 XML_Parser ext_parser; 3430 3431 UNUSED_P(base); 3432 UNUSED_P(systemId); 3433 UNUSED_P(publicId); 3434 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3435 if (ext_parser == NULL) 3436 fail("Could not create external entity parser"); 3437 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler); 3438 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3439 == XML_STATUS_OK) 3440 fail("Async entity error not caught"); 3441 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY) 3442 xml_failure(ext_parser); 3443 XML_ParserFree(ext_parser); 3444 return XML_STATUS_OK; 3445 } 3446 3447 START_TEST(test_ext_entity_trailing_cr) { 3448 const char *text = "<!DOCTYPE doc [\n" 3449 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3450 "]>\n" 3451 "<doc>&en;</doc>"; 3452 int found_cr; 3453 3454 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3455 XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher); 3456 XML_SetUserData(g_parser, &found_cr); 3457 found_cr = 0; 3458 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3459 != XML_STATUS_OK) 3460 xml_failure(g_parser); 3461 if (found_cr == 0) 3462 fail("No carriage return found"); 3463 XML_ParserReset(g_parser, NULL); 3464 3465 /* Try again with a different trailing CR */ 3466 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3467 XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher); 3468 XML_SetUserData(g_parser, &found_cr); 3469 found_cr = 0; 3470 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3471 != XML_STATUS_OK) 3472 xml_failure(g_parser); 3473 if (found_cr == 0) 3474 fail("No carriage return found"); 3475 } 3476 END_TEST 3477 3478 /* Test handling of trailing square bracket */ 3479 static void XMLCALL 3480 rsqb_handler(void *userData, const XML_Char *s, int len) { 3481 int *pfound = (int *)userData; 3482 3483 if (len == 1 && *s == XCS(']')) 3484 *pfound = 1; 3485 } 3486 3487 START_TEST(test_trailing_rsqb) { 3488 const char *text8 = "<doc>]"; 3489 const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000"; 3490 int found_rsqb; 3491 int text8_len = (int)strlen(text8); 3492 3493 XML_SetCharacterDataHandler(g_parser, rsqb_handler); 3494 XML_SetUserData(g_parser, &found_rsqb); 3495 found_rsqb = 0; 3496 if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE) 3497 == XML_STATUS_OK) 3498 fail("Failed to fault unclosed doc"); 3499 if (found_rsqb == 0) 3500 fail("Did not catch the right square bracket"); 3501 3502 /* Try again with a different encoding */ 3503 XML_ParserReset(g_parser, NULL); 3504 XML_SetCharacterDataHandler(g_parser, rsqb_handler); 3505 XML_SetUserData(g_parser, &found_rsqb); 3506 found_rsqb = 0; 3507 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1, 3508 XML_TRUE) 3509 == XML_STATUS_OK) 3510 fail("Failed to fault unclosed doc"); 3511 if (found_rsqb == 0) 3512 fail("Did not catch the right square bracket"); 3513 3514 /* And finally with a default handler */ 3515 XML_ParserReset(g_parser, NULL); 3516 XML_SetDefaultHandler(g_parser, rsqb_handler); 3517 XML_SetUserData(g_parser, &found_rsqb); 3518 found_rsqb = 0; 3519 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1, 3520 XML_TRUE) 3521 == XML_STATUS_OK) 3522 fail("Failed to fault unclosed doc"); 3523 if (found_rsqb == 0) 3524 fail("Did not catch the right square bracket"); 3525 } 3526 END_TEST 3527 3528 /* Test trailing right square bracket in an external entity parse */ 3529 static int XMLCALL 3530 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context, 3531 const XML_Char *base, const XML_Char *systemId, 3532 const XML_Char *publicId) { 3533 const char *text = "<tag>]"; 3534 XML_Parser ext_parser; 3535 3536 UNUSED_P(base); 3537 UNUSED_P(systemId); 3538 UNUSED_P(publicId); 3539 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3540 if (ext_parser == NULL) 3541 fail("Could not create external entity parser"); 3542 XML_SetCharacterDataHandler(ext_parser, rsqb_handler); 3543 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3544 != XML_STATUS_ERROR) 3545 fail("Async entity error not caught"); 3546 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY) 3547 xml_failure(ext_parser); 3548 XML_ParserFree(ext_parser); 3549 return XML_STATUS_OK; 3550 } 3551 3552 START_TEST(test_ext_entity_trailing_rsqb) { 3553 const char *text = "<!DOCTYPE doc [\n" 3554 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3555 "]>\n" 3556 "<doc>&en;</doc>"; 3557 int found_rsqb; 3558 3559 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3560 XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher); 3561 XML_SetUserData(g_parser, &found_rsqb); 3562 found_rsqb = 0; 3563 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3564 != XML_STATUS_OK) 3565 xml_failure(g_parser); 3566 if (found_rsqb == 0) 3567 fail("No right square bracket found"); 3568 } 3569 END_TEST 3570 3571 /* Test CDATA handling in an external entity */ 3572 static int XMLCALL 3573 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context, 3574 const XML_Char *base, const XML_Char *systemId, 3575 const XML_Char *publicId) { 3576 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>"; 3577 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>"); 3578 CharData storage; 3579 XML_Parser ext_parser; 3580 3581 UNUSED_P(base); 3582 UNUSED_P(systemId); 3583 UNUSED_P(publicId); 3584 CharData_Init(&storage); 3585 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3586 if (ext_parser == NULL) 3587 fail("Could not create external entity parser"); 3588 XML_SetUserData(ext_parser, &storage); 3589 XML_SetCharacterDataHandler(ext_parser, accumulate_characters); 3590 3591 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3592 == XML_STATUS_ERROR) 3593 xml_failure(ext_parser); 3594 CharData_CheckXMLChars(&storage, expected); 3595 3596 XML_ParserFree(ext_parser); 3597 return XML_STATUS_OK; 3598 } 3599 3600 START_TEST(test_ext_entity_good_cdata) { 3601 const char *text = "<!DOCTYPE doc [\n" 3602 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3603 "]>\n" 3604 "<doc>&en;</doc>"; 3605 3606 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3607 XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii); 3608 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3609 != XML_STATUS_OK) 3610 xml_failure(g_parser); 3611 } 3612 END_TEST 3613 3614 /* Test user parameter settings */ 3615 /* Variable holding the expected handler userData */ 3616 static void *handler_data = NULL; 3617 /* Count of the number of times the comment handler has been invoked */ 3618 static int comment_count = 0; 3619 /* Count of the number of skipped entities */ 3620 static int skip_count = 0; 3621 /* Count of the number of times the XML declaration handler is invoked */ 3622 static int xdecl_count = 0; 3623 3624 static void XMLCALL 3625 xml_decl_handler(void *userData, const XML_Char *version, 3626 const XML_Char *encoding, int standalone) { 3627 UNUSED_P(version); 3628 UNUSED_P(encoding); 3629 if (userData != handler_data) 3630 fail("User data (xml decl) not correctly set"); 3631 if (standalone != -1) 3632 fail("Standalone not flagged as not present in XML decl"); 3633 xdecl_count++; 3634 } 3635 3636 static void XMLCALL 3637 param_check_skip_handler(void *userData, const XML_Char *entityName, 3638 int is_parameter_entity) { 3639 UNUSED_P(entityName); 3640 UNUSED_P(is_parameter_entity); 3641 if (userData != handler_data) 3642 fail("User data (skip) not correctly set"); 3643 skip_count++; 3644 } 3645 3646 static void XMLCALL 3647 data_check_comment_handler(void *userData, const XML_Char *data) { 3648 UNUSED_P(data); 3649 /* Check that the userData passed through is what we expect */ 3650 if (userData != handler_data) 3651 fail("User data (parser) not correctly set"); 3652 /* Check that the user data in the parser is appropriate */ 3653 if (XML_GetUserData(userData) != (void *)1) 3654 fail("User data in parser not correctly set"); 3655 comment_count++; 3656 } 3657 3658 static int XMLCALL 3659 external_entity_param_checker(XML_Parser parser, const XML_Char *context, 3660 const XML_Char *base, const XML_Char *systemId, 3661 const XML_Char *publicId) { 3662 const char *text = "<!-- Subordinate parser -->\n" 3663 "<!ELEMENT doc (#PCDATA)*>"; 3664 XML_Parser ext_parser; 3665 3666 UNUSED_P(base); 3667 UNUSED_P(systemId); 3668 UNUSED_P(publicId); 3669 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3670 if (ext_parser == NULL) 3671 fail("Could not create external entity parser"); 3672 handler_data = ext_parser; 3673 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3674 == XML_STATUS_ERROR) { 3675 xml_failure(parser); 3676 return XML_STATUS_ERROR; 3677 } 3678 handler_data = parser; 3679 XML_ParserFree(ext_parser); 3680 return XML_STATUS_OK; 3681 } 3682 3683 START_TEST(test_user_parameters) { 3684 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3685 "<!-- Primary parse -->\n" 3686 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3687 "<doc>&entity;"; 3688 const char *epilog = "<!-- Back to primary parser -->\n" 3689 "</doc>"; 3690 3691 comment_count = 0; 3692 skip_count = 0; 3693 xdecl_count = 0; 3694 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3695 XML_SetXmlDeclHandler(g_parser, xml_decl_handler); 3696 XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker); 3697 XML_SetCommentHandler(g_parser, data_check_comment_handler); 3698 XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler); 3699 XML_UseParserAsHandlerArg(g_parser); 3700 XML_SetUserData(g_parser, (void *)1); 3701 handler_data = g_parser; 3702 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3703 == XML_STATUS_ERROR) 3704 xml_failure(g_parser); 3705 if (comment_count != 2) 3706 fail("Comment handler not invoked enough times"); 3707 /* Ensure we can't change policy mid-parse */ 3708 if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER)) 3709 fail("Changed param entity parsing policy while parsing"); 3710 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 3711 == XML_STATUS_ERROR) 3712 xml_failure(g_parser); 3713 if (comment_count != 3) 3714 fail("Comment handler not invoked enough times"); 3715 if (skip_count != 1) 3716 fail("Skip handler not invoked enough times"); 3717 if (xdecl_count != 1) 3718 fail("XML declaration handler not invoked"); 3719 } 3720 END_TEST 3721 3722 /* Test that an explicit external entity handler argument replaces 3723 * the parser as the first argument. 3724 * 3725 * We do not call the first parameter to the external entity handler 3726 * 'parser' for once, since the first time the handler is called it 3727 * will actually be a text string. We need to be able to access the 3728 * global 'parser' variable to create our external entity parser from, 3729 * since there are code paths we need to ensure get executed. 3730 */ 3731 static int XMLCALL 3732 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context, 3733 const XML_Char *base, 3734 const XML_Char *systemId, 3735 const XML_Char *publicId) { 3736 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3737 XML_Parser ext_parser; 3738 3739 UNUSED_P(base); 3740 UNUSED_P(systemId); 3741 UNUSED_P(publicId); 3742 if ((void *)parameter != handler_data) 3743 fail("External entity ref handler parameter not correct"); 3744 3745 /* Here we use the global 'parser' variable */ 3746 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL); 3747 if (ext_parser == NULL) 3748 fail("Could not create external entity parser"); 3749 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3750 == XML_STATUS_ERROR) 3751 xml_failure(ext_parser); 3752 3753 XML_ParserFree(ext_parser); 3754 return XML_STATUS_OK; 3755 } 3756 3757 START_TEST(test_ext_entity_ref_parameter) { 3758 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3759 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3760 "<doc>&entity;</doc>"; 3761 3762 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3763 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker); 3764 /* Set a handler arg that is not NULL and not parser (which is 3765 * what NULL would cause to be passed. 3766 */ 3767 XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text); 3768 handler_data = (void *)text; 3769 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3770 == XML_STATUS_ERROR) 3771 xml_failure(g_parser); 3772 3773 /* Now try again with unset args */ 3774 XML_ParserReset(g_parser, NULL); 3775 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3776 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker); 3777 XML_SetExternalEntityRefHandlerArg(g_parser, NULL); 3778 handler_data = (void *)g_parser; 3779 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3780 == XML_STATUS_ERROR) 3781 xml_failure(g_parser); 3782 } 3783 END_TEST 3784 3785 /* Test the parsing of an empty string */ 3786 START_TEST(test_empty_parse) { 3787 const char *text = "<doc></doc>"; 3788 const char *partial = "<doc>"; 3789 3790 if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR) 3791 fail("Parsing empty string faulted"); 3792 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 3793 fail("Parsing final empty string not faulted"); 3794 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS) 3795 fail("Parsing final empty string faulted for wrong reason"); 3796 3797 /* Now try with valid text before the empty end */ 3798 XML_ParserReset(g_parser, NULL); 3799 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3800 == XML_STATUS_ERROR) 3801 xml_failure(g_parser); 3802 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR) 3803 fail("Parsing final empty string faulted"); 3804 3805 /* Now try with invalid text before the empty end */ 3806 XML_ParserReset(g_parser, NULL); 3807 if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial), 3808 XML_FALSE) 3809 == XML_STATUS_ERROR) 3810 xml_failure(g_parser); 3811 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 3812 fail("Parsing final incomplete empty string not faulted"); 3813 } 3814 END_TEST 3815 3816 /* Test odd corners of the XML_GetBuffer interface */ 3817 static enum XML_Status 3818 get_feature(enum XML_FeatureEnum feature_id, long *presult) { 3819 const XML_Feature *feature = XML_GetFeatureList(); 3820 3821 if (feature == NULL) 3822 return XML_STATUS_ERROR; 3823 for (; feature->feature != XML_FEATURE_END; feature++) { 3824 if (feature->feature == feature_id) { 3825 *presult = feature->value; 3826 return XML_STATUS_OK; 3827 } 3828 } 3829 return XML_STATUS_ERROR; 3830 } 3831 3832 /* Having an element name longer than 1024 characters exercises some 3833 * of the pool allocation code in the parser that otherwise does not 3834 * get executed. The count at the end of the line is the number of 3835 * characters (bytes) in the element name by that point.x 3836 */ 3837 static const char *get_buffer_test_text 3838 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */ 3839 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */ 3840 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */ 3841 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */ 3842 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */ 3843 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */ 3844 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */ 3845 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */ 3846 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */ 3847 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */ 3848 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */ 3849 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */ 3850 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */ 3851 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */ 3852 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */ 3853 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */ 3854 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */ 3855 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */ 3856 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */ 3857 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */ 3858 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */ 3859 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */ 3860 3861 /* Test odd corners of the XML_GetBuffer interface */ 3862 START_TEST(test_get_buffer_1) { 3863 const char *text = get_buffer_test_text; 3864 void *buffer; 3865 long context_bytes; 3866 3867 /* Attempt to allocate a negative length buffer */ 3868 if (XML_GetBuffer(g_parser, -12) != NULL) 3869 fail("Negative length buffer not failed"); 3870 3871 /* Now get a small buffer and extend it past valid length */ 3872 buffer = XML_GetBuffer(g_parser, 1536); 3873 if (buffer == NULL) 3874 fail("1.5K buffer failed"); 3875 assert(buffer != NULL); 3876 memcpy(buffer, text, strlen(text)); 3877 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 3878 == XML_STATUS_ERROR) 3879 xml_failure(g_parser); 3880 if (XML_GetBuffer(g_parser, INT_MAX) != NULL) 3881 fail("INT_MAX buffer not failed"); 3882 3883 /* Now try extending it a more reasonable but still too large 3884 * amount. The allocator in XML_GetBuffer() doubles the buffer 3885 * size until it exceeds the requested amount or INT_MAX. If it 3886 * exceeds INT_MAX, it rejects the request, so we want a request 3887 * between INT_MAX and INT_MAX/2. A gap of 1K seems comfortable, 3888 * with an extra byte just to ensure that the request is off any 3889 * boundary. The request will be inflated internally by 3890 * XML_CONTEXT_BYTES (if defined), so we subtract that from our 3891 * request. 3892 */ 3893 if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK) 3894 context_bytes = 0; 3895 if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL) 3896 fail("INT_MAX- buffer not failed"); 3897 3898 /* Now try extending it a carefully crafted amount */ 3899 if (XML_GetBuffer(g_parser, 1000) == NULL) 3900 fail("1000 buffer failed"); 3901 } 3902 END_TEST 3903 3904 /* Test more corners of the XML_GetBuffer interface */ 3905 START_TEST(test_get_buffer_2) { 3906 const char *text = get_buffer_test_text; 3907 void *buffer; 3908 3909 /* Now get a decent buffer */ 3910 buffer = XML_GetBuffer(g_parser, 1536); 3911 if (buffer == NULL) 3912 fail("1.5K buffer failed"); 3913 assert(buffer != NULL); 3914 memcpy(buffer, text, strlen(text)); 3915 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 3916 == XML_STATUS_ERROR) 3917 xml_failure(g_parser); 3918 3919 /* Extend it, to catch a different code path */ 3920 if (XML_GetBuffer(g_parser, 1024) == NULL) 3921 fail("1024 buffer failed"); 3922 } 3923 END_TEST 3924 3925 /* Test for signed integer overflow CVE-2022-23852 */ 3926 #if defined(XML_CONTEXT_BYTES) 3927 START_TEST(test_get_buffer_3_overflow) { 3928 XML_Parser parser = XML_ParserCreate(NULL); 3929 assert(parser != NULL); 3930 3931 const char *const text = "\n"; 3932 const int expectedKeepValue = (int)strlen(text); 3933 3934 // After this call, variable "keep" in XML_GetBuffer will 3935 // have value expectedKeepValue 3936 if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */) 3937 == XML_STATUS_ERROR) 3938 xml_failure(parser); 3939 3940 assert(expectedKeepValue > 0); 3941 if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL) 3942 fail("enlarging buffer not failed"); 3943 3944 XML_ParserFree(parser); 3945 } 3946 END_TEST 3947 #endif // defined(XML_CONTEXT_BYTES) 3948 3949 /* Test position information macros */ 3950 START_TEST(test_byte_info_at_end) { 3951 const char *text = "<doc></doc>"; 3952 3953 if (XML_GetCurrentByteIndex(g_parser) != -1 3954 || XML_GetCurrentByteCount(g_parser) != 0) 3955 fail("Byte index/count incorrect at start of parse"); 3956 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3957 == XML_STATUS_ERROR) 3958 xml_failure(g_parser); 3959 /* At end, the count will be zero and the index the end of string */ 3960 if (XML_GetCurrentByteCount(g_parser) != 0) 3961 fail("Terminal byte count incorrect"); 3962 if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text)) 3963 fail("Terminal byte index incorrect"); 3964 } 3965 END_TEST 3966 3967 /* Test position information from errors */ 3968 #define PRE_ERROR_STR "<doc></" 3969 #define POST_ERROR_STR "wombat></doc>" 3970 START_TEST(test_byte_info_at_error) { 3971 const char *text = PRE_ERROR_STR POST_ERROR_STR; 3972 3973 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3974 == XML_STATUS_OK) 3975 fail("Syntax error not faulted"); 3976 if (XML_GetCurrentByteCount(g_parser) != 0) 3977 fail("Error byte count incorrect"); 3978 if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR)) 3979 fail("Error byte index incorrect"); 3980 } 3981 END_TEST 3982 #undef PRE_ERROR_STR 3983 #undef POST_ERROR_STR 3984 3985 /* Test position information in handler */ 3986 typedef struct ByteTestData { 3987 int start_element_len; 3988 int cdata_len; 3989 int total_string_len; 3990 } ByteTestData; 3991 3992 static void 3993 byte_character_handler(void *userData, const XML_Char *s, int len) { 3994 #ifdef XML_CONTEXT_BYTES 3995 int offset, size; 3996 const char *buffer; 3997 ByteTestData *data = (ByteTestData *)userData; 3998 3999 UNUSED_P(s); 4000 buffer = XML_GetInputContext(g_parser, &offset, &size); 4001 if (buffer == NULL) 4002 fail("Failed to get context buffer"); 4003 if (offset != data->start_element_len) 4004 fail("Context offset in unexpected position"); 4005 if (len != data->cdata_len) 4006 fail("CDATA length reported incorrectly"); 4007 if (size != data->total_string_len) 4008 fail("Context size is not full buffer"); 4009 if (XML_GetCurrentByteIndex(g_parser) != offset) 4010 fail("Character byte index incorrect"); 4011 if (XML_GetCurrentByteCount(g_parser) != len) 4012 fail("Character byte count incorrect"); 4013 #else 4014 UNUSED_P(s); 4015 UNUSED_P(userData); 4016 UNUSED_P(len); 4017 #endif 4018 } 4019 4020 #define START_ELEMENT "<e>" 4021 #define CDATA_TEXT "Hello" 4022 #define END_ELEMENT "</e>" 4023 START_TEST(test_byte_info_at_cdata) { 4024 const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT; 4025 int offset, size; 4026 ByteTestData data; 4027 4028 /* Check initial context is empty */ 4029 if (XML_GetInputContext(g_parser, &offset, &size) != NULL) 4030 fail("Unexpected context at start of parse"); 4031 4032 data.start_element_len = (int)strlen(START_ELEMENT); 4033 data.cdata_len = (int)strlen(CDATA_TEXT); 4034 data.total_string_len = (int)strlen(text); 4035 XML_SetCharacterDataHandler(g_parser, byte_character_handler); 4036 XML_SetUserData(g_parser, &data); 4037 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK) 4038 xml_failure(g_parser); 4039 } 4040 END_TEST 4041 #undef START_ELEMENT 4042 #undef CDATA_TEXT 4043 #undef END_ELEMENT 4044 4045 /* Test predefined entities are correctly recognised */ 4046 START_TEST(test_predefined_entities) { 4047 const char *text = "<doc><>&"'</doc>"; 4048 const XML_Char *expected = XCS("<doc><>&"'</doc>"); 4049 const XML_Char *result = XCS("<>&\"'"); 4050 CharData storage; 4051 4052 XML_SetDefaultHandler(g_parser, accumulate_characters); 4053 /* run_character_check uses XML_SetCharacterDataHandler(), which 4054 * unfortunately heads off a code path that we need to exercise. 4055 */ 4056 CharData_Init(&storage); 4057 XML_SetUserData(g_parser, &storage); 4058 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4059 == XML_STATUS_ERROR) 4060 xml_failure(g_parser); 4061 /* The default handler doesn't translate the entities */ 4062 CharData_CheckXMLChars(&storage, expected); 4063 4064 /* Now try again and check the translation */ 4065 XML_ParserReset(g_parser, NULL); 4066 run_character_check(text, result); 4067 } 4068 END_TEST 4069 4070 /* Regression test that an invalid tag in an external parameter 4071 * reference in an external DTD is correctly faulted. 4072 * 4073 * Only a few specific tags are legal in DTDs ignoring comments and 4074 * processing instructions, all of which begin with an exclamation 4075 * mark. "<el/>" is not one of them, so the parser should raise an 4076 * error on encountering it. 4077 */ 4078 static int XMLCALL 4079 external_entity_param(XML_Parser parser, const XML_Char *context, 4080 const XML_Char *base, const XML_Char *systemId, 4081 const XML_Char *publicId) { 4082 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4083 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4084 "<!ENTITY % e2 '%e1;'>\n" 4085 "%e1;\n"; 4086 const char *text2 = "<!ELEMENT el EMPTY>\n" 4087 "<el/>\n"; 4088 XML_Parser ext_parser; 4089 4090 UNUSED_P(base); 4091 UNUSED_P(publicId); 4092 if (systemId == NULL) 4093 return XML_STATUS_OK; 4094 4095 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4096 if (ext_parser == NULL) 4097 fail("Could not create external entity parser"); 4098 4099 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4100 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4101 != XML_STATUS_ERROR) 4102 fail("Inner DTD with invalid tag not rejected"); 4103 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) 4104 xml_failure(ext_parser); 4105 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4106 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4107 != XML_STATUS_ERROR) 4108 fail("Invalid tag in external param not rejected"); 4109 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX) 4110 xml_failure(ext_parser); 4111 } else { 4112 fail("Unknown system ID"); 4113 } 4114 4115 XML_ParserFree(ext_parser); 4116 return XML_STATUS_ERROR; 4117 } 4118 4119 START_TEST(test_invalid_tag_in_dtd) { 4120 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4121 "<doc></doc>\n"; 4122 4123 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4124 XML_SetExternalEntityRefHandler(g_parser, external_entity_param); 4125 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4126 "Invalid tag IN DTD external param not rejected"); 4127 } 4128 END_TEST 4129 4130 /* Test entities not quite the predefined ones are not mis-recognised */ 4131 START_TEST(test_not_predefined_entities) { 4132 const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>", 4133 "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL}; 4134 int i = 0; 4135 4136 while (text[i] != NULL) { 4137 expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY, 4138 "Undefined entity not rejected"); 4139 XML_ParserReset(g_parser, NULL); 4140 i++; 4141 } 4142 } 4143 END_TEST 4144 4145 /* Test conditional inclusion (IGNORE) */ 4146 static int XMLCALL 4147 external_entity_load_ignore(XML_Parser parser, const XML_Char *context, 4148 const XML_Char *base, const XML_Char *systemId, 4149 const XML_Char *publicId) { 4150 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>"; 4151 XML_Parser ext_parser; 4152 4153 UNUSED_P(base); 4154 UNUSED_P(systemId); 4155 UNUSED_P(publicId); 4156 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4157 if (ext_parser == NULL) 4158 fail("Could not create external entity parser"); 4159 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 4160 == XML_STATUS_ERROR) 4161 xml_failure(parser); 4162 4163 XML_ParserFree(ext_parser); 4164 return XML_STATUS_OK; 4165 } 4166 4167 START_TEST(test_ignore_section) { 4168 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4169 "<doc><e>&entity;</e></doc>"; 4170 const XML_Char *expected 4171 = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;"); 4172 CharData storage; 4173 4174 CharData_Init(&storage); 4175 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4176 XML_SetUserData(g_parser, &storage); 4177 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore); 4178 XML_SetDefaultHandler(g_parser, accumulate_characters); 4179 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4180 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4181 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4182 XML_SetStartElementHandler(g_parser, dummy_start_element); 4183 XML_SetEndElementHandler(g_parser, dummy_end_element); 4184 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4185 == XML_STATUS_ERROR) 4186 xml_failure(g_parser); 4187 CharData_CheckXMLChars(&storage, expected); 4188 } 4189 END_TEST 4190 4191 static int XMLCALL 4192 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context, 4193 const XML_Char *base, 4194 const XML_Char *systemId, 4195 const XML_Char *publicId) { 4196 const char text[] = 4197 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */ 4198 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0" 4199 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0" 4200 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0"; 4201 XML_Parser ext_parser; 4202 4203 UNUSED_P(base); 4204 UNUSED_P(systemId); 4205 UNUSED_P(publicId); 4206 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4207 if (ext_parser == NULL) 4208 fail("Could not create external entity parser"); 4209 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4210 == XML_STATUS_ERROR) 4211 xml_failure(parser); 4212 4213 XML_ParserFree(ext_parser); 4214 return XML_STATUS_OK; 4215 } 4216 4217 START_TEST(test_ignore_section_utf16) { 4218 const char text[] = 4219 /* <!DOCTYPE d SYSTEM 's'> */ 4220 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 " 4221 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0" 4222 /* <d><e>&en;</e></d> */ 4223 "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0"; 4224 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;"); 4225 CharData storage; 4226 4227 CharData_Init(&storage); 4228 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4229 XML_SetUserData(g_parser, &storage); 4230 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16); 4231 XML_SetDefaultHandler(g_parser, accumulate_characters); 4232 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4233 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4234 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4235 XML_SetStartElementHandler(g_parser, dummy_start_element); 4236 XML_SetEndElementHandler(g_parser, dummy_end_element); 4237 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4238 == XML_STATUS_ERROR) 4239 xml_failure(g_parser); 4240 CharData_CheckXMLChars(&storage, expected); 4241 } 4242 END_TEST 4243 4244 static int XMLCALL 4245 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context, 4246 const XML_Char *base, 4247 const XML_Char *systemId, 4248 const XML_Char *publicId) { 4249 const char text[] = 4250 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */ 4251 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0[" 4252 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 " 4253 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>"; 4254 XML_Parser ext_parser; 4255 4256 UNUSED_P(base); 4257 UNUSED_P(systemId); 4258 UNUSED_P(publicId); 4259 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4260 if (ext_parser == NULL) 4261 fail("Could not create external entity parser"); 4262 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4263 == XML_STATUS_ERROR) 4264 xml_failure(parser); 4265 4266 XML_ParserFree(ext_parser); 4267 return XML_STATUS_OK; 4268 } 4269 4270 START_TEST(test_ignore_section_utf16_be) { 4271 const char text[] = 4272 /* <!DOCTYPE d SYSTEM 's'> */ 4273 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 " 4274 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n" 4275 /* <d><e>&en;</e></d> */ 4276 "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>"; 4277 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;"); 4278 CharData storage; 4279 4280 CharData_Init(&storage); 4281 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4282 XML_SetUserData(g_parser, &storage); 4283 XML_SetExternalEntityRefHandler(g_parser, 4284 external_entity_load_ignore_utf16_be); 4285 XML_SetDefaultHandler(g_parser, accumulate_characters); 4286 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4287 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4288 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4289 XML_SetStartElementHandler(g_parser, dummy_start_element); 4290 XML_SetEndElementHandler(g_parser, dummy_end_element); 4291 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4292 == XML_STATUS_ERROR) 4293 xml_failure(g_parser); 4294 CharData_CheckXMLChars(&storage, expected); 4295 } 4296 END_TEST 4297 4298 /* Test mis-formatted conditional exclusion */ 4299 START_TEST(test_bad_ignore_section) { 4300 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4301 "<doc><e>&entity;</e></doc>"; 4302 ExtFaults faults[] 4303 = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL, 4304 XML_ERROR_SYNTAX}, 4305 {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL, 4306 XML_ERROR_INVALID_TOKEN}, 4307 {/* FIrst two bytes of a three-byte char */ 4308 "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL, 4309 XML_ERROR_PARTIAL_CHAR}, 4310 {NULL, NULL, NULL, XML_ERROR_NONE}}; 4311 ExtFaults *fault; 4312 4313 for (fault = &faults[0]; fault->parse_text != NULL; fault++) { 4314 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4315 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 4316 XML_SetUserData(g_parser, fault); 4317 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4318 "Incomplete IGNORE section not failed"); 4319 XML_ParserReset(g_parser, NULL); 4320 } 4321 } 4322 END_TEST 4323 4324 /* Test recursive parsing */ 4325 static int XMLCALL 4326 external_entity_valuer(XML_Parser parser, const XML_Char *context, 4327 const XML_Char *base, const XML_Char *systemId, 4328 const XML_Char *publicId) { 4329 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4330 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4331 "<!ENTITY % e2 '%e1;'>\n" 4332 "%e1;\n"; 4333 XML_Parser ext_parser; 4334 4335 UNUSED_P(base); 4336 UNUSED_P(publicId); 4337 if (systemId == NULL) 4338 return XML_STATUS_OK; 4339 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4340 if (ext_parser == NULL) 4341 fail("Could not create external entity parser"); 4342 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4343 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4344 == XML_STATUS_ERROR) 4345 xml_failure(ext_parser); 4346 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4347 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 4348 enum XML_Status status; 4349 enum XML_Error error; 4350 4351 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text, 4352 (int)strlen(fault->parse_text), XML_TRUE); 4353 if (fault->error == XML_ERROR_NONE) { 4354 if (status == XML_STATUS_ERROR) 4355 xml_failure(ext_parser); 4356 } else { 4357 if (status != XML_STATUS_ERROR) 4358 fail(fault->fail_text); 4359 error = XML_GetErrorCode(ext_parser); 4360 if (error != fault->error 4361 && (fault->error != XML_ERROR_XML_DECL 4362 || error != XML_ERROR_TEXT_DECL)) 4363 xml_failure(ext_parser); 4364 } 4365 } 4366 4367 XML_ParserFree(ext_parser); 4368 return XML_STATUS_OK; 4369 } 4370 4371 START_TEST(test_external_entity_values) { 4372 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4373 "<doc></doc>\n"; 4374 ExtFaults data_004_2[] = { 4375 {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE}, 4376 {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL, 4377 XML_ERROR_INVALID_TOKEN}, 4378 {"'wombat", "Unterminated string not faulted", NULL, 4379 XML_ERROR_UNCLOSED_TOKEN}, 4380 {"\xe2\x82", "Partial UTF-8 character not faulted", NULL, 4381 XML_ERROR_PARTIAL_CHAR}, 4382 {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE}, 4383 {"<?xml?>", "Malformed XML declaration not faulted", NULL, 4384 XML_ERROR_XML_DECL}, 4385 {/* UTF-8 BOM */ 4386 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, 4387 XML_ERROR_NONE}, 4388 {"<?xml version='1.0' encoding='utf-8'?>\n$", 4389 "Invalid token after text declaration not faulted", NULL, 4390 XML_ERROR_INVALID_TOKEN}, 4391 {"<?xml version='1.0' encoding='utf-8'?>\n'wombat", 4392 "Unterminated string after text decl not faulted", NULL, 4393 XML_ERROR_UNCLOSED_TOKEN}, 4394 {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82", 4395 "Partial UTF-8 character after text decl not faulted", NULL, 4396 XML_ERROR_PARTIAL_CHAR}, 4397 {"%e1;", "Recursive parameter entity not faulted", NULL, 4398 XML_ERROR_RECURSIVE_ENTITY_REF}, 4399 {NULL, NULL, NULL, XML_ERROR_NONE}}; 4400 int i; 4401 4402 for (i = 0; data_004_2[i].parse_text != NULL; i++) { 4403 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4404 XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer); 4405 XML_SetUserData(g_parser, &data_004_2[i]); 4406 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4407 == XML_STATUS_ERROR) 4408 xml_failure(g_parser); 4409 XML_ParserReset(g_parser, NULL); 4410 } 4411 } 4412 END_TEST 4413 4414 /* Test the recursive parse interacts with a not standalone handler */ 4415 static int XMLCALL 4416 external_entity_not_standalone(XML_Parser parser, const XML_Char *context, 4417 const XML_Char *base, const XML_Char *systemId, 4418 const XML_Char *publicId) { 4419 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4420 "<!ENTITY % e1 SYSTEM 'bar'>\n" 4421 "%e1;\n"; 4422 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>"; 4423 XML_Parser ext_parser; 4424 4425 UNUSED_P(base); 4426 UNUSED_P(publicId); 4427 if (systemId == NULL) 4428 return XML_STATUS_OK; 4429 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4430 if (ext_parser == NULL) 4431 fail("Could not create external entity parser"); 4432 if (! xcstrcmp(systemId, XCS("foo"))) { 4433 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler); 4434 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4435 != XML_STATUS_ERROR) 4436 fail("Expected not standalone rejection"); 4437 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE) 4438 xml_failure(ext_parser); 4439 XML_SetNotStandaloneHandler(ext_parser, NULL); 4440 XML_ParserFree(ext_parser); 4441 return XML_STATUS_ERROR; 4442 } else if (! xcstrcmp(systemId, XCS("bar"))) { 4443 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4444 == XML_STATUS_ERROR) 4445 xml_failure(ext_parser); 4446 } 4447 4448 XML_ParserFree(ext_parser); 4449 return XML_STATUS_OK; 4450 } 4451 4452 START_TEST(test_ext_entity_not_standalone) { 4453 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4454 "<doc></doc>"; 4455 4456 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4457 XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone); 4458 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4459 "Standalone rejection not caught"); 4460 } 4461 END_TEST 4462 4463 static int XMLCALL 4464 external_entity_value_aborter(XML_Parser parser, const XML_Char *context, 4465 const XML_Char *base, const XML_Char *systemId, 4466 const XML_Char *publicId) { 4467 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4468 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4469 "<!ENTITY % e2 '%e1;'>\n" 4470 "%e1;\n"; 4471 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>"; 4472 XML_Parser ext_parser; 4473 4474 UNUSED_P(base); 4475 UNUSED_P(publicId); 4476 if (systemId == NULL) 4477 return XML_STATUS_OK; 4478 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4479 if (ext_parser == NULL) 4480 fail("Could not create external entity parser"); 4481 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4482 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4483 == XML_STATUS_ERROR) 4484 xml_failure(ext_parser); 4485 } 4486 if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4487 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 4488 XML_SetUserData(ext_parser, ext_parser); 4489 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4490 != XML_STATUS_ERROR) 4491 fail("Aborted parse not faulted"); 4492 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED) 4493 xml_failure(ext_parser); 4494 } 4495 4496 XML_ParserFree(ext_parser); 4497 return XML_STATUS_OK; 4498 } 4499 4500 START_TEST(test_ext_entity_value_abort) { 4501 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4502 "<doc></doc>\n"; 4503 4504 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4505 XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter); 4506 resumable = XML_FALSE; 4507 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4508 == XML_STATUS_ERROR) 4509 xml_failure(g_parser); 4510 } 4511 END_TEST 4512 4513 START_TEST(test_bad_public_doctype) { 4514 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 4515 "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n" 4516 "<doc></doc>"; 4517 4518 /* Setting a handler provokes a particular code path */ 4519 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 4520 dummy_end_doctype_handler); 4521 expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed"); 4522 } 4523 END_TEST 4524 4525 /* Test based on ibm/valid/P32/ibm32v04.xml */ 4526 START_TEST(test_attribute_enum_value) { 4527 const char *text = "<?xml version='1.0' standalone='no'?>\n" 4528 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 4529 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 4530 ExtTest dtd_data 4531 = {"<!ELEMENT animal (#PCDATA|a)*>\n" 4532 "<!ELEMENT a EMPTY>\n" 4533 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>", 4534 NULL, NULL}; 4535 const XML_Char *expected = XCS("This is a \n \n\nyellow tiger"); 4536 4537 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 4538 XML_SetUserData(g_parser, &dtd_data); 4539 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4540 /* An attribute list handler provokes a different code path */ 4541 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 4542 run_ext_character_check(text, &dtd_data, expected); 4543 } 4544 END_TEST 4545 4546 /* Slightly bizarrely, the library seems to silently ignore entity 4547 * definitions for predefined entities, even when they are wrong. The 4548 * language of the XML 1.0 spec is somewhat unhelpful as to what ought 4549 * to happen, so this is currently treated as acceptable. 4550 */ 4551 START_TEST(test_predefined_entity_redefinition) { 4552 const char *text = "<!DOCTYPE doc [\n" 4553 "<!ENTITY apos 'foo'>\n" 4554 "]>\n" 4555 "<doc>'</doc>"; 4556 run_character_check(text, XCS("'")); 4557 } 4558 END_TEST 4559 4560 /* Test that the parser stops processing the DTD after an unresolved 4561 * parameter entity is encountered. 4562 */ 4563 START_TEST(test_dtd_stop_processing) { 4564 const char *text = "<!DOCTYPE doc [\n" 4565 "%foo;\n" 4566 "<!ENTITY bar 'bas'>\n" 4567 "]><doc/>"; 4568 4569 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 4570 dummy_handler_flags = 0; 4571 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4572 == XML_STATUS_ERROR) 4573 xml_failure(g_parser); 4574 if (dummy_handler_flags != 0) 4575 fail("DTD processing still going after undefined PE"); 4576 } 4577 END_TEST 4578 4579 /* Test public notations with no system ID */ 4580 START_TEST(test_public_notation_no_sysid) { 4581 const char *text = "<!DOCTYPE doc [\n" 4582 "<!NOTATION note PUBLIC 'foo'>\n" 4583 "<!ELEMENT doc EMPTY>\n" 4584 "]>\n<doc/>"; 4585 4586 dummy_handler_flags = 0; 4587 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 4588 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4589 == XML_STATUS_ERROR) 4590 xml_failure(g_parser); 4591 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 4592 fail("Notation declaration handler not called"); 4593 } 4594 END_TEST 4595 4596 static void XMLCALL 4597 record_element_start_handler(void *userData, const XML_Char *name, 4598 const XML_Char **atts) { 4599 UNUSED_P(atts); 4600 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name)); 4601 } 4602 4603 START_TEST(test_nested_groups) { 4604 const char *text 4605 = "<!DOCTYPE doc [\n" 4606 "<!ELEMENT doc " 4607 /* Sixteen elements per line */ 4608 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 4609 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 4610 "))))))))))))))))))))))))))))))))>\n" 4611 "<!ELEMENT e EMPTY>" 4612 "]>\n" 4613 "<doc><e/></doc>"; 4614 CharData storage; 4615 4616 CharData_Init(&storage); 4617 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4618 XML_SetStartElementHandler(g_parser, record_element_start_handler); 4619 XML_SetUserData(g_parser, &storage); 4620 dummy_handler_flags = 0; 4621 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4622 == XML_STATUS_ERROR) 4623 xml_failure(g_parser); 4624 CharData_CheckXMLChars(&storage, XCS("doce")); 4625 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 4626 fail("Element handler not fired"); 4627 } 4628 END_TEST 4629 4630 START_TEST(test_group_choice) { 4631 const char *text = "<!DOCTYPE doc [\n" 4632 "<!ELEMENT doc (a|b|c)+>\n" 4633 "<!ELEMENT a EMPTY>\n" 4634 "<!ELEMENT b (#PCDATA)>\n" 4635 "<!ELEMENT c ANY>\n" 4636 "]>\n" 4637 "<doc>\n" 4638 "<a/>\n" 4639 "<b attr='foo'>This is a foo</b>\n" 4640 "<c></c>\n" 4641 "</doc>\n"; 4642 4643 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4644 dummy_handler_flags = 0; 4645 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4646 == XML_STATUS_ERROR) 4647 xml_failure(g_parser); 4648 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 4649 fail("Element handler flag not raised"); 4650 } 4651 END_TEST 4652 4653 static int XMLCALL 4654 external_entity_public(XML_Parser parser, const XML_Char *context, 4655 const XML_Char *base, const XML_Char *systemId, 4656 const XML_Char *publicId) { 4657 const char *text1 = (const char *)XML_GetUserData(parser); 4658 const char *text2 = "<!ATTLIST doc a CDATA 'value'>"; 4659 const char *text = NULL; 4660 XML_Parser ext_parser; 4661 int parse_res; 4662 4663 UNUSED_P(base); 4664 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4665 if (ext_parser == NULL) 4666 return XML_STATUS_ERROR; 4667 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) { 4668 text = text1; 4669 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) { 4670 text = text2; 4671 } else 4672 fail("Unexpected parameters to external entity parser"); 4673 assert(text != NULL); 4674 parse_res 4675 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 4676 XML_ParserFree(ext_parser); 4677 return parse_res; 4678 } 4679 4680 START_TEST(test_standalone_parameter_entity) { 4681 const char *text = "<?xml version='1.0' standalone='yes'?>\n" 4682 "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n" 4683 "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n" 4684 "%entity;\n" 4685 "]>\n" 4686 "<doc></doc>"; 4687 char dtd_data[] = "<!ENTITY % e1 'foo'>\n"; 4688 4689 XML_SetUserData(g_parser, dtd_data); 4690 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4691 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 4692 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4693 == XML_STATUS_ERROR) 4694 xml_failure(g_parser); 4695 } 4696 END_TEST 4697 4698 /* Test skipping of parameter entity in an external DTD */ 4699 /* Derived from ibm/invalid/P69/ibm69i01.xml */ 4700 START_TEST(test_skipped_parameter_entity) { 4701 const char *text = "<?xml version='1.0'?>\n" 4702 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n" 4703 "<!ELEMENT root (#PCDATA|a)* >\n" 4704 "]>\n" 4705 "<root></root>"; 4706 ExtTest dtd_data = {"%pe2;", NULL, NULL}; 4707 4708 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 4709 XML_SetUserData(g_parser, &dtd_data); 4710 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4711 XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler); 4712 dummy_handler_flags = 0; 4713 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4714 == XML_STATUS_ERROR) 4715 xml_failure(g_parser); 4716 if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG) 4717 fail("Skip handler not executed"); 4718 } 4719 END_TEST 4720 4721 /* Test recursive parameter entity definition rejected in external DTD */ 4722 START_TEST(test_recursive_external_parameter_entity) { 4723 const char *text = "<?xml version='1.0'?>\n" 4724 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n" 4725 "<!ELEMENT root (#PCDATA|a)* >\n" 4726 "]>\n" 4727 "<root></root>"; 4728 ExtFaults dtd_data = {"<!ENTITY % pe2 '%pe2;'>\n%pe2;", 4729 "Recursive external parameter entity not faulted", NULL, 4730 XML_ERROR_RECURSIVE_ENTITY_REF}; 4731 4732 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 4733 XML_SetUserData(g_parser, &dtd_data); 4734 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4735 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4736 "Recursive external parameter not spotted"); 4737 } 4738 END_TEST 4739 4740 /* Test undefined parameter entity in external entity handler */ 4741 static int XMLCALL 4742 external_entity_devaluer(XML_Parser parser, const XML_Char *context, 4743 const XML_Char *base, const XML_Char *systemId, 4744 const XML_Char *publicId) { 4745 const char *text = "<!ELEMENT doc EMPTY>\n" 4746 "<!ENTITY % e1 SYSTEM 'bar'>\n" 4747 "%e1;\n"; 4748 XML_Parser ext_parser; 4749 intptr_t clear_handler = (intptr_t)XML_GetUserData(parser); 4750 4751 UNUSED_P(base); 4752 UNUSED_P(publicId); 4753 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar"))) 4754 return XML_STATUS_OK; 4755 if (xcstrcmp(systemId, XCS("foo"))) 4756 fail("Unexpected system ID"); 4757 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4758 if (ext_parser == NULL) 4759 fail("Could note create external entity parser"); 4760 if (clear_handler) 4761 XML_SetExternalEntityRefHandler(ext_parser, NULL); 4762 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 4763 == XML_STATUS_ERROR) 4764 xml_failure(ext_parser); 4765 4766 XML_ParserFree(ext_parser); 4767 return XML_STATUS_OK; 4768 } 4769 4770 START_TEST(test_undefined_ext_entity_in_external_dtd) { 4771 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4772 "<doc></doc>\n"; 4773 4774 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4775 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer); 4776 XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE); 4777 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4778 == XML_STATUS_ERROR) 4779 xml_failure(g_parser); 4780 4781 /* Now repeat without the external entity ref handler invoking 4782 * another copy of itself. 4783 */ 4784 XML_ParserReset(g_parser, NULL); 4785 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4786 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer); 4787 XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE); 4788 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4789 == XML_STATUS_ERROR) 4790 xml_failure(g_parser); 4791 } 4792 END_TEST 4793 4794 static void XMLCALL 4795 aborting_xdecl_handler(void *userData, const XML_Char *version, 4796 const XML_Char *encoding, int standalone) { 4797 UNUSED_P(userData); 4798 UNUSED_P(version); 4799 UNUSED_P(encoding); 4800 UNUSED_P(standalone); 4801 XML_StopParser(g_parser, resumable); 4802 XML_SetXmlDeclHandler(g_parser, NULL); 4803 } 4804 4805 /* Test suspending the parse on receiving an XML declaration works */ 4806 START_TEST(test_suspend_xdecl) { 4807 const char *text = long_character_data_text; 4808 4809 XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler); 4810 resumable = XML_TRUE; 4811 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4812 != XML_STATUS_SUSPENDED) 4813 xml_failure(g_parser); 4814 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 4815 xml_failure(g_parser); 4816 /* Attempt to start a new parse while suspended */ 4817 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4818 != XML_STATUS_ERROR) 4819 fail("Attempt to parse while suspended not faulted"); 4820 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 4821 fail("Suspended parse not faulted with correct error"); 4822 } 4823 END_TEST 4824 4825 /* Test aborting the parse in an epilog works */ 4826 static void XMLCALL 4827 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) { 4828 const XML_Char *match = (const XML_Char *)userData; 4829 4830 if (match == NULL 4831 || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) { 4832 XML_StopParser(g_parser, resumable); 4833 XML_SetDefaultHandler(g_parser, NULL); 4834 } 4835 } 4836 4837 START_TEST(test_abort_epilog) { 4838 const char *text = "<doc></doc>\n\r\n"; 4839 XML_Char match[] = XCS("\r"); 4840 4841 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4842 XML_SetUserData(g_parser, match); 4843 resumable = XML_FALSE; 4844 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4845 != XML_STATUS_ERROR) 4846 fail("Abort not triggered"); 4847 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED) 4848 xml_failure(g_parser); 4849 } 4850 END_TEST 4851 4852 /* Test a different code path for abort in the epilog */ 4853 START_TEST(test_abort_epilog_2) { 4854 const char *text = "<doc></doc>\n"; 4855 XML_Char match[] = XCS("\n"); 4856 4857 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4858 XML_SetUserData(g_parser, match); 4859 resumable = XML_FALSE; 4860 expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered"); 4861 } 4862 END_TEST 4863 4864 /* Test suspension from the epilog */ 4865 START_TEST(test_suspend_epilog) { 4866 const char *text = "<doc></doc>\n"; 4867 XML_Char match[] = XCS("\n"); 4868 4869 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4870 XML_SetUserData(g_parser, match); 4871 resumable = XML_TRUE; 4872 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4873 != XML_STATUS_SUSPENDED) 4874 xml_failure(g_parser); 4875 } 4876 END_TEST 4877 4878 static void XMLCALL 4879 suspending_end_handler(void *userData, const XML_Char *s) { 4880 UNUSED_P(s); 4881 XML_StopParser((XML_Parser)userData, 1); 4882 } 4883 4884 START_TEST(test_suspend_in_sole_empty_tag) { 4885 const char *text = "<doc/>"; 4886 enum XML_Status rc; 4887 4888 XML_SetEndElementHandler(g_parser, suspending_end_handler); 4889 XML_SetUserData(g_parser, g_parser); 4890 rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 4891 if (rc == XML_STATUS_ERROR) 4892 xml_failure(g_parser); 4893 else if (rc != XML_STATUS_SUSPENDED) 4894 fail("Suspend not triggered"); 4895 rc = XML_ResumeParser(g_parser); 4896 if (rc == XML_STATUS_ERROR) 4897 xml_failure(g_parser); 4898 else if (rc != XML_STATUS_OK) 4899 fail("Resume failed"); 4900 } 4901 END_TEST 4902 4903 START_TEST(test_unfinished_epilog) { 4904 const char *text = "<doc></doc><"; 4905 4906 expect_failure(text, XML_ERROR_UNCLOSED_TOKEN, 4907 "Incomplete epilog entry not faulted"); 4908 } 4909 END_TEST 4910 4911 START_TEST(test_partial_char_in_epilog) { 4912 const char *text = "<doc></doc>\xe2\x82"; 4913 4914 /* First check that no fault is raised if the parse is not finished */ 4915 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 4916 == XML_STATUS_ERROR) 4917 xml_failure(g_parser); 4918 /* Now check that it is faulted once we finish */ 4919 if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR) 4920 fail("Partial character in epilog not faulted"); 4921 if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR) 4922 xml_failure(g_parser); 4923 } 4924 END_TEST 4925 4926 START_TEST(test_hash_collision) { 4927 /* For full coverage of the lookup routine, we need to ensure a 4928 * hash collision even though we can only tell that we have one 4929 * through breakpoint debugging or coverage statistics. The 4930 * following will cause a hash collision on machines with a 64-bit 4931 * long type; others will have to experiment. The full coverage 4932 * tests invoked from qa.sh usually provide a hash collision, but 4933 * not always. This is an attempt to provide insurance. 4934 */ 4935 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U) 4936 const char *text 4937 = "<doc>\n" 4938 "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n" 4939 "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n" 4940 "<b5></b5><b6></b6><b7></b7><b8></b8>\n" 4941 "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n" 4942 "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n" 4943 "<d8>This triggers the table growth and collides with b2</d8>\n" 4944 "</doc>\n"; 4945 4946 XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT); 4947 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4948 == XML_STATUS_ERROR) 4949 xml_failure(g_parser); 4950 } 4951 END_TEST 4952 #undef COLLIDING_HASH_SALT 4953 4954 /* Test resuming a parse suspended in entity substitution */ 4955 static void XMLCALL 4956 start_element_suspender(void *userData, const XML_Char *name, 4957 const XML_Char **atts) { 4958 UNUSED_P(userData); 4959 UNUSED_P(atts); 4960 if (! xcstrcmp(name, XCS("suspend"))) 4961 XML_StopParser(g_parser, XML_TRUE); 4962 if (! xcstrcmp(name, XCS("abort"))) 4963 XML_StopParser(g_parser, XML_FALSE); 4964 } 4965 4966 START_TEST(test_suspend_resume_internal_entity) { 4967 const char *text 4968 = "<!DOCTYPE doc [\n" 4969 "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n" 4970 "]>\n" 4971 "<doc>&foo;</doc>\n"; 4972 const XML_Char *expected1 = XCS("Hi"); 4973 const XML_Char *expected2 = XCS("HiHo"); 4974 CharData storage; 4975 4976 CharData_Init(&storage); 4977 XML_SetStartElementHandler(g_parser, start_element_suspender); 4978 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 4979 XML_SetUserData(g_parser, &storage); 4980 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4981 != XML_STATUS_SUSPENDED) 4982 xml_failure(g_parser); 4983 CharData_CheckXMLChars(&storage, XCS("")); 4984 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED) 4985 xml_failure(g_parser); 4986 CharData_CheckXMLChars(&storage, expected1); 4987 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 4988 xml_failure(g_parser); 4989 CharData_CheckXMLChars(&storage, expected2); 4990 } 4991 END_TEST 4992 4993 /* Test syntax error is caught at parse resumption */ 4994 START_TEST(test_resume_entity_with_syntax_error) { 4995 const char *text = "<!DOCTYPE doc [\n" 4996 "<!ENTITY foo '<suspend>Hi</wombat>'>\n" 4997 "]>\n" 4998 "<doc>&foo;</doc>\n"; 4999 5000 XML_SetStartElementHandler(g_parser, start_element_suspender); 5001 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5002 != XML_STATUS_SUSPENDED) 5003 xml_failure(g_parser); 5004 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 5005 fail("Syntax error in entity not faulted"); 5006 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH) 5007 xml_failure(g_parser); 5008 } 5009 END_TEST 5010 5011 /* Test suspending and resuming in a parameter entity substitution */ 5012 static void XMLCALL 5013 element_decl_suspender(void *userData, const XML_Char *name, 5014 XML_Content *model) { 5015 UNUSED_P(userData); 5016 UNUSED_P(name); 5017 XML_StopParser(g_parser, XML_TRUE); 5018 XML_FreeContentModel(g_parser, model); 5019 } 5020 5021 START_TEST(test_suspend_resume_parameter_entity) { 5022 const char *text = "<!DOCTYPE doc [\n" 5023 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n" 5024 "%foo;\n" 5025 "]>\n" 5026 "<doc>Hello, world</doc>"; 5027 const XML_Char *expected = XCS("Hello, world"); 5028 CharData storage; 5029 5030 CharData_Init(&storage); 5031 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5032 XML_SetElementDeclHandler(g_parser, element_decl_suspender); 5033 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 5034 XML_SetUserData(g_parser, &storage); 5035 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5036 != XML_STATUS_SUSPENDED) 5037 xml_failure(g_parser); 5038 CharData_CheckXMLChars(&storage, XCS("")); 5039 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 5040 xml_failure(g_parser); 5041 CharData_CheckXMLChars(&storage, expected); 5042 } 5043 END_TEST 5044 5045 /* Test attempting to use parser after an error is faulted */ 5046 START_TEST(test_restart_on_error) { 5047 const char *text = "<$doc><doc></doc>"; 5048 5049 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5050 != XML_STATUS_ERROR) 5051 fail("Invalid tag name not faulted"); 5052 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 5053 xml_failure(g_parser); 5054 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 5055 fail("Restarting invalid parse not faulted"); 5056 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 5057 xml_failure(g_parser); 5058 } 5059 END_TEST 5060 5061 /* Test that angle brackets in an attribute default value are faulted */ 5062 START_TEST(test_reject_lt_in_attribute_value) { 5063 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n" 5064 "<doc></doc>"; 5065 5066 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5067 "Bad attribute default not faulted"); 5068 } 5069 END_TEST 5070 5071 START_TEST(test_reject_unfinished_param_in_att_value) { 5072 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n" 5073 "<doc></doc>"; 5074 5075 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5076 "Bad attribute default not faulted"); 5077 } 5078 END_TEST 5079 5080 START_TEST(test_trailing_cr_in_att_value) { 5081 const char *text = "<doc a='value\r'/>"; 5082 5083 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5084 == XML_STATUS_ERROR) 5085 xml_failure(g_parser); 5086 } 5087 END_TEST 5088 5089 /* Try parsing a general entity within a parameter entity in a 5090 * standalone internal DTD. Covers a corner case in the parser. 5091 */ 5092 START_TEST(test_standalone_internal_entity) { 5093 const char *text = "<?xml version='1.0' standalone='yes' ?>\n" 5094 "<!DOCTYPE doc [\n" 5095 " <!ELEMENT doc (#PCDATA)>\n" 5096 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n" 5097 " <!ENTITY ge 'AttDefaultValue'>\n" 5098 " %pe;\n" 5099 "]>\n" 5100 "<doc att2='any'/>"; 5101 5102 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5103 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5104 == XML_STATUS_ERROR) 5105 xml_failure(g_parser); 5106 } 5107 END_TEST 5108 5109 /* Test that a reference to an unknown external entity is skipped */ 5110 START_TEST(test_skipped_external_entity) { 5111 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5112 "<doc></doc>\n"; 5113 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n" 5114 "<!ENTITY % e2 '%e1;'>\n", 5115 NULL, NULL}; 5116 5117 XML_SetUserData(g_parser, &test_data); 5118 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5119 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5120 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5121 == XML_STATUS_ERROR) 5122 xml_failure(g_parser); 5123 } 5124 END_TEST 5125 5126 /* Test a different form of unknown external entity */ 5127 typedef struct ext_hdlr_data { 5128 const char *parse_text; 5129 XML_ExternalEntityRefHandler handler; 5130 } ExtHdlrData; 5131 5132 static int XMLCALL 5133 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context, 5134 const XML_Char *base, const XML_Char *systemId, 5135 const XML_Char *publicId) { 5136 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser); 5137 XML_Parser ext_parser; 5138 5139 UNUSED_P(base); 5140 UNUSED_P(systemId); 5141 UNUSED_P(publicId); 5142 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 5143 if (ext_parser == NULL) 5144 fail("Could not create external entity parser."); 5145 /* Use the requested entity parser for further externals */ 5146 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler); 5147 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text, 5148 (int)strlen(test_data->parse_text), XML_TRUE) 5149 == XML_STATUS_ERROR) { 5150 xml_failure(ext_parser); 5151 } 5152 5153 XML_ParserFree(ext_parser); 5154 return XML_STATUS_OK; 5155 } 5156 5157 START_TEST(test_skipped_null_loaded_ext_entity) { 5158 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5159 "<doc />"; 5160 ExtHdlrData test_data 5161 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5162 "<!ENTITY % pe2 '%pe1;'>\n" 5163 "%pe2;\n", 5164 external_entity_null_loader}; 5165 5166 XML_SetUserData(g_parser, &test_data); 5167 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5168 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5169 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5170 == XML_STATUS_ERROR) 5171 xml_failure(g_parser); 5172 } 5173 END_TEST 5174 5175 START_TEST(test_skipped_unloaded_ext_entity) { 5176 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5177 "<doc />"; 5178 ExtHdlrData test_data 5179 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5180 "<!ENTITY % pe2 '%pe1;'>\n" 5181 "%pe2;\n", 5182 NULL}; 5183 5184 XML_SetUserData(g_parser, &test_data); 5185 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5186 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5187 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5188 == XML_STATUS_ERROR) 5189 xml_failure(g_parser); 5190 } 5191 END_TEST 5192 5193 /* Test that a parameter entity value ending with a carriage return 5194 * has it translated internally into a newline. 5195 */ 5196 START_TEST(test_param_entity_with_trailing_cr) { 5197 #define PARAM_ENTITY_NAME "pe" 5198 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">" 5199 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5200 "<doc/>"; 5201 ExtTest test_data 5202 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n" 5203 "%" PARAM_ENTITY_NAME ";\n", 5204 NULL, NULL}; 5205 5206 XML_SetUserData(g_parser, &test_data); 5207 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5208 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5209 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler); 5210 entity_name_to_match = XCS(PARAM_ENTITY_NAME); 5211 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n"); 5212 entity_match_flag = ENTITY_MATCH_NOT_FOUND; 5213 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5214 == XML_STATUS_ERROR) 5215 xml_failure(g_parser); 5216 if (entity_match_flag == ENTITY_MATCH_FAIL) 5217 fail("Parameter entity CR->NEWLINE conversion failed"); 5218 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND) 5219 fail("Parameter entity not parsed"); 5220 } 5221 #undef PARAM_ENTITY_NAME 5222 #undef PARAM_ENTITY_CORE_VALUE 5223 END_TEST 5224 5225 START_TEST(test_invalid_character_entity) { 5226 const char *text = "<!DOCTYPE doc [\n" 5227 " <!ENTITY entity '�'>\n" 5228 "]>\n" 5229 "<doc>&entity;</doc>"; 5230 5231 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5232 "Out of range character reference not faulted"); 5233 } 5234 END_TEST 5235 5236 START_TEST(test_invalid_character_entity_2) { 5237 const char *text = "<!DOCTYPE doc [\n" 5238 " <!ENTITY entity '&#xg0;'>\n" 5239 "]>\n" 5240 "<doc>&entity;</doc>"; 5241 5242 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5243 "Out of range character reference not faulted"); 5244 } 5245 END_TEST 5246 5247 START_TEST(test_invalid_character_entity_3) { 5248 const char text[] = 5249 /* <!DOCTYPE doc [\n */ 5250 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 5251 /* U+0E04 = KHO KHWAI 5252 * U+0E08 = CHO CHAN */ 5253 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */ 5254 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 " 5255 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n" 5256 /* ]>\n */ 5257 "\0]\0>\0\n" 5258 /* <doc>&entity;</doc> */ 5259 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>"; 5260 5261 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5262 != XML_STATUS_ERROR) 5263 fail("Invalid start of entity name not faulted"); 5264 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY) 5265 xml_failure(g_parser); 5266 } 5267 END_TEST 5268 5269 START_TEST(test_invalid_character_entity_4) { 5270 const char *text = "<!DOCTYPE doc [\n" 5271 " <!ENTITY entity '�'>\n" /* = � */ 5272 "]>\n" 5273 "<doc>&entity;</doc>"; 5274 5275 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5276 "Out of range character reference not faulted"); 5277 } 5278 END_TEST 5279 5280 /* Test that processing instructions are picked up by a default handler */ 5281 START_TEST(test_pi_handled_in_default) { 5282 const char *text = "<?test processing instruction?>\n<doc/>"; 5283 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>"); 5284 CharData storage; 5285 5286 CharData_Init(&storage); 5287 XML_SetDefaultHandler(g_parser, accumulate_characters); 5288 XML_SetUserData(g_parser, &storage); 5289 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5290 == XML_STATUS_ERROR) 5291 xml_failure(g_parser); 5292 CharData_CheckXMLChars(&storage, expected); 5293 } 5294 END_TEST 5295 5296 /* Test that comments are picked up by a default handler */ 5297 START_TEST(test_comment_handled_in_default) { 5298 const char *text = "<!-- This is a comment -->\n<doc/>"; 5299 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>"); 5300 CharData storage; 5301 5302 CharData_Init(&storage); 5303 XML_SetDefaultHandler(g_parser, accumulate_characters); 5304 XML_SetUserData(g_parser, &storage); 5305 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5306 == XML_STATUS_ERROR) 5307 xml_failure(g_parser); 5308 CharData_CheckXMLChars(&storage, expected); 5309 } 5310 END_TEST 5311 5312 /* Test PIs that look almost but not quite like XML declarations */ 5313 static void XMLCALL 5314 accumulate_pi_characters(void *userData, const XML_Char *target, 5315 const XML_Char *data) { 5316 CharData *storage = (CharData *)userData; 5317 5318 CharData_AppendXMLChars(storage, target, -1); 5319 CharData_AppendXMLChars(storage, XCS(": "), 2); 5320 CharData_AppendXMLChars(storage, data, -1); 5321 CharData_AppendXMLChars(storage, XCS("\n"), 1); 5322 } 5323 5324 START_TEST(test_pi_yml) { 5325 const char *text = "<?yml something like data?><doc/>"; 5326 const XML_Char *expected = XCS("yml: something like data\n"); 5327 CharData storage; 5328 5329 CharData_Init(&storage); 5330 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5331 XML_SetUserData(g_parser, &storage); 5332 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5333 == XML_STATUS_ERROR) 5334 xml_failure(g_parser); 5335 CharData_CheckXMLChars(&storage, expected); 5336 } 5337 END_TEST 5338 5339 START_TEST(test_pi_xnl) { 5340 const char *text = "<?xnl nothing like data?><doc/>"; 5341 const XML_Char *expected = XCS("xnl: nothing like data\n"); 5342 CharData storage; 5343 5344 CharData_Init(&storage); 5345 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5346 XML_SetUserData(g_parser, &storage); 5347 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5348 == XML_STATUS_ERROR) 5349 xml_failure(g_parser); 5350 CharData_CheckXMLChars(&storage, expected); 5351 } 5352 END_TEST 5353 5354 START_TEST(test_pi_xmm) { 5355 const char *text = "<?xmm everything like data?><doc/>"; 5356 const XML_Char *expected = XCS("xmm: everything like data\n"); 5357 CharData storage; 5358 5359 CharData_Init(&storage); 5360 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5361 XML_SetUserData(g_parser, &storage); 5362 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5363 == XML_STATUS_ERROR) 5364 xml_failure(g_parser); 5365 CharData_CheckXMLChars(&storage, expected); 5366 } 5367 END_TEST 5368 5369 START_TEST(test_utf16_pi) { 5370 const char text[] = 5371 /* <?{KHO KHWAI}{CHO CHAN}?> 5372 * where {KHO KHWAI} = U+0E04 5373 * and {CHO CHAN} = U+0E08 5374 */ 5375 "<\0?\0\x04\x0e\x08\x0e?\0>\0" 5376 /* <q/> */ 5377 "<\0q\0/\0>\0"; 5378 #ifdef XML_UNICODE 5379 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5380 #else 5381 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5382 #endif 5383 CharData storage; 5384 5385 CharData_Init(&storage); 5386 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5387 XML_SetUserData(g_parser, &storage); 5388 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5389 == XML_STATUS_ERROR) 5390 xml_failure(g_parser); 5391 CharData_CheckXMLChars(&storage, expected); 5392 } 5393 END_TEST 5394 5395 START_TEST(test_utf16_be_pi) { 5396 const char text[] = 5397 /* <?{KHO KHWAI}{CHO CHAN}?> 5398 * where {KHO KHWAI} = U+0E04 5399 * and {CHO CHAN} = U+0E08 5400 */ 5401 "\0<\0?\x0e\x04\x0e\x08\0?\0>" 5402 /* <q/> */ 5403 "\0<\0q\0/\0>"; 5404 #ifdef XML_UNICODE 5405 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5406 #else 5407 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5408 #endif 5409 CharData storage; 5410 5411 CharData_Init(&storage); 5412 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5413 XML_SetUserData(g_parser, &storage); 5414 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5415 == XML_STATUS_ERROR) 5416 xml_failure(g_parser); 5417 CharData_CheckXMLChars(&storage, expected); 5418 } 5419 END_TEST 5420 5421 /* Test that comments can be picked up and translated */ 5422 static void XMLCALL 5423 accumulate_comment(void *userData, const XML_Char *data) { 5424 CharData *storage = (CharData *)userData; 5425 5426 CharData_AppendXMLChars(storage, data, -1); 5427 } 5428 5429 START_TEST(test_utf16_be_comment) { 5430 const char text[] = 5431 /* <!-- Comment A --> */ 5432 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n" 5433 /* <doc/> */ 5434 "\0<\0d\0o\0c\0/\0>"; 5435 const XML_Char *expected = XCS(" Comment A "); 5436 CharData storage; 5437 5438 CharData_Init(&storage); 5439 XML_SetCommentHandler(g_parser, accumulate_comment); 5440 XML_SetUserData(g_parser, &storage); 5441 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5442 == XML_STATUS_ERROR) 5443 xml_failure(g_parser); 5444 CharData_CheckXMLChars(&storage, expected); 5445 } 5446 END_TEST 5447 5448 START_TEST(test_utf16_le_comment) { 5449 const char text[] = 5450 /* <!-- Comment B --> */ 5451 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0" 5452 /* <doc/> */ 5453 "<\0d\0o\0c\0/\0>\0"; 5454 const XML_Char *expected = XCS(" Comment B "); 5455 CharData storage; 5456 5457 CharData_Init(&storage); 5458 XML_SetCommentHandler(g_parser, accumulate_comment); 5459 XML_SetUserData(g_parser, &storage); 5460 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5461 == XML_STATUS_ERROR) 5462 xml_failure(g_parser); 5463 CharData_CheckXMLChars(&storage, expected); 5464 } 5465 END_TEST 5466 5467 /* Test that the unknown encoding handler with map entries that expect 5468 * conversion but no conversion function is faulted 5469 */ 5470 static int XMLCALL 5471 failing_converter(void *data, const char *s) { 5472 UNUSED_P(data); 5473 UNUSED_P(s); 5474 /* Always claim to have failed */ 5475 return -1; 5476 } 5477 5478 static int XMLCALL 5479 prefix_converter(void *data, const char *s) { 5480 UNUSED_P(data); 5481 /* If the first byte is 0xff, raise an error */ 5482 if (s[0] == (char)-1) 5483 return -1; 5484 /* Just add the low bits of the first byte to the second */ 5485 return (s[1] + (s[0] & 0x7f)) & 0x01ff; 5486 } 5487 5488 static int XMLCALL 5489 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) { 5490 int i; 5491 int high_map = -2; /* Assume a 2-byte sequence */ 5492 5493 if (! xcstrcmp(encoding, XCS("invalid-9")) 5494 || ! xcstrcmp(encoding, XCS("ascii-like")) 5495 || ! xcstrcmp(encoding, XCS("invalid-len")) 5496 || ! xcstrcmp(encoding, XCS("invalid-a")) 5497 || ! xcstrcmp(encoding, XCS("invalid-surrogate")) 5498 || ! xcstrcmp(encoding, XCS("invalid-high"))) 5499 high_map = -1; 5500 5501 for (i = 0; i < 128; ++i) 5502 info->map[i] = i; 5503 for (; i < 256; ++i) 5504 info->map[i] = high_map; 5505 5506 /* If required, put an invalid value in the ASCII entries */ 5507 if (! xcstrcmp(encoding, XCS("invalid-9"))) 5508 info->map[9] = 5; 5509 /* If required, have a top-bit set character starts a 5-byte sequence */ 5510 if (! xcstrcmp(encoding, XCS("invalid-len"))) 5511 info->map[0x81] = -5; 5512 /* If required, make a top-bit set character a valid ASCII character */ 5513 if (! xcstrcmp(encoding, XCS("invalid-a"))) 5514 info->map[0x82] = 'a'; 5515 /* If required, give a top-bit set character a forbidden value, 5516 * what would otherwise be the first of a surrogate pair. 5517 */ 5518 if (! xcstrcmp(encoding, XCS("invalid-surrogate"))) 5519 info->map[0x83] = 0xd801; 5520 /* If required, give a top-bit set character too high a value */ 5521 if (! xcstrcmp(encoding, XCS("invalid-high"))) 5522 info->map[0x84] = 0x010101; 5523 5524 info->data = data; 5525 info->release = NULL; 5526 if (! xcstrcmp(encoding, XCS("failing-conv"))) 5527 info->convert = failing_converter; 5528 else if (! xcstrcmp(encoding, XCS("prefix-conv"))) 5529 info->convert = prefix_converter; 5530 else 5531 info->convert = NULL; 5532 return XML_STATUS_OK; 5533 } 5534 5535 START_TEST(test_missing_encoding_conversion_fn) { 5536 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n" 5537 "<doc>\x81</doc>"; 5538 5539 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5540 /* MiscEncodingHandler sets up an encoding with every top-bit-set 5541 * character introducing a two-byte sequence. For this, it 5542 * requires a convert function. The above function call doesn't 5543 * pass one through, so when BadEncodingHandler actually gets 5544 * called it should supply an invalid encoding. 5545 */ 5546 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5547 "Encoding with missing convert() not faulted"); 5548 } 5549 END_TEST 5550 5551 START_TEST(test_failing_encoding_conversion_fn) { 5552 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n" 5553 "<doc>\x81</doc>"; 5554 5555 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5556 /* BadEncodingHandler sets up an encoding with every top-bit-set 5557 * character introducing a two-byte sequence. For this, it 5558 * requires a convert function. The above function call passes 5559 * one that insists all possible sequences are invalid anyway. 5560 */ 5561 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5562 "Encoding with failing convert() not faulted"); 5563 } 5564 END_TEST 5565 5566 /* Test unknown encoding conversions */ 5567 START_TEST(test_unknown_encoding_success) { 5568 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5569 /* Equivalent to <eoc>Hello, world</eoc> */ 5570 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>"; 5571 5572 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5573 run_character_check(text, XCS("Hello, world")); 5574 } 5575 END_TEST 5576 5577 /* Test bad name character in unknown encoding */ 5578 START_TEST(test_unknown_encoding_bad_name) { 5579 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5580 "<\xff\x64oc>Hello, world</\xff\x64oc>"; 5581 5582 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5583 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5584 "Bad name start in unknown encoding not faulted"); 5585 } 5586 END_TEST 5587 5588 /* Test bad mid-name character in unknown encoding */ 5589 START_TEST(test_unknown_encoding_bad_name_2) { 5590 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5591 "<d\xffoc>Hello, world</d\xffoc>"; 5592 5593 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5594 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5595 "Bad name in unknown encoding not faulted"); 5596 } 5597 END_TEST 5598 5599 /* Test element name that is long enough to fill the conversion buffer 5600 * in an unknown encoding, finishing with an encoded character. 5601 */ 5602 START_TEST(test_unknown_encoding_long_name_1) { 5603 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5604 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>" 5605 "Hi" 5606 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"; 5607 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5608 CharData storage; 5609 5610 CharData_Init(&storage); 5611 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5612 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5613 XML_SetUserData(g_parser, &storage); 5614 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5615 == XML_STATUS_ERROR) 5616 xml_failure(g_parser); 5617 CharData_CheckXMLChars(&storage, expected); 5618 } 5619 END_TEST 5620 5621 /* Test element name that is long enough to fill the conversion buffer 5622 * in an unknown encoding, finishing with an simple character. 5623 */ 5624 START_TEST(test_unknown_encoding_long_name_2) { 5625 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5626 "<abcdefghabcdefghabcdefghijklmnop>" 5627 "Hi" 5628 "</abcdefghabcdefghabcdefghijklmnop>"; 5629 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5630 CharData storage; 5631 5632 CharData_Init(&storage); 5633 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5634 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5635 XML_SetUserData(g_parser, &storage); 5636 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5637 == XML_STATUS_ERROR) 5638 xml_failure(g_parser); 5639 CharData_CheckXMLChars(&storage, expected); 5640 } 5641 END_TEST 5642 5643 START_TEST(test_invalid_unknown_encoding) { 5644 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n" 5645 "<doc>Hello world</doc>"; 5646 5647 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5648 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5649 "Invalid unknown encoding not faulted"); 5650 } 5651 END_TEST 5652 5653 START_TEST(test_unknown_ascii_encoding_ok) { 5654 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5655 "<doc>Hello, world</doc>"; 5656 5657 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5658 run_character_check(text, XCS("Hello, world")); 5659 } 5660 END_TEST 5661 5662 START_TEST(test_unknown_ascii_encoding_fail) { 5663 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5664 "<doc>Hello, \x80 world</doc>"; 5665 5666 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5667 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5668 "Invalid character not faulted"); 5669 } 5670 END_TEST 5671 5672 START_TEST(test_unknown_encoding_invalid_length) { 5673 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n" 5674 "<doc>Hello, world</doc>"; 5675 5676 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5677 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5678 "Invalid unknown encoding not faulted"); 5679 } 5680 END_TEST 5681 5682 START_TEST(test_unknown_encoding_invalid_topbit) { 5683 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n" 5684 "<doc>Hello, world</doc>"; 5685 5686 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5687 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5688 "Invalid unknown encoding not faulted"); 5689 } 5690 END_TEST 5691 5692 START_TEST(test_unknown_encoding_invalid_surrogate) { 5693 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n" 5694 "<doc>Hello, \x82 world</doc>"; 5695 5696 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5697 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5698 "Invalid unknown encoding not faulted"); 5699 } 5700 END_TEST 5701 5702 START_TEST(test_unknown_encoding_invalid_high) { 5703 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n" 5704 "<doc>Hello, world</doc>"; 5705 5706 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5707 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5708 "Invalid unknown encoding not faulted"); 5709 } 5710 END_TEST 5711 5712 START_TEST(test_unknown_encoding_invalid_attr_value) { 5713 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5714 "<doc attr='\xff\x30'/>"; 5715 5716 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5717 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5718 "Invalid attribute valid not faulted"); 5719 } 5720 END_TEST 5721 5722 /* Test an external entity parser set to use latin-1 detects UTF-16 5723 * BOMs correctly. 5724 */ 5725 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 }; 5726 5727 typedef struct ExtTest2 { 5728 const char *parse_text; 5729 int parse_len; 5730 const XML_Char *encoding; 5731 CharData *storage; 5732 enum ee_parse_flags flags; 5733 } ExtTest2; 5734 5735 static int XMLCALL 5736 external_entity_loader2(XML_Parser parser, const XML_Char *context, 5737 const XML_Char *base, const XML_Char *systemId, 5738 const XML_Char *publicId) { 5739 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser); 5740 XML_Parser extparser; 5741 5742 UNUSED_P(base); 5743 UNUSED_P(systemId); 5744 UNUSED_P(publicId); 5745 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 5746 if (extparser == NULL) 5747 fail("Coulr not create external entity parser"); 5748 if (test_data->encoding != NULL) { 5749 if (! XML_SetEncoding(extparser, test_data->encoding)) 5750 fail("XML_SetEncoding() ignored for external entity"); 5751 } 5752 if (test_data->flags & EE_PARSE_FULL_BUFFER) { 5753 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 5754 XML_TRUE) 5755 == XML_STATUS_ERROR) { 5756 xml_failure(extparser); 5757 } 5758 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text, 5759 test_data->parse_len, XML_TRUE) 5760 == XML_STATUS_ERROR) { 5761 xml_failure(extparser); 5762 } 5763 5764 XML_ParserFree(extparser); 5765 return XML_STATUS_OK; 5766 } 5767 5768 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */ 5769 static void XMLCALL 5770 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) { 5771 ExtTest2 *test_data = (ExtTest2 *)userData; 5772 accumulate_characters(test_data->storage, s, len); 5773 } 5774 5775 START_TEST(test_ext_entity_latin1_utf16le_bom) { 5776 const char *text = "<!DOCTYPE doc [\n" 5777 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5778 "]>\n" 5779 "<doc>&en;</doc>"; 5780 ExtTest2 test_data 5781 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5782 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5783 * 0x4c = L and 0x20 is a space 5784 */ 5785 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5786 #ifdef XML_UNICODE 5787 const XML_Char *expected = XCS("\x00ff\x00feL "); 5788 #else 5789 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5790 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5791 #endif 5792 CharData storage; 5793 5794 CharData_Init(&storage); 5795 test_data.storage = &storage; 5796 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5797 XML_SetUserData(g_parser, &test_data); 5798 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5799 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5800 == XML_STATUS_ERROR) 5801 xml_failure(g_parser); 5802 CharData_CheckXMLChars(&storage, expected); 5803 } 5804 END_TEST 5805 5806 START_TEST(test_ext_entity_latin1_utf16be_bom) { 5807 const char *text = "<!DOCTYPE doc [\n" 5808 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5809 "]>\n" 5810 "<doc>&en;</doc>"; 5811 ExtTest2 test_data 5812 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5813 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5814 * 0x4c = L and 0x20 is a space 5815 */ 5816 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5817 #ifdef XML_UNICODE 5818 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5819 #else 5820 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5821 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L"); 5822 #endif 5823 CharData storage; 5824 5825 CharData_Init(&storage); 5826 test_data.storage = &storage; 5827 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5828 XML_SetUserData(g_parser, &test_data); 5829 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5830 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5831 == XML_STATUS_ERROR) 5832 xml_failure(g_parser); 5833 CharData_CheckXMLChars(&storage, expected); 5834 } 5835 END_TEST 5836 5837 /* Parsing the full buffer rather than a byte at a time makes a 5838 * difference to the encoding scanning code, so repeat the above tests 5839 * without breaking them down by byte. 5840 */ 5841 START_TEST(test_ext_entity_latin1_utf16le_bom2) { 5842 const char *text = "<!DOCTYPE doc [\n" 5843 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5844 "]>\n" 5845 "<doc>&en;</doc>"; 5846 ExtTest2 test_data 5847 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5848 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5849 * 0x4c = L and 0x20 is a space 5850 */ 5851 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5852 #ifdef XML_UNICODE 5853 const XML_Char *expected = XCS("\x00ff\x00feL "); 5854 #else 5855 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5856 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5857 #endif 5858 CharData storage; 5859 5860 CharData_Init(&storage); 5861 test_data.storage = &storage; 5862 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5863 XML_SetUserData(g_parser, &test_data); 5864 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5865 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5866 == XML_STATUS_ERROR) 5867 xml_failure(g_parser); 5868 CharData_CheckXMLChars(&storage, expected); 5869 } 5870 END_TEST 5871 5872 START_TEST(test_ext_entity_latin1_utf16be_bom2) { 5873 const char *text = "<!DOCTYPE doc [\n" 5874 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5875 "]>\n" 5876 "<doc>&en;</doc>"; 5877 ExtTest2 test_data 5878 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5879 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5880 * 0x4c = L and 0x20 is a space 5881 */ 5882 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5883 #ifdef XML_UNICODE 5884 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5885 #else 5886 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5887 const XML_Char *expected = "\xc3\xbe\xc3\xbf L"; 5888 #endif 5889 CharData storage; 5890 5891 CharData_Init(&storage); 5892 test_data.storage = &storage; 5893 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5894 XML_SetUserData(g_parser, &test_data); 5895 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5896 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5897 == XML_STATUS_ERROR) 5898 xml_failure(g_parser); 5899 CharData_CheckXMLChars(&storage, expected); 5900 } 5901 END_TEST 5902 5903 /* Test little-endian UTF-16 given an explicit big-endian encoding */ 5904 START_TEST(test_ext_entity_utf16_be) { 5905 const char *text = "<!DOCTYPE doc [\n" 5906 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5907 "]>\n" 5908 "<doc>&en;</doc>"; 5909 ExtTest2 test_data 5910 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE}; 5911 #ifdef XML_UNICODE 5912 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 5913 #else 5914 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 5915 "\xe6\x94\x80" /* U+6500 */ 5916 "\xe2\xbc\x80" /* U+2F00 */ 5917 "\xe3\xb8\x80"); /* U+3E00 */ 5918 #endif 5919 CharData storage; 5920 5921 CharData_Init(&storage); 5922 test_data.storage = &storage; 5923 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5924 XML_SetUserData(g_parser, &test_data); 5925 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5926 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5927 == XML_STATUS_ERROR) 5928 xml_failure(g_parser); 5929 CharData_CheckXMLChars(&storage, expected); 5930 } 5931 END_TEST 5932 5933 /* Test big-endian UTF-16 given an explicit little-endian encoding */ 5934 START_TEST(test_ext_entity_utf16_le) { 5935 const char *text = "<!DOCTYPE doc [\n" 5936 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5937 "]>\n" 5938 "<doc>&en;</doc>"; 5939 ExtTest2 test_data 5940 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE}; 5941 #ifdef XML_UNICODE 5942 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 5943 #else 5944 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 5945 "\xe6\x94\x80" /* U+6500 */ 5946 "\xe2\xbc\x80" /* U+2F00 */ 5947 "\xe3\xb8\x80"); /* U+3E00 */ 5948 #endif 5949 CharData storage; 5950 5951 CharData_Init(&storage); 5952 test_data.storage = &storage; 5953 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5954 XML_SetUserData(g_parser, &test_data); 5955 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5956 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5957 == XML_STATUS_ERROR) 5958 xml_failure(g_parser); 5959 CharData_CheckXMLChars(&storage, expected); 5960 } 5961 END_TEST 5962 5963 /* Test little-endian UTF-16 given no explicit encoding. 5964 * The existing default encoding (UTF-8) is assumed to hold without a 5965 * BOM to contradict it, so the entity value will in fact provoke an 5966 * error because 0x00 is not a valid XML character. We parse the 5967 * whole buffer in one go rather than feeding it in byte by byte to 5968 * exercise different code paths in the initial scanning routines. 5969 */ 5970 typedef struct ExtFaults2 { 5971 const char *parse_text; 5972 int parse_len; 5973 const char *fail_text; 5974 const XML_Char *encoding; 5975 enum XML_Error error; 5976 } ExtFaults2; 5977 5978 static int XMLCALL 5979 external_entity_faulter2(XML_Parser parser, const XML_Char *context, 5980 const XML_Char *base, const XML_Char *systemId, 5981 const XML_Char *publicId) { 5982 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser); 5983 XML_Parser extparser; 5984 5985 UNUSED_P(base); 5986 UNUSED_P(systemId); 5987 UNUSED_P(publicId); 5988 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 5989 if (extparser == NULL) 5990 fail("Could not create external entity parser"); 5991 if (test_data->encoding != NULL) { 5992 if (! XML_SetEncoding(extparser, test_data->encoding)) 5993 fail("XML_SetEncoding() ignored for external entity"); 5994 } 5995 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 5996 XML_TRUE) 5997 != XML_STATUS_ERROR) 5998 fail(test_data->fail_text); 5999 if (XML_GetErrorCode(extparser) != test_data->error) 6000 xml_failure(extparser); 6001 6002 XML_ParserFree(extparser); 6003 return XML_STATUS_ERROR; 6004 } 6005 6006 START_TEST(test_ext_entity_utf16_unknown) { 6007 const char *text = "<!DOCTYPE doc [\n" 6008 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 6009 "]>\n" 6010 "<doc>&en;</doc>"; 6011 ExtFaults2 test_data 6012 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL, 6013 XML_ERROR_INVALID_TOKEN}; 6014 6015 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2); 6016 XML_SetUserData(g_parser, &test_data); 6017 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 6018 "Invalid character should not have been accepted"); 6019 } 6020 END_TEST 6021 6022 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */ 6023 START_TEST(test_ext_entity_utf8_non_bom) { 6024 const char *text = "<!DOCTYPE doc [\n" 6025 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 6026 "]>\n" 6027 "<doc>&en;</doc>"; 6028 ExtTest2 test_data 6029 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */ 6030 3, NULL, NULL, EE_PARSE_NONE}; 6031 #ifdef XML_UNICODE 6032 const XML_Char *expected = XCS("\xfec0"); 6033 #else 6034 const XML_Char *expected = XCS("\xef\xbb\x80"); 6035 #endif 6036 CharData storage; 6037 6038 CharData_Init(&storage); 6039 test_data.storage = &storage; 6040 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6041 XML_SetUserData(g_parser, &test_data); 6042 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6043 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6044 == XML_STATUS_ERROR) 6045 xml_failure(g_parser); 6046 CharData_CheckXMLChars(&storage, expected); 6047 } 6048 END_TEST 6049 6050 /* Test that UTF-8 in a CDATA section is correctly passed through */ 6051 START_TEST(test_utf8_in_cdata_section) { 6052 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>"; 6053 #ifdef XML_UNICODE 6054 const XML_Char *expected = XCS("one \x00e9 two"); 6055 #else 6056 const XML_Char *expected = XCS("one \xc3\xa9 two"); 6057 #endif 6058 6059 run_character_check(text, expected); 6060 } 6061 END_TEST 6062 6063 /* Test that little-endian UTF-16 in a CDATA section is handled */ 6064 START_TEST(test_utf8_in_cdata_section_2) { 6065 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>"; 6066 #ifdef XML_UNICODE 6067 const XML_Char *expected = XCS("\x00e9]\x00e9two"); 6068 #else 6069 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two"); 6070 #endif 6071 6072 run_character_check(text, expected); 6073 } 6074 END_TEST 6075 6076 START_TEST(test_utf8_in_start_tags) { 6077 struct test_case { 6078 bool goodName; 6079 bool goodNameStart; 6080 const char *tagName; 6081 }; 6082 6083 // The idea with the tests below is this: 6084 // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences 6085 // go to isNever and are hence not a concern. 6086 // 6087 // We start with a character that is a valid name character 6088 // (or even name-start character, see XML 1.0r4 spec) and then we flip 6089 // single bits at places where (1) the result leaves the UTF-8 encoding space 6090 // and (2) we stay in the same n-byte sequence family. 6091 // 6092 // The flipped bits are highlighted in angle brackets in comments, 6093 // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped 6094 // the most significant bit to 1 to leave UTF-8 encoding space. 6095 struct test_case cases[] = { 6096 // 1-byte UTF-8: [0xxx xxxx] 6097 {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':' 6098 {false, false, "\xBA"}, // [<1>011 1010] 6099 {true, false, "\x39"}, // [0011 1001] = ASCII nine '9' 6100 {false, false, "\xB9"}, // [<1>011 1001] 6101 6102 // 2-byte UTF-8: [110x xxxx] [10xx xxxx] 6103 {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] = 6104 // Arabic small waw U+06E5 6105 {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101] 6106 {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101] 6107 {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101] 6108 {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] = 6109 // combining char U+0301 6110 {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001] 6111 {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001] 6112 {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001] 6113 6114 // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx] 6115 {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] = 6116 // Devanagari Letter A U+0905 6117 {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101] 6118 {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101] 6119 {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101] 6120 {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101] 6121 {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101] 6122 {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] = 6123 // combining char U+0901 6124 {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001] 6125 {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001] 6126 {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001] 6127 {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001] 6128 {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001] 6129 }; 6130 const bool atNameStart[] = {true, false}; 6131 6132 size_t i = 0; 6133 char doc[1024]; 6134 size_t failCount = 0; 6135 6136 for (; i < sizeof(cases) / sizeof(cases[0]); i++) { 6137 size_t j = 0; 6138 for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) { 6139 const bool expectedSuccess 6140 = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName; 6141 sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName); 6142 XML_Parser parser = XML_ParserCreate(NULL); 6143 6144 const enum XML_Status status 6145 = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE); 6146 6147 bool success = true; 6148 if ((status == XML_STATUS_OK) != expectedSuccess) { 6149 success = false; 6150 } 6151 if ((status == XML_STATUS_ERROR) 6152 && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) { 6153 success = false; 6154 } 6155 6156 if (! success) { 6157 fprintf( 6158 stderr, 6159 "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n", 6160 (unsigned)i + 1u, atNameStart[j] ? " " : "not ", 6161 (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser)); 6162 failCount++; 6163 } 6164 6165 XML_ParserFree(parser); 6166 } 6167 } 6168 6169 if (failCount > 0) { 6170 fail("UTF-8 regression detected"); 6171 } 6172 } 6173 END_TEST 6174 6175 /* Test trailing spaces in elements are accepted */ 6176 static void XMLCALL 6177 record_element_end_handler(void *userData, const XML_Char *name) { 6178 CharData *storage = (CharData *)userData; 6179 6180 CharData_AppendXMLChars(storage, XCS("/"), 1); 6181 CharData_AppendXMLChars(storage, name, -1); 6182 } 6183 6184 START_TEST(test_trailing_spaces_in_elements) { 6185 const char *text = "<doc >Hi</doc >"; 6186 const XML_Char *expected = XCS("doc/doc"); 6187 CharData storage; 6188 6189 CharData_Init(&storage); 6190 XML_SetElementHandler(g_parser, record_element_start_handler, 6191 record_element_end_handler); 6192 XML_SetUserData(g_parser, &storage); 6193 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6194 == XML_STATUS_ERROR) 6195 xml_failure(g_parser); 6196 CharData_CheckXMLChars(&storage, expected); 6197 } 6198 END_TEST 6199 6200 START_TEST(test_utf16_attribute) { 6201 const char text[] = 6202 /* <d {KHO KHWAI}{CHO CHAN}='a'/> 6203 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6204 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6205 */ 6206 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0"; 6207 const XML_Char *expected = XCS("a"); 6208 CharData storage; 6209 6210 CharData_Init(&storage); 6211 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6212 XML_SetUserData(g_parser, &storage); 6213 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6214 == XML_STATUS_ERROR) 6215 xml_failure(g_parser); 6216 CharData_CheckXMLChars(&storage, expected); 6217 } 6218 END_TEST 6219 6220 START_TEST(test_utf16_second_attr) { 6221 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/> 6222 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6223 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6224 */ 6225 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0" 6226 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0"; 6227 const XML_Char *expected = XCS("1"); 6228 CharData storage; 6229 6230 CharData_Init(&storage); 6231 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6232 XML_SetUserData(g_parser, &storage); 6233 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6234 == XML_STATUS_ERROR) 6235 xml_failure(g_parser); 6236 CharData_CheckXMLChars(&storage, expected); 6237 } 6238 END_TEST 6239 6240 START_TEST(test_attr_after_solidus) { 6241 const char *text = "<doc attr1='a' / attr2='b'>"; 6242 6243 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted"); 6244 } 6245 END_TEST 6246 6247 static void XMLCALL 6248 accumulate_entity_decl(void *userData, const XML_Char *entityName, 6249 int is_parameter_entity, const XML_Char *value, 6250 int value_length, const XML_Char *base, 6251 const XML_Char *systemId, const XML_Char *publicId, 6252 const XML_Char *notationName) { 6253 CharData *storage = (CharData *)userData; 6254 6255 UNUSED_P(is_parameter_entity); 6256 UNUSED_P(base); 6257 UNUSED_P(systemId); 6258 UNUSED_P(publicId); 6259 UNUSED_P(notationName); 6260 CharData_AppendXMLChars(storage, entityName, -1); 6261 CharData_AppendXMLChars(storage, XCS("="), 1); 6262 CharData_AppendXMLChars(storage, value, value_length); 6263 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6264 } 6265 6266 START_TEST(test_utf16_pe) { 6267 /* <!DOCTYPE doc [ 6268 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'> 6269 * %{KHO KHWAI}{CHO CHAN}; 6270 * ]> 6271 * <doc></doc> 6272 * 6273 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6274 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6275 */ 6276 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 6277 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 " 6278 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 " 6279 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n" 6280 "\0%\x0e\x04\x0e\x08\0;\0\n" 6281 "\0]\0>\0\n" 6282 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>"; 6283 #ifdef XML_UNICODE 6284 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n"); 6285 #else 6286 const XML_Char *expected 6287 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n"); 6288 #endif 6289 CharData storage; 6290 6291 CharData_Init(&storage); 6292 XML_SetUserData(g_parser, &storage); 6293 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl); 6294 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6295 == XML_STATUS_ERROR) 6296 xml_failure(g_parser); 6297 CharData_CheckXMLChars(&storage, expected); 6298 } 6299 END_TEST 6300 6301 /* Test that duff attribute description keywords are rejected */ 6302 START_TEST(test_bad_attr_desc_keyword) { 6303 const char *text = "<!DOCTYPE doc [\n" 6304 " <!ATTLIST doc attr CDATA #!IMPLIED>\n" 6305 "]>\n" 6306 "<doc />"; 6307 6308 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6309 "Bad keyword !IMPLIED not faulted"); 6310 } 6311 END_TEST 6312 6313 /* Test that an invalid attribute description keyword consisting of 6314 * UTF-16 characters with their top bytes non-zero are correctly 6315 * faulted 6316 */ 6317 START_TEST(test_bad_attr_desc_keyword_utf16) { 6318 /* <!DOCTYPE d [ 6319 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}> 6320 * ]><d/> 6321 * 6322 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6323 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6324 */ 6325 const char text[] 6326 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6327 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 " 6328 "\0#\x0e\x04\x0e\x08\0>\0\n" 6329 "\0]\0>\0<\0d\0/\0>"; 6330 6331 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6332 != XML_STATUS_ERROR) 6333 fail("Invalid UTF16 attribute keyword not faulted"); 6334 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6335 xml_failure(g_parser); 6336 } 6337 END_TEST 6338 6339 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this 6340 * using prefix-encoding (see above) to trigger specific code paths 6341 */ 6342 START_TEST(test_bad_doctype) { 6343 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 6344 "<!DOCTYPE doc [ \x80\x44 ]><doc/>"; 6345 6346 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6347 expect_failure(text, XML_ERROR_SYNTAX, 6348 "Invalid bytes in DOCTYPE not faulted"); 6349 } 6350 END_TEST 6351 6352 START_TEST(test_bad_doctype_utf8) { 6353 const char *text = "<!DOCTYPE \xDB\x25" 6354 "doc><doc/>"; // [1101 1011] [<0>010 0101] 6355 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6356 "Invalid UTF-8 in DOCTYPE not faulted"); 6357 } 6358 END_TEST 6359 6360 START_TEST(test_bad_doctype_utf16) { 6361 const char text[] = 6362 /* <!DOCTYPE doc [ \x06f2 ]><doc/> 6363 * 6364 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number 6365 * (name character) but not a valid letter (name start character) 6366 */ 6367 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 " 6368 "\x06\xf2" 6369 "\0 \0]\0>\0<\0d\0o\0c\0/\0>"; 6370 6371 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6372 != XML_STATUS_ERROR) 6373 fail("Invalid bytes in DOCTYPE not faulted"); 6374 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6375 xml_failure(g_parser); 6376 } 6377 END_TEST 6378 6379 START_TEST(test_bad_doctype_plus) { 6380 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n" 6381 "<1+>&foo;</1+>"; 6382 6383 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6384 "'+' in document name not faulted"); 6385 } 6386 END_TEST 6387 6388 START_TEST(test_bad_doctype_star) { 6389 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n" 6390 "<1*>&foo;</1*>"; 6391 6392 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6393 "'*' in document name not faulted"); 6394 } 6395 END_TEST 6396 6397 START_TEST(test_bad_doctype_query) { 6398 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n" 6399 "<1?>&foo;</1?>"; 6400 6401 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6402 "'?' in document name not faulted"); 6403 } 6404 END_TEST 6405 6406 START_TEST(test_unknown_encoding_bad_ignore) { 6407 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>" 6408 "<!DOCTYPE doc SYSTEM 'foo'>" 6409 "<doc><e>&entity;</e></doc>"; 6410 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>", 6411 "Invalid character not faulted", XCS("prefix-conv"), 6412 XML_ERROR_INVALID_TOKEN}; 6413 6414 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6415 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6416 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 6417 XML_SetUserData(g_parser, &fault); 6418 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 6419 "Bad IGNORE section with unknown encoding not failed"); 6420 } 6421 END_TEST 6422 6423 START_TEST(test_entity_in_utf16_be_attr) { 6424 const char text[] = 6425 /* <e a='ä ä'></e> */ 6426 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 " 6427 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>"; 6428 #ifdef XML_UNICODE 6429 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6430 #else 6431 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6432 #endif 6433 CharData storage; 6434 6435 CharData_Init(&storage); 6436 XML_SetUserData(g_parser, &storage); 6437 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6438 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6439 == XML_STATUS_ERROR) 6440 xml_failure(g_parser); 6441 CharData_CheckXMLChars(&storage, expected); 6442 } 6443 END_TEST 6444 6445 START_TEST(test_entity_in_utf16_le_attr) { 6446 const char text[] = 6447 /* <e a='ä ä'></e> */ 6448 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0" 6449 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0"; 6450 #ifdef XML_UNICODE 6451 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6452 #else 6453 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6454 #endif 6455 CharData storage; 6456 6457 CharData_Init(&storage); 6458 XML_SetUserData(g_parser, &storage); 6459 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6460 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6461 == XML_STATUS_ERROR) 6462 xml_failure(g_parser); 6463 CharData_CheckXMLChars(&storage, expected); 6464 } 6465 END_TEST 6466 6467 START_TEST(test_entity_public_utf16_be) { 6468 const char text[] = 6469 /* <!DOCTYPE d [ */ 6470 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6471 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6472 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 " 6473 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n" 6474 /* %e; */ 6475 "\0%\0e\0;\0\n" 6476 /* ]> */ 6477 "\0]\0>\0\n" 6478 /* <d>&j;</d> */ 6479 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>"; 6480 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6481 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>", 6482 34, NULL, NULL, EE_PARSE_NONE}; 6483 const XML_Char *expected = XCS("baz"); 6484 CharData storage; 6485 6486 CharData_Init(&storage); 6487 test_data.storage = &storage; 6488 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6489 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6490 XML_SetUserData(g_parser, &test_data); 6491 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6492 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6493 == XML_STATUS_ERROR) 6494 xml_failure(g_parser); 6495 CharData_CheckXMLChars(&storage, expected); 6496 } 6497 END_TEST 6498 6499 START_TEST(test_entity_public_utf16_le) { 6500 const char text[] = 6501 /* <!DOCTYPE d [ */ 6502 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0" 6503 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6504 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0" 6505 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0" 6506 /* %e; */ 6507 "%\0e\0;\0\n\0" 6508 /* ]> */ 6509 "]\0>\0\n\0" 6510 /* <d>&j;</d> */ 6511 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0"; 6512 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6513 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0", 6514 34, NULL, NULL, EE_PARSE_NONE}; 6515 const XML_Char *expected = XCS("baz"); 6516 CharData storage; 6517 6518 CharData_Init(&storage); 6519 test_data.storage = &storage; 6520 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6521 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6522 XML_SetUserData(g_parser, &test_data); 6523 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6524 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6525 == XML_STATUS_ERROR) 6526 xml_failure(g_parser); 6527 CharData_CheckXMLChars(&storage, expected); 6528 } 6529 END_TEST 6530 6531 /* Test that a doctype with neither an internal nor external subset is 6532 * faulted 6533 */ 6534 START_TEST(test_short_doctype) { 6535 const char *text = "<!DOCTYPE doc></doc>"; 6536 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6537 "DOCTYPE without subset not rejected"); 6538 } 6539 END_TEST 6540 6541 START_TEST(test_short_doctype_2) { 6542 const char *text = "<!DOCTYPE doc PUBLIC></doc>"; 6543 expect_failure(text, XML_ERROR_SYNTAX, 6544 "DOCTYPE without Public ID not rejected"); 6545 } 6546 END_TEST 6547 6548 START_TEST(test_short_doctype_3) { 6549 const char *text = "<!DOCTYPE doc SYSTEM></doc>"; 6550 expect_failure(text, XML_ERROR_SYNTAX, 6551 "DOCTYPE without System ID not rejected"); 6552 } 6553 END_TEST 6554 6555 START_TEST(test_long_doctype) { 6556 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>"; 6557 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected"); 6558 } 6559 END_TEST 6560 6561 START_TEST(test_bad_entity) { 6562 const char *text = "<!DOCTYPE doc [\n" 6563 " <!ENTITY foo PUBLIC>\n" 6564 "]>\n" 6565 "<doc/>"; 6566 expect_failure(text, XML_ERROR_SYNTAX, 6567 "ENTITY without Public ID is not rejected"); 6568 } 6569 END_TEST 6570 6571 /* Test unquoted value is faulted */ 6572 START_TEST(test_bad_entity_2) { 6573 const char *text = "<!DOCTYPE doc [\n" 6574 " <!ENTITY % foo bar>\n" 6575 "]>\n" 6576 "<doc/>"; 6577 expect_failure(text, XML_ERROR_SYNTAX, 6578 "ENTITY without Public ID is not rejected"); 6579 } 6580 END_TEST 6581 6582 START_TEST(test_bad_entity_3) { 6583 const char *text = "<!DOCTYPE doc [\n" 6584 " <!ENTITY % foo PUBLIC>\n" 6585 "]>\n" 6586 "<doc/>"; 6587 expect_failure(text, XML_ERROR_SYNTAX, 6588 "Parameter ENTITY without Public ID is not rejected"); 6589 } 6590 END_TEST 6591 6592 START_TEST(test_bad_entity_4) { 6593 const char *text = "<!DOCTYPE doc [\n" 6594 " <!ENTITY % foo SYSTEM>\n" 6595 "]>\n" 6596 "<doc/>"; 6597 expect_failure(text, XML_ERROR_SYNTAX, 6598 "Parameter ENTITY without Public ID is not rejected"); 6599 } 6600 END_TEST 6601 6602 START_TEST(test_bad_notation) { 6603 const char *text = "<!DOCTYPE doc [\n" 6604 " <!NOTATION n SYSTEM>\n" 6605 "]>\n" 6606 "<doc/>"; 6607 expect_failure(text, XML_ERROR_SYNTAX, 6608 "Notation without System ID is not rejected"); 6609 } 6610 END_TEST 6611 6612 /* Test for issue #11, wrongly suppressed default handler */ 6613 typedef struct default_check { 6614 const XML_Char *expected; 6615 const int expectedLen; 6616 XML_Bool seen; 6617 } DefaultCheck; 6618 6619 static void XMLCALL 6620 checking_default_handler(void *userData, const XML_Char *s, int len) { 6621 DefaultCheck *data = (DefaultCheck *)userData; 6622 int i; 6623 6624 for (i = 0; data[i].expected != NULL; i++) { 6625 if (data[i].expectedLen == len 6626 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) { 6627 data[i].seen = XML_TRUE; 6628 break; 6629 } 6630 } 6631 } 6632 6633 START_TEST(test_default_doctype_handler) { 6634 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n" 6635 " <!ENTITY foo 'bar'>\n" 6636 "]>\n" 6637 "<doc>&foo;</doc>"; 6638 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE}, 6639 {XCS("'test.dtd'"), 10, XML_FALSE}, 6640 {NULL, 0, XML_FALSE}}; 6641 int i; 6642 6643 XML_SetUserData(g_parser, &test_data); 6644 XML_SetDefaultHandler(g_parser, checking_default_handler); 6645 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 6646 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6647 == XML_STATUS_ERROR) 6648 xml_failure(g_parser); 6649 for (i = 0; test_data[i].expected != NULL; i++) 6650 if (! test_data[i].seen) 6651 fail("Default handler not run for public !DOCTYPE"); 6652 } 6653 END_TEST 6654 6655 START_TEST(test_empty_element_abort) { 6656 const char *text = "<abort/>"; 6657 6658 XML_SetStartElementHandler(g_parser, start_element_suspender); 6659 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6660 != XML_STATUS_ERROR) 6661 fail("Expected to error on abort"); 6662 } 6663 END_TEST 6664 6665 /* 6666 * Namespaces tests. 6667 */ 6668 6669 static void 6670 namespace_setup(void) { 6671 g_parser = XML_ParserCreateNS(NULL, XCS(' ')); 6672 if (g_parser == NULL) 6673 fail("Parser not created."); 6674 } 6675 6676 static void 6677 namespace_teardown(void) { 6678 basic_teardown(); 6679 } 6680 6681 /* Check that an element name and attribute name match the expected values. 6682 The expected values are passed as an array reference of string pointers 6683 provided as the userData argument; the first is the expected 6684 element name, and the second is the expected attribute name. 6685 */ 6686 static int triplet_start_flag = XML_FALSE; 6687 static int triplet_end_flag = XML_FALSE; 6688 6689 static void XMLCALL 6690 triplet_start_checker(void *userData, const XML_Char *name, 6691 const XML_Char **atts) { 6692 XML_Char **elemstr = (XML_Char **)userData; 6693 char buffer[1024]; 6694 if (xcstrcmp(elemstr[0], name) != 0) { 6695 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name); 6696 fail(buffer); 6697 } 6698 if (xcstrcmp(elemstr[1], atts[0]) != 0) { 6699 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]); 6700 fail(buffer); 6701 } 6702 triplet_start_flag = XML_TRUE; 6703 } 6704 6705 /* Check that the element name passed to the end-element handler matches 6706 the expected value. The expected value is passed as the first element 6707 in an array of strings passed as the userData argument. 6708 */ 6709 static void XMLCALL 6710 triplet_end_checker(void *userData, const XML_Char *name) { 6711 XML_Char **elemstr = (XML_Char **)userData; 6712 if (xcstrcmp(elemstr[0], name) != 0) { 6713 char buffer[1024]; 6714 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name); 6715 fail(buffer); 6716 } 6717 triplet_end_flag = XML_TRUE; 6718 } 6719 6720 START_TEST(test_return_ns_triplet) { 6721 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 6722 " xmlns:bar='http://example.org/'>"; 6723 const char *epilog = "</foo:e>"; 6724 const XML_Char *elemstr[] 6725 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")}; 6726 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6727 XML_SetUserData(g_parser, (void *)elemstr); 6728 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 6729 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler, 6730 dummy_end_namespace_decl_handler); 6731 triplet_start_flag = XML_FALSE; 6732 triplet_end_flag = XML_FALSE; 6733 dummy_handler_flags = 0; 6734 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 6735 == XML_STATUS_ERROR) 6736 xml_failure(g_parser); 6737 if (! triplet_start_flag) 6738 fail("triplet_start_checker not invoked"); 6739 /* Check that unsetting "return triplets" fails while still parsing */ 6740 XML_SetReturnNSTriplet(g_parser, XML_FALSE); 6741 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 6742 == XML_STATUS_ERROR) 6743 xml_failure(g_parser); 6744 if (! triplet_end_flag) 6745 fail("triplet_end_checker not invoked"); 6746 if (dummy_handler_flags 6747 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG)) 6748 fail("Namespace handlers not called"); 6749 } 6750 END_TEST 6751 6752 static void XMLCALL 6753 overwrite_start_checker(void *userData, const XML_Char *name, 6754 const XML_Char **atts) { 6755 CharData *storage = (CharData *)userData; 6756 CharData_AppendXMLChars(storage, XCS("start "), 6); 6757 CharData_AppendXMLChars(storage, name, -1); 6758 while (*atts != NULL) { 6759 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11); 6760 CharData_AppendXMLChars(storage, *atts, -1); 6761 atts += 2; 6762 } 6763 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6764 } 6765 6766 static void XMLCALL 6767 overwrite_end_checker(void *userData, const XML_Char *name) { 6768 CharData *storage = (CharData *)userData; 6769 CharData_AppendXMLChars(storage, XCS("end "), 4); 6770 CharData_AppendXMLChars(storage, name, -1); 6771 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6772 } 6773 6774 static void 6775 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) { 6776 CharData storage; 6777 CharData_Init(&storage); 6778 XML_SetUserData(g_parser, &storage); 6779 XML_SetElementHandler(g_parser, overwrite_start_checker, 6780 overwrite_end_checker); 6781 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6782 == XML_STATUS_ERROR) 6783 xml_failure(g_parser); 6784 CharData_CheckXMLChars(&storage, result); 6785 } 6786 6787 /* Regression test for SF bug #566334. */ 6788 START_TEST(test_ns_tagname_overwrite) { 6789 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6790 " <n:f n:attr='foo'/>\n" 6791 " <n:g n:attr2='bar'/>\n" 6792 "</n:e>"; 6793 const XML_Char *result = XCS("start http://example.org/ e\n") 6794 XCS("start http://example.org/ f\n") 6795 XCS("attribute http://example.org/ attr\n") 6796 XCS("end http://example.org/ f\n") 6797 XCS("start http://example.org/ g\n") 6798 XCS("attribute http://example.org/ attr2\n") 6799 XCS("end http://example.org/ g\n") 6800 XCS("end http://example.org/ e\n"); 6801 run_ns_tagname_overwrite_test(text, result); 6802 } 6803 END_TEST 6804 6805 /* Regression test for SF bug #566334. */ 6806 START_TEST(test_ns_tagname_overwrite_triplet) { 6807 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6808 " <n:f n:attr='foo'/>\n" 6809 " <n:g n:attr2='bar'/>\n" 6810 "</n:e>"; 6811 const XML_Char *result = XCS("start http://example.org/ e n\n") 6812 XCS("start http://example.org/ f n\n") 6813 XCS("attribute http://example.org/ attr n\n") 6814 XCS("end http://example.org/ f n\n") 6815 XCS("start http://example.org/ g n\n") 6816 XCS("attribute http://example.org/ attr2 n\n") 6817 XCS("end http://example.org/ g n\n") 6818 XCS("end http://example.org/ e n\n"); 6819 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6820 run_ns_tagname_overwrite_test(text, result); 6821 } 6822 END_TEST 6823 6824 /* Regression test for SF bug #620343. */ 6825 static void XMLCALL 6826 start_element_fail(void *userData, const XML_Char *name, 6827 const XML_Char **atts) { 6828 UNUSED_P(userData); 6829 UNUSED_P(name); 6830 UNUSED_P(atts); 6831 6832 /* We should never get here. */ 6833 fail("should never reach start_element_fail()"); 6834 } 6835 6836 static void XMLCALL 6837 start_ns_clearing_start_element(void *userData, const XML_Char *prefix, 6838 const XML_Char *uri) { 6839 UNUSED_P(prefix); 6840 UNUSED_P(uri); 6841 XML_SetStartElementHandler((XML_Parser)userData, NULL); 6842 } 6843 6844 START_TEST(test_start_ns_clears_start_element) { 6845 /* This needs to use separate start/end tags; using the empty tag 6846 syntax doesn't cause the problematic path through Expat to be 6847 taken. 6848 */ 6849 const char *text = "<e xmlns='http://example.org/'></e>"; 6850 6851 XML_SetStartElementHandler(g_parser, start_element_fail); 6852 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element); 6853 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 6854 XML_UseParserAsHandlerArg(g_parser); 6855 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6856 == XML_STATUS_ERROR) 6857 xml_failure(g_parser); 6858 } 6859 END_TEST 6860 6861 /* Regression test for SF bug #616863. */ 6862 static int XMLCALL 6863 external_entity_handler(XML_Parser parser, const XML_Char *context, 6864 const XML_Char *base, const XML_Char *systemId, 6865 const XML_Char *publicId) { 6866 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser); 6867 const char *text; 6868 XML_Parser p2; 6869 6870 UNUSED_P(base); 6871 UNUSED_P(systemId); 6872 UNUSED_P(publicId); 6873 if (callno == 1) 6874 text = ("<!ELEMENT doc (e+)>\n" 6875 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 6876 "<!ELEMENT e EMPTY>\n"); 6877 else 6878 text = ("<?xml version='1.0' encoding='us-ascii'?>" 6879 "<e/>"); 6880 6881 XML_SetUserData(parser, (void *)callno); 6882 p2 = XML_ExternalEntityParserCreate(parser, context, NULL); 6883 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE) 6884 == XML_STATUS_ERROR) { 6885 xml_failure(p2); 6886 return XML_STATUS_ERROR; 6887 } 6888 XML_ParserFree(p2); 6889 return XML_STATUS_OK; 6890 } 6891 6892 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) { 6893 const char *text = "<?xml version='1.0'?>\n" 6894 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 6895 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 6896 "]>\n" 6897 "<doc xmlns='http://example.org/ns1'>\n" 6898 "&en;\n" 6899 "</doc>"; 6900 6901 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6902 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler); 6903 /* We actually need to set this handler to tickle this bug. */ 6904 XML_SetStartElementHandler(g_parser, dummy_start_element); 6905 XML_SetUserData(g_parser, NULL); 6906 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6907 == XML_STATUS_ERROR) 6908 xml_failure(g_parser); 6909 } 6910 END_TEST 6911 6912 /* Regression test #1 for SF bug #673791. */ 6913 START_TEST(test_ns_prefix_with_empty_uri_1) { 6914 const char *text = "<doc xmlns:prefix='http://example.org/'>\n" 6915 " <e xmlns:prefix=''/>\n" 6916 "</doc>"; 6917 6918 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6919 "Did not report re-setting namespace" 6920 " URI with prefix to ''."); 6921 } 6922 END_TEST 6923 6924 /* Regression test #2 for SF bug #673791. */ 6925 START_TEST(test_ns_prefix_with_empty_uri_2) { 6926 const char *text = "<?xml version='1.0'?>\n" 6927 "<docelem xmlns:pre=''/>"; 6928 6929 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6930 "Did not report setting namespace URI with prefix to ''."); 6931 } 6932 END_TEST 6933 6934 /* Regression test #3 for SF bug #673791. */ 6935 START_TEST(test_ns_prefix_with_empty_uri_3) { 6936 const char *text = "<!DOCTYPE doc [\n" 6937 " <!ELEMENT doc EMPTY>\n" 6938 " <!ATTLIST doc\n" 6939 " xmlns:prefix CDATA ''>\n" 6940 "]>\n" 6941 "<doc/>"; 6942 6943 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6944 "Didn't report attr default setting NS w/ prefix to ''."); 6945 } 6946 END_TEST 6947 6948 /* Regression test #4 for SF bug #673791. */ 6949 START_TEST(test_ns_prefix_with_empty_uri_4) { 6950 const char *text = "<!DOCTYPE doc [\n" 6951 " <!ELEMENT prefix:doc EMPTY>\n" 6952 " <!ATTLIST prefix:doc\n" 6953 " xmlns:prefix CDATA 'http://example.org/'>\n" 6954 "]>\n" 6955 "<prefix:doc/>"; 6956 /* Packaged info expected by the end element handler; 6957 the weird structuring lets us re-use the triplet_end_checker() 6958 function also used for another test. */ 6959 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")}; 6960 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6961 XML_SetUserData(g_parser, (void *)elemstr); 6962 XML_SetEndElementHandler(g_parser, triplet_end_checker); 6963 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6964 == XML_STATUS_ERROR) 6965 xml_failure(g_parser); 6966 } 6967 END_TEST 6968 6969 /* Test with non-xmlns prefix */ 6970 START_TEST(test_ns_unbound_prefix) { 6971 const char *text = "<!DOCTYPE doc [\n" 6972 " <!ELEMENT prefix:doc EMPTY>\n" 6973 " <!ATTLIST prefix:doc\n" 6974 " notxmlns:prefix CDATA 'http://example.org/'>\n" 6975 "]>\n" 6976 "<prefix:doc/>"; 6977 6978 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6979 != XML_STATUS_ERROR) 6980 fail("Unbound prefix incorrectly passed"); 6981 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX) 6982 xml_failure(g_parser); 6983 } 6984 END_TEST 6985 6986 START_TEST(test_ns_default_with_empty_uri) { 6987 const char *text = "<doc xmlns='http://example.org/'>\n" 6988 " <e xmlns=''/>\n" 6989 "</doc>"; 6990 /* Add some handlers to exercise extra code paths */ 6991 XML_SetStartNamespaceDeclHandler(g_parser, 6992 dummy_start_namespace_decl_handler); 6993 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 6994 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6995 == XML_STATUS_ERROR) 6996 xml_failure(g_parser); 6997 } 6998 END_TEST 6999 7000 /* Regression test for SF bug #692964: two prefixes for one namespace. */ 7001 START_TEST(test_ns_duplicate_attrs_diff_prefixes) { 7002 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7003 " xmlns:b='http://example.org/a'\n" 7004 " a:a='v' b:a='v' />"; 7005 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE, 7006 "did not report multiple attributes with same URI+name"); 7007 } 7008 END_TEST 7009 7010 START_TEST(test_ns_duplicate_hashes) { 7011 /* The hash of an attribute is calculated as the hash of its URI 7012 * concatenated with a space followed by its name (after the 7013 * colon). We wish to generate attributes with the same hash 7014 * value modulo the attribute table size so that we can check that 7015 * the attribute hash table works correctly. The attribute hash 7016 * table size will be the smallest power of two greater than the 7017 * number of attributes, but at least eight. There is 7018 * unfortunately no programmatic way of getting the hash or the 7019 * table size at user level, but the test code coverage percentage 7020 * will drop if the hashes cease to point to the same row. 7021 * 7022 * The cunning plan is to have few enough attributes to have a 7023 * reliable table size of 8, and have the single letter attribute 7024 * names be 8 characters apart, producing a hash which will be the 7025 * same modulo 8. 7026 */ 7027 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7028 " a:a='v' a:i='w' />"; 7029 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7030 == XML_STATUS_ERROR) 7031 xml_failure(g_parser); 7032 } 7033 END_TEST 7034 7035 /* Regression test for SF bug #695401: unbound prefix. */ 7036 START_TEST(test_ns_unbound_prefix_on_attribute) { 7037 const char *text = "<doc a:attr=''/>"; 7038 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7039 "did not report unbound prefix on attribute"); 7040 } 7041 END_TEST 7042 7043 /* Regression test for SF bug #695401: unbound prefix. */ 7044 START_TEST(test_ns_unbound_prefix_on_element) { 7045 const char *text = "<a:doc/>"; 7046 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7047 "did not report unbound prefix on element"); 7048 } 7049 END_TEST 7050 7051 /* Test that the parsing status is correctly reset by XML_ParserReset(). 7052 * We usE test_return_ns_triplet() for our example parse to improve 7053 * coverage of tidying up code executed. 7054 */ 7055 START_TEST(test_ns_parser_reset) { 7056 XML_ParsingStatus status; 7057 7058 XML_GetParsingStatus(g_parser, &status); 7059 if (status.parsing != XML_INITIALIZED) 7060 fail("parsing status doesn't start INITIALIZED"); 7061 test_return_ns_triplet(); 7062 XML_GetParsingStatus(g_parser, &status); 7063 if (status.parsing != XML_FINISHED) 7064 fail("parsing status doesn't end FINISHED"); 7065 XML_ParserReset(g_parser, NULL); 7066 XML_GetParsingStatus(g_parser, &status); 7067 if (status.parsing != XML_INITIALIZED) 7068 fail("parsing status doesn't reset to INITIALIZED"); 7069 } 7070 END_TEST 7071 7072 /* Test that long element names with namespaces are handled correctly */ 7073 START_TEST(test_ns_long_element) { 7074 const char *text 7075 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 7076 " xmlns:foo='http://example.org/' bar:a='12'\n" 7077 " xmlns:bar='http://example.org/'>" 7078 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 7079 const XML_Char *elemstr[] 7080 = {XCS("http://example.org/") 7081 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 7082 XCS("http://example.org/ a bar")}; 7083 7084 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 7085 XML_SetUserData(g_parser, (void *)elemstr); 7086 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 7087 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7088 == XML_STATUS_ERROR) 7089 xml_failure(g_parser); 7090 } 7091 END_TEST 7092 7093 /* Test mixed population of prefixed and unprefixed attributes */ 7094 START_TEST(test_ns_mixed_prefix_atts) { 7095 const char *text = "<e a='12' bar:b='13'\n" 7096 " xmlns:bar='http://example.org/'>" 7097 "</e>"; 7098 7099 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7100 == XML_STATUS_ERROR) 7101 xml_failure(g_parser); 7102 } 7103 END_TEST 7104 7105 /* Test having a long namespaced element name inside a short one. 7106 * This exercises some internal buffer reallocation that is shared 7107 * across elements with the same namespace URI. 7108 */ 7109 START_TEST(test_ns_extend_uri_buffer) { 7110 const char *text = "<foo:e xmlns:foo='http://example.org/'>" 7111 " <foo:thisisalongenoughnametotriggerallocationaction" 7112 " foo:a='12' />" 7113 "</foo:e>"; 7114 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7115 == XML_STATUS_ERROR) 7116 xml_failure(g_parser); 7117 } 7118 END_TEST 7119 7120 /* Test that xmlns is correctly rejected as an attribute in the xmlns 7121 * namespace, but not in other namespaces 7122 */ 7123 START_TEST(test_ns_reserved_attributes) { 7124 const char *text1 7125 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />"; 7126 const char *text2 7127 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />"; 7128 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS, 7129 "xmlns not rejected as an attribute"); 7130 XML_ParserReset(g_parser, NULL); 7131 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7132 == XML_STATUS_ERROR) 7133 xml_failure(g_parser); 7134 } 7135 END_TEST 7136 7137 /* Test more reserved attributes */ 7138 START_TEST(test_ns_reserved_attributes_2) { 7139 const char *text1 = "<foo:e xmlns:foo='http://example.org/'" 7140 " xmlns:xml='http://example.org/' />"; 7141 const char *text2 7142 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />"; 7143 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />"; 7144 7145 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML, 7146 "xml not rejected as an attribute"); 7147 XML_ParserReset(g_parser, NULL); 7148 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI, 7149 "Use of w3.org URL not faulted"); 7150 XML_ParserReset(g_parser, NULL); 7151 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI, 7152 "Use of w3.org xmlns URL not faulted"); 7153 } 7154 END_TEST 7155 7156 /* Test string pool handling of namespace names of 2048 characters */ 7157 /* Exercises a particular string pool growth path */ 7158 START_TEST(test_ns_extremely_long_prefix) { 7159 /* C99 compilers are only required to support 4095-character 7160 * strings, so the following needs to be split in two to be safe 7161 * for all compilers. 7162 */ 7163 const char *text1 7164 = "<doc " 7165 /* 64 character on each line */ 7166 /* ...gives a total length of 2048 */ 7167 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7168 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7169 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7170 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7171 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7172 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7173 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7174 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7175 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7176 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7177 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7178 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7179 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7180 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7181 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7182 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7183 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7184 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7185 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7186 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7187 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7188 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7189 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7190 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7191 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7192 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7193 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7194 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7195 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7196 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7197 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7198 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7199 ":a='12'"; 7200 const char *text2 7201 = " xmlns:" 7202 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7203 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7204 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7205 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7206 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7207 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7208 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7209 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7210 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7211 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7212 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7213 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7214 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7215 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7216 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7217 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7218 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7219 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7220 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7221 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7222 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7223 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7224 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7225 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7226 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7227 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7228 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7229 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7230 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7231 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7232 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7233 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7234 "='foo'\n>" 7235 "</doc>"; 7236 7237 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 7238 == XML_STATUS_ERROR) 7239 xml_failure(g_parser); 7240 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7241 == XML_STATUS_ERROR) 7242 xml_failure(g_parser); 7243 } 7244 END_TEST 7245 7246 /* Test unknown encoding handlers in namespace setup */ 7247 START_TEST(test_ns_unknown_encoding_success) { 7248 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 7249 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>"; 7250 7251 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7252 run_character_check(text, XCS("Hi")); 7253 } 7254 END_TEST 7255 7256 /* Test that too many colons are rejected */ 7257 START_TEST(test_ns_double_colon) { 7258 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />"; 7259 const enum XML_Status status 7260 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7261 #ifdef XML_NS 7262 if ((status == XML_STATUS_OK) 7263 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7264 fail("Double colon in attribute name not faulted" 7265 " (despite active namespace support)"); 7266 } 7267 #else 7268 if (status != XML_STATUS_OK) { 7269 fail("Double colon in attribute name faulted" 7270 " (despite inactive namespace support"); 7271 } 7272 #endif 7273 } 7274 END_TEST 7275 7276 START_TEST(test_ns_double_colon_element) { 7277 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />"; 7278 const enum XML_Status status 7279 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7280 #ifdef XML_NS 7281 if ((status == XML_STATUS_OK) 7282 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7283 fail("Double colon in element name not faulted" 7284 " (despite active namespace support)"); 7285 } 7286 #else 7287 if (status != XML_STATUS_OK) { 7288 fail("Double colon in element name faulted" 7289 " (despite inactive namespace support"); 7290 } 7291 #endif 7292 } 7293 END_TEST 7294 7295 /* Test that non-name characters after a colon are rejected */ 7296 START_TEST(test_ns_bad_attr_leafname) { 7297 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />"; 7298 7299 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7300 "Invalid character in leafname not faulted"); 7301 } 7302 END_TEST 7303 7304 START_TEST(test_ns_bad_element_leafname) { 7305 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />"; 7306 7307 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7308 "Invalid character in element leafname not faulted"); 7309 } 7310 END_TEST 7311 7312 /* Test high-byte-set UTF-16 characters are valid in a leafname */ 7313 START_TEST(test_ns_utf16_leafname) { 7314 const char text[] = 7315 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' /> 7316 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7317 */ 7318 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0" 7319 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0"; 7320 const XML_Char *expected = XCS("a"); 7321 CharData storage; 7322 7323 CharData_Init(&storage); 7324 XML_SetStartElementHandler(g_parser, accumulate_attribute); 7325 XML_SetUserData(g_parser, &storage); 7326 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7327 == XML_STATUS_ERROR) 7328 xml_failure(g_parser); 7329 CharData_CheckXMLChars(&storage, expected); 7330 } 7331 END_TEST 7332 7333 START_TEST(test_ns_utf16_element_leafname) { 7334 const char text[] = 7335 /* <n:{KHO KHWAI} xmlns:n='URI'/> 7336 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7337 */ 7338 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>"; 7339 #ifdef XML_UNICODE 7340 const XML_Char *expected = XCS("URI \x0e04"); 7341 #else 7342 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7343 #endif 7344 CharData storage; 7345 7346 CharData_Init(&storage); 7347 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7348 XML_SetUserData(g_parser, &storage); 7349 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7350 == XML_STATUS_ERROR) 7351 xml_failure(g_parser); 7352 CharData_CheckXMLChars(&storage, expected); 7353 } 7354 END_TEST 7355 7356 START_TEST(test_ns_utf16_doctype) { 7357 const char text[] = 7358 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n 7359 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7360 */ 7361 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 " 7362 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 " 7363 "\0]\0>\0\n" 7364 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */ 7365 "\0<\0f\0o\0o\0:\x0e\x04\0 " 7366 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>" 7367 "\0&\0b\0a\0r\0;" 7368 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>"; 7369 #ifdef XML_UNICODE 7370 const XML_Char *expected = XCS("URI \x0e04"); 7371 #else 7372 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7373 #endif 7374 CharData storage; 7375 7376 CharData_Init(&storage); 7377 XML_SetUserData(g_parser, &storage); 7378 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7379 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7380 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7381 == XML_STATUS_ERROR) 7382 xml_failure(g_parser); 7383 CharData_CheckXMLChars(&storage, expected); 7384 } 7385 END_TEST 7386 7387 START_TEST(test_ns_invalid_doctype) { 7388 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n" 7389 "<foo:!bad>&bar;</foo:!bad>"; 7390 7391 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7392 "Invalid character in document local name not faulted"); 7393 } 7394 END_TEST 7395 7396 START_TEST(test_ns_double_colon_doctype) { 7397 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n" 7398 "<foo:a:doc>&bar;</foo:a:doc>"; 7399 7400 expect_failure(text, XML_ERROR_SYNTAX, 7401 "Double colon in document name not faulted"); 7402 } 7403 END_TEST 7404 7405 START_TEST(test_ns_separator_in_uri) { 7406 struct test_case { 7407 enum XML_Status expectedStatus; 7408 const char *doc; 7409 XML_Char namesep; 7410 }; 7411 struct test_case cases[] = { 7412 {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')}, 7413 {XML_STATUS_ERROR, "<doc xmlns='one
two' />", XCS('\n')}, 7414 {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')}, 7415 }; 7416 7417 size_t i = 0; 7418 size_t failCount = 0; 7419 for (; i < sizeof(cases) / sizeof(cases[0]); i++) { 7420 XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep); 7421 XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); 7422 if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), 7423 /*isFinal*/ XML_TRUE) 7424 != cases[i].expectedStatus) { 7425 failCount++; 7426 } 7427 XML_ParserFree(parser); 7428 } 7429 7430 if (failCount) { 7431 fail("Namespace separator handling is broken"); 7432 } 7433 } 7434 END_TEST 7435 7436 /* Control variable; the number of times duff_allocator() will successfully 7437 * allocate */ 7438 #define ALLOC_ALWAYS_SUCCEED (-1) 7439 #define REALLOC_ALWAYS_SUCCEED (-1) 7440 7441 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED; 7442 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED; 7443 7444 /* Crocked allocator for allocation failure tests */ 7445 static void * 7446 duff_allocator(size_t size) { 7447 if (allocation_count == 0) 7448 return NULL; 7449 if (allocation_count != ALLOC_ALWAYS_SUCCEED) 7450 allocation_count--; 7451 return malloc(size); 7452 } 7453 7454 /* Crocked reallocator for allocation failure tests */ 7455 static void * 7456 duff_reallocator(void *ptr, size_t size) { 7457 if (reallocation_count == 0) 7458 return NULL; 7459 if (reallocation_count != REALLOC_ALWAYS_SUCCEED) 7460 reallocation_count--; 7461 return realloc(ptr, size); 7462 } 7463 7464 /* Test that a failure to allocate the parser structure fails gracefully */ 7465 START_TEST(test_misc_alloc_create_parser) { 7466 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7467 unsigned int i; 7468 const unsigned int max_alloc_count = 10; 7469 7470 /* Something this simple shouldn't need more than 10 allocations */ 7471 for (i = 0; i < max_alloc_count; i++) { 7472 allocation_count = i; 7473 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7474 if (g_parser != NULL) 7475 break; 7476 } 7477 if (i == 0) 7478 fail("Parser unexpectedly ignored failing allocator"); 7479 else if (i == max_alloc_count) 7480 fail("Parser not created with max allocation count"); 7481 } 7482 END_TEST 7483 7484 /* Test memory allocation failures for a parser with an encoding */ 7485 START_TEST(test_misc_alloc_create_parser_with_encoding) { 7486 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7487 unsigned int i; 7488 const unsigned int max_alloc_count = 10; 7489 7490 /* Try several levels of allocation */ 7491 for (i = 0; i < max_alloc_count; i++) { 7492 allocation_count = i; 7493 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL); 7494 if (g_parser != NULL) 7495 break; 7496 } 7497 if (i == 0) 7498 fail("Parser ignored failing allocator"); 7499 else if (i == max_alloc_count) 7500 fail("Parser not created with max allocation count"); 7501 } 7502 END_TEST 7503 7504 /* Test that freeing a NULL parser doesn't cause an explosion. 7505 * (Not actually tested anywhere else) 7506 */ 7507 START_TEST(test_misc_null_parser) { 7508 XML_ParserFree(NULL); 7509 } 7510 END_TEST 7511 7512 /* Test that XML_ErrorString rejects out-of-range codes */ 7513 START_TEST(test_misc_error_string) { 7514 if (XML_ErrorString((enum XML_Error) - 1) != NULL) 7515 fail("Negative error code not rejected"); 7516 if (XML_ErrorString((enum XML_Error)100) != NULL) 7517 fail("Large error code not rejected"); 7518 } 7519 END_TEST 7520 7521 /* Test the version information is consistent */ 7522 7523 /* Since we are working in XML_LChars (potentially 16-bits), we 7524 * can't use the standard C library functions for character 7525 * manipulation and have to roll our own. 7526 */ 7527 static int 7528 parse_version(const XML_LChar *version_text, 7529 XML_Expat_Version *version_struct) { 7530 if (! version_text) 7531 return XML_FALSE; 7532 7533 while (*version_text != 0x00) { 7534 if (*version_text >= ASCII_0 && *version_text <= ASCII_9) 7535 break; 7536 version_text++; 7537 } 7538 if (*version_text == 0x00) 7539 return XML_FALSE; 7540 7541 /* version_struct->major = strtoul(version_text, 10, &version_text) */ 7542 version_struct->major = 0; 7543 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7544 version_struct->major 7545 = 10 * version_struct->major + (*version_text++ - ASCII_0); 7546 } 7547 if (*version_text++ != ASCII_PERIOD) 7548 return XML_FALSE; 7549 7550 /* Now for the minor version number */ 7551 version_struct->minor = 0; 7552 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7553 version_struct->minor 7554 = 10 * version_struct->minor + (*version_text++ - ASCII_0); 7555 } 7556 if (*version_text++ != ASCII_PERIOD) 7557 return XML_FALSE; 7558 7559 /* Finally the micro version number */ 7560 version_struct->micro = 0; 7561 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7562 version_struct->micro 7563 = 10 * version_struct->micro + (*version_text++ - ASCII_0); 7564 } 7565 if (*version_text != 0x00) 7566 return XML_FALSE; 7567 return XML_TRUE; 7568 } 7569 7570 static int 7571 versions_equal(const XML_Expat_Version *first, 7572 const XML_Expat_Version *second) { 7573 return (first->major == second->major && first->minor == second->minor 7574 && first->micro == second->micro); 7575 } 7576 7577 START_TEST(test_misc_version) { 7578 XML_Expat_Version read_version = XML_ExpatVersionInfo(); 7579 /* Silence compiler warning with the following assignment */ 7580 XML_Expat_Version parsed_version = {0, 0, 0}; 7581 const XML_LChar *version_text = XML_ExpatVersion(); 7582 7583 if (version_text == NULL) 7584 fail("Could not obtain version text"); 7585 assert(version_text != NULL); 7586 if (! parse_version(version_text, &parsed_version)) 7587 fail("Unable to parse version text"); 7588 if (! versions_equal(&read_version, &parsed_version)) 7589 fail("Version mismatch"); 7590 7591 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) 7592 if (xcstrcmp(version_text, XCS("expat_2.4.7"))) /* needs bump on releases */ 7593 fail("XML_*_VERSION in expat.h out of sync?\n"); 7594 #else 7595 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T 7596 * then XML_LChar is defined as char, for some reason. 7597 */ 7598 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */ 7599 fail("XML_*_VERSION in expat.h out of sync?\n"); 7600 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */ 7601 } 7602 END_TEST 7603 7604 /* Test feature information */ 7605 START_TEST(test_misc_features) { 7606 const XML_Feature *features = XML_GetFeatureList(); 7607 7608 /* Prevent problems with double-freeing parsers */ 7609 g_parser = NULL; 7610 if (features == NULL) { 7611 fail("Failed to get feature information"); 7612 } else { 7613 /* Loop through the features checking what we can */ 7614 while (features->feature != XML_FEATURE_END) { 7615 switch (features->feature) { 7616 case XML_FEATURE_SIZEOF_XML_CHAR: 7617 if (features->value != sizeof(XML_Char)) 7618 fail("Incorrect size of XML_Char"); 7619 break; 7620 case XML_FEATURE_SIZEOF_XML_LCHAR: 7621 if (features->value != sizeof(XML_LChar)) 7622 fail("Incorrect size of XML_LChar"); 7623 break; 7624 default: 7625 break; 7626 } 7627 features++; 7628 } 7629 } 7630 } 7631 END_TEST 7632 7633 /* Regression test for GitHub Issue #17: memory leak parsing attribute 7634 * values with mixed bound and unbound namespaces. 7635 */ 7636 START_TEST(test_misc_attribute_leak) { 7637 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>"; 7638 XML_Memory_Handling_Suite memsuite 7639 = {tracking_malloc, tracking_realloc, tracking_free}; 7640 7641 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n")); 7642 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found"); 7643 XML_ParserFree(g_parser); 7644 /* Prevent the teardown trying to double free */ 7645 g_parser = NULL; 7646 7647 if (! tracking_report()) 7648 fail("Memory leak found"); 7649 } 7650 END_TEST 7651 7652 /* Test parser created for UTF-16LE is successful */ 7653 START_TEST(test_misc_utf16le) { 7654 const char text[] = 7655 /* <?xml version='1.0'?><q>Hi</q> */ 7656 "<\0?\0x\0m\0l\0 \0" 7657 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0" 7658 "<\0q\0>\0H\0i\0<\0/\0q\0>\0"; 7659 const XML_Char *expected = XCS("Hi"); 7660 CharData storage; 7661 7662 g_parser = XML_ParserCreate(XCS("UTF-16LE")); 7663 if (g_parser == NULL) 7664 fail("Parser not created"); 7665 7666 CharData_Init(&storage); 7667 XML_SetUserData(g_parser, &storage); 7668 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 7669 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7670 == XML_STATUS_ERROR) 7671 xml_failure(g_parser); 7672 CharData_CheckXMLChars(&storage, expected); 7673 } 7674 END_TEST 7675 7676 typedef struct { 7677 XML_Parser parser; 7678 int deep; 7679 } DataIssue240; 7680 7681 static void 7682 start_element_issue_240(void *userData, const XML_Char *name, 7683 const XML_Char **atts) { 7684 DataIssue240 *mydata = (DataIssue240 *)userData; 7685 UNUSED_P(name); 7686 UNUSED_P(atts); 7687 mydata->deep++; 7688 } 7689 7690 static void 7691 end_element_issue_240(void *userData, const XML_Char *name) { 7692 DataIssue240 *mydata = (DataIssue240 *)userData; 7693 7694 UNUSED_P(name); 7695 mydata->deep--; 7696 if (mydata->deep == 0) { 7697 XML_StopParser(mydata->parser, 0); 7698 } 7699 } 7700 7701 START_TEST(test_misc_stop_during_end_handler_issue_240_1) { 7702 XML_Parser parser; 7703 DataIssue240 *mydata; 7704 enum XML_Status result; 7705 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>"; 7706 7707 parser = XML_ParserCreate(NULL); 7708 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7709 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7710 mydata->parser = parser; 7711 mydata->deep = 0; 7712 XML_SetUserData(parser, mydata); 7713 7714 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1); 7715 XML_ParserFree(parser); 7716 free(mydata); 7717 if (result != XML_STATUS_ERROR) 7718 fail("Stopping the parser did not work as expected"); 7719 } 7720 END_TEST 7721 7722 START_TEST(test_misc_stop_during_end_handler_issue_240_2) { 7723 XML_Parser parser; 7724 DataIssue240 *mydata; 7725 enum XML_Status result; 7726 const char *const doc2 = "<doc><elem/></doc>"; 7727 7728 parser = XML_ParserCreate(NULL); 7729 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7730 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7731 mydata->parser = parser; 7732 mydata->deep = 0; 7733 XML_SetUserData(parser, mydata); 7734 7735 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1); 7736 XML_ParserFree(parser); 7737 free(mydata); 7738 if (result != XML_STATUS_ERROR) 7739 fail("Stopping the parser did not work as expected"); 7740 } 7741 END_TEST 7742 7743 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { 7744 const char *const inputOne = "<!DOCTYPE d [\n" 7745 "<!ENTITY % e ']><d/>'>\n" 7746 "\n" 7747 "%e;"; 7748 const char *const inputTwo = "<!DOCTYPE d [\n" 7749 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n" 7750 "\n" 7751 "%e2;"; 7752 const char *const inputThree = "<!DOCTYPE d [\n" 7753 "<!ENTITY % e ']><d'>\n" 7754 "\n" 7755 "%e;"; 7756 const char *const inputIssue317 = "<!DOCTYPE doc [\n" 7757 "<!ENTITY % foo ']>\n" 7758 "<doc>Hell<oc (#PCDATA)*>'>\n" 7759 "%foo;\n" 7760 "]>\n" 7761 "<doc>Hello, world</dVc>"; 7762 7763 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317}; 7764 size_t inputIndex = 0; 7765 7766 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) { 7767 XML_Parser parser; 7768 enum XML_Status parseResult; 7769 int setParamEntityResult; 7770 XML_Size lineNumber; 7771 XML_Size columnNumber; 7772 const char *const input = inputs[inputIndex]; 7773 7774 parser = XML_ParserCreate(NULL); 7775 setParamEntityResult 7776 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7777 if (setParamEntityResult != 1) 7778 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS."); 7779 7780 parseResult = XML_Parse(parser, input, (int)strlen(input), 0); 7781 if (parseResult != XML_STATUS_ERROR) { 7782 parseResult = XML_Parse(parser, "", 0, 1); 7783 if (parseResult != XML_STATUS_ERROR) { 7784 fail("Parsing was expected to fail but succeeded."); 7785 } 7786 } 7787 7788 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) 7789 fail("Error code does not match XML_ERROR_INVALID_TOKEN"); 7790 7791 lineNumber = XML_GetCurrentLineNumber(parser); 7792 if (lineNumber != 4) 7793 fail("XML_GetCurrentLineNumber does not work as expected."); 7794 7795 columnNumber = XML_GetCurrentColumnNumber(parser); 7796 if (columnNumber != 0) 7797 fail("XML_GetCurrentColumnNumber does not work as expected."); 7798 7799 XML_ParserFree(parser); 7800 } 7801 } 7802 END_TEST 7803 7804 static void 7805 alloc_setup(void) { 7806 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 7807 7808 /* Ensure the parser creation will go through */ 7809 allocation_count = ALLOC_ALWAYS_SUCCEED; 7810 reallocation_count = REALLOC_ALWAYS_SUCCEED; 7811 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7812 if (g_parser == NULL) 7813 fail("Parser not created"); 7814 } 7815 7816 static void 7817 alloc_teardown(void) { 7818 basic_teardown(); 7819 } 7820 7821 /* Test the effects of allocation failures on xml declaration processing */ 7822 START_TEST(test_alloc_parse_xdecl) { 7823 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7824 "<doc>Hello, world</doc>"; 7825 int i; 7826 const int max_alloc_count = 15; 7827 7828 for (i = 0; i < max_alloc_count; i++) { 7829 allocation_count = i; 7830 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7831 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7832 != XML_STATUS_ERROR) 7833 break; 7834 /* Resetting the parser is insufficient, because some memory 7835 * allocations are cached within the parser. Instead we use 7836 * the teardown and setup routines to ensure that we have the 7837 * right sort of parser back in our hands. 7838 */ 7839 alloc_teardown(); 7840 alloc_setup(); 7841 } 7842 if (i == 0) 7843 fail("Parse succeeded despite failing allocator"); 7844 if (i == max_alloc_count) 7845 fail("Parse failed with max allocations"); 7846 } 7847 END_TEST 7848 7849 /* As above, but with an encoding big enough to cause storing the 7850 * version information to expand the string pool being used. 7851 */ 7852 static int XMLCALL 7853 long_encoding_handler(void *userData, const XML_Char *encoding, 7854 XML_Encoding *info) { 7855 int i; 7856 7857 UNUSED_P(userData); 7858 UNUSED_P(encoding); 7859 for (i = 0; i < 256; i++) 7860 info->map[i] = i; 7861 info->data = NULL; 7862 info->convert = NULL; 7863 info->release = NULL; 7864 return XML_STATUS_OK; 7865 } 7866 7867 START_TEST(test_alloc_parse_xdecl_2) { 7868 const char *text 7869 = "<?xml version='1.0' encoding='" 7870 /* Each line is 64 characters */ 7871 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456" 7872 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7873 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7874 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7875 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7876 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7877 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7878 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7879 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7880 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7881 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7882 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7883 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7884 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7885 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7886 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN" 7887 "'?>" 7888 "<doc>Hello, world</doc>"; 7889 int i; 7890 const int max_alloc_count = 20; 7891 7892 for (i = 0; i < max_alloc_count; i++) { 7893 allocation_count = i; 7894 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7895 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL); 7896 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7897 != XML_STATUS_ERROR) 7898 break; 7899 /* See comment in test_alloc_parse_xdecl() */ 7900 alloc_teardown(); 7901 alloc_setup(); 7902 } 7903 if (i == 0) 7904 fail("Parse succeeded despite failing allocator"); 7905 if (i == max_alloc_count) 7906 fail("Parse failed with max allocations"); 7907 } 7908 END_TEST 7909 7910 /* Test the effects of allocation failures on a straightforward parse */ 7911 START_TEST(test_alloc_parse_pi) { 7912 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7913 "<?pi unknown?>\n" 7914 "<doc>" 7915 "Hello, world" 7916 "</doc>"; 7917 int i; 7918 const int max_alloc_count = 15; 7919 7920 for (i = 0; i < max_alloc_count; i++) { 7921 allocation_count = i; 7922 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7923 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7924 != XML_STATUS_ERROR) 7925 break; 7926 /* See comment in test_alloc_parse_xdecl() */ 7927 alloc_teardown(); 7928 alloc_setup(); 7929 } 7930 if (i == 0) 7931 fail("Parse succeeded despite failing allocator"); 7932 if (i == max_alloc_count) 7933 fail("Parse failed with max allocations"); 7934 } 7935 END_TEST 7936 7937 START_TEST(test_alloc_parse_pi_2) { 7938 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7939 "<doc>" 7940 "Hello, world" 7941 "<?pi unknown?>\n" 7942 "</doc>"; 7943 int i; 7944 const int max_alloc_count = 15; 7945 7946 for (i = 0; i < max_alloc_count; i++) { 7947 allocation_count = i; 7948 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7949 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7950 != XML_STATUS_ERROR) 7951 break; 7952 /* See comment in test_alloc_parse_xdecl() */ 7953 alloc_teardown(); 7954 alloc_setup(); 7955 } 7956 if (i == 0) 7957 fail("Parse succeeded despite failing allocator"); 7958 if (i == max_alloc_count) 7959 fail("Parse failed with max allocations"); 7960 } 7961 END_TEST 7962 7963 START_TEST(test_alloc_parse_pi_3) { 7964 const char *text 7965 = "<?" 7966 /* 64 characters per line */ 7967 "This processing instruction should be long enough to ensure that" 7968 "it triggers the growth of an internal string pool when the " 7969 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP" 7970 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7971 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7972 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7973 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7974 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7975 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7976 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7982 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7983 "Q?><doc/>"; 7984 int i; 7985 const int max_alloc_count = 20; 7986 7987 for (i = 0; i < max_alloc_count; i++) { 7988 allocation_count = i; 7989 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7990 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7991 != XML_STATUS_ERROR) 7992 break; 7993 /* See comment in test_alloc_parse_xdecl() */ 7994 alloc_teardown(); 7995 alloc_setup(); 7996 } 7997 if (i == 0) 7998 fail("Parse succeeded despite failing allocator"); 7999 if (i == max_alloc_count) 8000 fail("Parse failed with max allocations"); 8001 } 8002 END_TEST 8003 8004 START_TEST(test_alloc_parse_comment) { 8005 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8006 "<!-- Test parsing this comment -->" 8007 "<doc>Hi</doc>"; 8008 int i; 8009 const int max_alloc_count = 15; 8010 8011 for (i = 0; i < max_alloc_count; i++) { 8012 allocation_count = i; 8013 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8014 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8015 != XML_STATUS_ERROR) 8016 break; 8017 /* See comment in test_alloc_parse_xdecl() */ 8018 alloc_teardown(); 8019 alloc_setup(); 8020 } 8021 if (i == 0) 8022 fail("Parse succeeded despite failing allocator"); 8023 if (i == max_alloc_count) 8024 fail("Parse failed with max allocations"); 8025 } 8026 END_TEST 8027 8028 START_TEST(test_alloc_parse_comment_2) { 8029 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8030 "<doc>" 8031 "Hello, world" 8032 "<!-- Parse this comment too -->" 8033 "</doc>"; 8034 int i; 8035 const int max_alloc_count = 15; 8036 8037 for (i = 0; i < max_alloc_count; i++) { 8038 allocation_count = i; 8039 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8040 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8041 != XML_STATUS_ERROR) 8042 break; 8043 /* See comment in test_alloc_parse_xdecl() */ 8044 alloc_teardown(); 8045 alloc_setup(); 8046 } 8047 if (i == 0) 8048 fail("Parse succeeded despite failing allocator"); 8049 if (i == max_alloc_count) 8050 fail("Parse failed with max allocations"); 8051 } 8052 END_TEST 8053 8054 static int XMLCALL 8055 external_entity_duff_loader(XML_Parser parser, const XML_Char *context, 8056 const XML_Char *base, const XML_Char *systemId, 8057 const XML_Char *publicId) { 8058 XML_Parser new_parser; 8059 unsigned int i; 8060 const unsigned int max_alloc_count = 10; 8061 8062 UNUSED_P(base); 8063 UNUSED_P(systemId); 8064 UNUSED_P(publicId); 8065 /* Try a few different allocation levels */ 8066 for (i = 0; i < max_alloc_count; i++) { 8067 allocation_count = i; 8068 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8069 if (new_parser != NULL) { 8070 XML_ParserFree(new_parser); 8071 break; 8072 } 8073 } 8074 if (i == 0) 8075 fail("External parser creation ignored failing allocator"); 8076 else if (i == max_alloc_count) 8077 fail("Extern parser not created with max allocation count"); 8078 8079 /* Make sure other random allocation doesn't now fail */ 8080 allocation_count = ALLOC_ALWAYS_SUCCEED; 8081 8082 /* Make sure the failure code path is executed too */ 8083 return XML_STATUS_ERROR; 8084 } 8085 8086 /* Test that external parser creation running out of memory is 8087 * correctly reported. Based on the external entity test cases. 8088 */ 8089 START_TEST(test_alloc_create_external_parser) { 8090 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8091 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8092 "<doc>&entity;</doc>"; 8093 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8094 8095 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8096 XML_SetUserData(g_parser, foo_text); 8097 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader); 8098 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8099 != XML_STATUS_ERROR) { 8100 fail("External parser allocator returned success incorrectly"); 8101 } 8102 } 8103 END_TEST 8104 8105 /* More external parser memory allocation testing */ 8106 START_TEST(test_alloc_run_external_parser) { 8107 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8108 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8109 "<doc>&entity;</doc>"; 8110 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8111 unsigned int i; 8112 const unsigned int max_alloc_count = 15; 8113 8114 for (i = 0; i < max_alloc_count; i++) { 8115 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8116 XML_SetUserData(g_parser, foo_text); 8117 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 8118 allocation_count = i; 8119 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8120 != XML_STATUS_ERROR) 8121 break; 8122 /* See comment in test_alloc_parse_xdecl() */ 8123 alloc_teardown(); 8124 alloc_setup(); 8125 } 8126 if (i == 0) 8127 fail("Parsing ignored failing allocator"); 8128 else if (i == max_alloc_count) 8129 fail("Parsing failed with allocation count 10"); 8130 } 8131 END_TEST 8132 8133 static int XMLCALL 8134 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context, 8135 const XML_Char *base, const XML_Char *systemId, 8136 const XML_Char *publicId) { 8137 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8138 const char *text; 8139 XML_Parser new_parser; 8140 int i; 8141 const int max_alloc_count = 20; 8142 8143 UNUSED_P(base); 8144 UNUSED_P(systemId); 8145 UNUSED_P(publicId); 8146 if (callno == 0) { 8147 /* First time through, check how many calls to malloc occur */ 8148 text = ("<!ELEMENT doc (e+)>\n" 8149 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8150 "<!ELEMENT e EMPTY>\n"); 8151 allocation_count = 10000; 8152 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8153 if (new_parser == NULL) { 8154 fail("Unable to allocate first external parser"); 8155 return XML_STATUS_ERROR; 8156 } 8157 /* Stash the number of calls in the user data */ 8158 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count)); 8159 } else { 8160 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8161 "<e/>"); 8162 /* Try at varying levels to exercise more code paths */ 8163 for (i = 0; i < max_alloc_count; i++) { 8164 allocation_count = callno + i; 8165 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8166 if (new_parser != NULL) 8167 break; 8168 } 8169 if (i == 0) { 8170 fail("Second external parser unexpectedly created"); 8171 XML_ParserFree(new_parser); 8172 return XML_STATUS_ERROR; 8173 } else if (i == max_alloc_count) { 8174 fail("Second external parser not created"); 8175 return XML_STATUS_ERROR; 8176 } 8177 } 8178 8179 allocation_count = ALLOC_ALWAYS_SUCCEED; 8180 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE) 8181 == XML_STATUS_ERROR) { 8182 xml_failure(new_parser); 8183 return XML_STATUS_ERROR; 8184 } 8185 XML_ParserFree(new_parser); 8186 return XML_STATUS_OK; 8187 } 8188 8189 /* Test that running out of memory in dtdCopy is correctly reported. 8190 * Based on test_default_ns_from_ext_subset_and_ext_ge() 8191 */ 8192 START_TEST(test_alloc_dtd_copy_default_atts) { 8193 const char *text = "<?xml version='1.0'?>\n" 8194 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8195 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8196 "]>\n" 8197 "<doc xmlns='http://example.org/ns1'>\n" 8198 "&en;\n" 8199 "</doc>"; 8200 8201 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8202 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler); 8203 XML_SetUserData(g_parser, NULL); 8204 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8205 == XML_STATUS_ERROR) 8206 xml_failure(g_parser); 8207 } 8208 END_TEST 8209 8210 static int XMLCALL 8211 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context, 8212 const XML_Char *base, const XML_Char *systemId, 8213 const XML_Char *publicId) { 8214 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8215 const char *text; 8216 XML_Parser new_parser; 8217 enum XML_Status rv; 8218 8219 UNUSED_P(base); 8220 UNUSED_P(systemId); 8221 UNUSED_P(publicId); 8222 if (callno == 0) { 8223 /* Try different allocation levels for whole exercise */ 8224 text = ("<!ELEMENT doc (e+)>\n" 8225 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8226 "<!ELEMENT e EMPTY>\n"); 8227 XML_SetUserData(parser, (void *)(intptr_t)1); 8228 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8229 if (new_parser == NULL) 8230 return XML_STATUS_ERROR; 8231 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8232 } else { 8233 /* Just run through once */ 8234 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8235 "<e/>"); 8236 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8237 if (new_parser == NULL) 8238 return XML_STATUS_ERROR; 8239 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8240 } 8241 XML_ParserFree(new_parser); 8242 if (rv == XML_STATUS_ERROR) 8243 return XML_STATUS_ERROR; 8244 return XML_STATUS_OK; 8245 } 8246 8247 /* Test more external entity allocation failure paths */ 8248 START_TEST(test_alloc_external_entity) { 8249 const char *text = "<?xml version='1.0'?>\n" 8250 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8251 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8252 "]>\n" 8253 "<doc xmlns='http://example.org/ns1'>\n" 8254 "&en;\n" 8255 "</doc>"; 8256 int i; 8257 const int alloc_test_max_repeats = 50; 8258 8259 for (i = 0; i < alloc_test_max_repeats; i++) { 8260 allocation_count = -1; 8261 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8262 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2); 8263 XML_SetUserData(g_parser, NULL); 8264 allocation_count = i; 8265 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8266 == XML_STATUS_OK) 8267 break; 8268 /* See comment in test_alloc_parse_xdecl() */ 8269 alloc_teardown(); 8270 alloc_setup(); 8271 } 8272 allocation_count = -1; 8273 if (i == 0) 8274 fail("External entity parsed despite duff allocator"); 8275 if (i == alloc_test_max_repeats) 8276 fail("External entity not parsed at max allocation count"); 8277 } 8278 END_TEST 8279 8280 /* Test more allocation failure paths */ 8281 static int XMLCALL 8282 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context, 8283 const XML_Char *base, 8284 const XML_Char *systemId, 8285 const XML_Char *publicId) { 8286 /* As for external_entity_loader() */ 8287 const char *text = "<?xml encoding='iso-8859-3'?>" 8288 "\xC3\xA9"; 8289 XML_Parser ext_parser; 8290 enum XML_Status status; 8291 8292 UNUSED_P(base); 8293 UNUSED_P(systemId); 8294 UNUSED_P(publicId); 8295 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8296 if (ext_parser == NULL) 8297 return XML_STATUS_ERROR; 8298 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) { 8299 XML_ParserFree(ext_parser); 8300 return XML_STATUS_ERROR; 8301 } 8302 status 8303 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8304 XML_ParserFree(ext_parser); 8305 if (status == XML_STATUS_ERROR) 8306 return XML_STATUS_ERROR; 8307 return XML_STATUS_OK; 8308 } 8309 8310 START_TEST(test_alloc_ext_entity_set_encoding) { 8311 const char *text = "<!DOCTYPE doc [\n" 8312 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8313 "]>\n" 8314 "<doc>&en;</doc>"; 8315 int i; 8316 const int max_allocation_count = 30; 8317 8318 for (i = 0; i < max_allocation_count; i++) { 8319 XML_SetExternalEntityRefHandler(g_parser, 8320 external_entity_alloc_set_encoding); 8321 allocation_count = i; 8322 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8323 == XML_STATUS_OK) 8324 break; 8325 allocation_count = -1; 8326 /* See comment in test_alloc_parse_xdecl() */ 8327 alloc_teardown(); 8328 alloc_setup(); 8329 } 8330 if (i == 0) 8331 fail("Encoding check succeeded despite failing allocator"); 8332 if (i == max_allocation_count) 8333 fail("Encoding failed at max allocation count"); 8334 } 8335 END_TEST 8336 8337 static int XMLCALL 8338 unknown_released_encoding_handler(void *data, const XML_Char *encoding, 8339 XML_Encoding *info) { 8340 UNUSED_P(data); 8341 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) { 8342 int i; 8343 8344 for (i = 0; i < 256; i++) 8345 info->map[i] = i; 8346 info->data = NULL; 8347 info->convert = NULL; 8348 info->release = dummy_release; 8349 return XML_STATUS_OK; 8350 } 8351 return XML_STATUS_ERROR; 8352 } 8353 8354 /* Test the effects of allocation failure in internal entities. 8355 * Based on test_unknown_encoding_internal_entity 8356 */ 8357 START_TEST(test_alloc_internal_entity) { 8358 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 8359 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 8360 "<test a='&foo;'/>"; 8361 unsigned int i; 8362 const unsigned int max_alloc_count = 20; 8363 8364 for (i = 0; i < max_alloc_count; i++) { 8365 allocation_count = i; 8366 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, 8367 NULL); 8368 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8369 != XML_STATUS_ERROR) 8370 break; 8371 /* See comment in test_alloc_parse_xdecl() */ 8372 alloc_teardown(); 8373 alloc_setup(); 8374 } 8375 if (i == 0) 8376 fail("Internal entity worked despite failing allocations"); 8377 else if (i == max_alloc_count) 8378 fail("Internal entity failed at max allocation count"); 8379 } 8380 END_TEST 8381 8382 /* Test the robustness against allocation failure of element handling 8383 * Based on test_dtd_default_handling(). 8384 */ 8385 START_TEST(test_alloc_dtd_default_handling) { 8386 const char *text = "<!DOCTYPE doc [\n" 8387 "<!ENTITY e SYSTEM 'http://example.org/e'>\n" 8388 "<!NOTATION n SYSTEM 'http://example.org/n'>\n" 8389 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n" 8390 "<!ELEMENT doc (#PCDATA)>\n" 8391 "<!ATTLIST doc a CDATA #IMPLIED>\n" 8392 "<?pi in dtd?>\n" 8393 "<!--comment in dtd-->\n" 8394 "]>\n" 8395 "<doc><![CDATA[text in doc]]></doc>"; 8396 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>"); 8397 CharData storage; 8398 int i; 8399 const int max_alloc_count = 25; 8400 8401 for (i = 0; i < max_alloc_count; i++) { 8402 allocation_count = i; 8403 dummy_handler_flags = 0; 8404 XML_SetDefaultHandler(g_parser, accumulate_characters); 8405 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 8406 dummy_end_doctype_handler); 8407 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8408 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8409 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 8410 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8411 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8412 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8413 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler, 8414 dummy_end_cdata_handler); 8415 XML_SetUnparsedEntityDeclHandler(g_parser, 8416 dummy_unparsed_entity_decl_handler); 8417 CharData_Init(&storage); 8418 XML_SetUserData(g_parser, &storage); 8419 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 8420 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8421 != XML_STATUS_ERROR) 8422 break; 8423 /* See comment in test_alloc_parse_xdecl() */ 8424 alloc_teardown(); 8425 alloc_setup(); 8426 } 8427 if (i == 0) 8428 fail("Default DTD parsed despite allocation failures"); 8429 if (i == max_alloc_count) 8430 fail("Default DTD not parsed with maximum alloc count"); 8431 CharData_CheckXMLChars(&storage, expected); 8432 if (dummy_handler_flags 8433 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG 8434 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG 8435 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG 8436 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG 8437 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG 8438 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG)) 8439 fail("Not all handlers were called"); 8440 } 8441 END_TEST 8442 8443 /* Test robustness of XML_SetEncoding() with a failing allocator */ 8444 START_TEST(test_alloc_explicit_encoding) { 8445 int i; 8446 const int max_alloc_count = 5; 8447 8448 for (i = 0; i < max_alloc_count; i++) { 8449 allocation_count = i; 8450 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK) 8451 break; 8452 } 8453 if (i == 0) 8454 fail("Encoding set despite failing allocator"); 8455 else if (i == max_alloc_count) 8456 fail("Encoding not set at max allocation count"); 8457 } 8458 END_TEST 8459 8460 /* Test robustness of XML_SetBase against a failing allocator */ 8461 START_TEST(test_alloc_set_base) { 8462 const XML_Char *new_base = XCS("/local/file/name.xml"); 8463 int i; 8464 const int max_alloc_count = 5; 8465 8466 for (i = 0; i < max_alloc_count; i++) { 8467 allocation_count = i; 8468 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK) 8469 break; 8470 } 8471 if (i == 0) 8472 fail("Base set despite failing allocator"); 8473 else if (i == max_alloc_count) 8474 fail("Base not set with max allocation count"); 8475 } 8476 END_TEST 8477 8478 /* Test buffer extension in the face of a duff reallocator */ 8479 START_TEST(test_alloc_realloc_buffer) { 8480 const char *text = get_buffer_test_text; 8481 void *buffer; 8482 int i; 8483 const int max_realloc_count = 10; 8484 8485 /* Get a smallish buffer */ 8486 for (i = 0; i < max_realloc_count; i++) { 8487 reallocation_count = i; 8488 buffer = XML_GetBuffer(g_parser, 1536); 8489 if (buffer == NULL) 8490 fail("1.5K buffer reallocation failed"); 8491 assert(buffer != NULL); 8492 memcpy(buffer, text, strlen(text)); 8493 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 8494 == XML_STATUS_OK) 8495 break; 8496 /* See comment in test_alloc_parse_xdecl() */ 8497 alloc_teardown(); 8498 alloc_setup(); 8499 } 8500 reallocation_count = -1; 8501 if (i == 0) 8502 fail("Parse succeeded with no reallocation"); 8503 else if (i == max_realloc_count) 8504 fail("Parse failed with max reallocation count"); 8505 } 8506 END_TEST 8507 8508 /* Same test for external entity parsers */ 8509 static int XMLCALL 8510 external_entity_reallocator(XML_Parser parser, const XML_Char *context, 8511 const XML_Char *base, const XML_Char *systemId, 8512 const XML_Char *publicId) { 8513 const char *text = get_buffer_test_text; 8514 XML_Parser ext_parser; 8515 void *buffer; 8516 enum XML_Status status; 8517 8518 UNUSED_P(base); 8519 UNUSED_P(systemId); 8520 UNUSED_P(publicId); 8521 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8522 if (ext_parser == NULL) 8523 fail("Could not create external entity parser"); 8524 8525 reallocation_count = (intptr_t)XML_GetUserData(parser); 8526 buffer = XML_GetBuffer(ext_parser, 1536); 8527 if (buffer == NULL) 8528 fail("Buffer allocation failed"); 8529 assert(buffer != NULL); 8530 memcpy(buffer, text, strlen(text)); 8531 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE); 8532 reallocation_count = -1; 8533 XML_ParserFree(ext_parser); 8534 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR; 8535 } 8536 8537 START_TEST(test_alloc_ext_entity_realloc_buffer) { 8538 const char *text = "<!DOCTYPE doc [\n" 8539 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8540 "]>\n" 8541 "<doc>&en;</doc>"; 8542 int i; 8543 const int max_realloc_count = 10; 8544 8545 for (i = 0; i < max_realloc_count; i++) { 8546 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator); 8547 XML_SetUserData(g_parser, (void *)(intptr_t)i); 8548 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8549 == XML_STATUS_OK) 8550 break; 8551 /* See comment in test_alloc_parse_xdecl() */ 8552 alloc_teardown(); 8553 alloc_setup(); 8554 } 8555 if (i == 0) 8556 fail("Succeeded with no reallocations"); 8557 if (i == max_realloc_count) 8558 fail("Failed with max reallocations"); 8559 } 8560 END_TEST 8561 8562 /* Test elements with many attributes are handled correctly */ 8563 START_TEST(test_alloc_realloc_many_attributes) { 8564 const char *text = "<!DOCTYPE doc [\n" 8565 "<!ATTLIST doc za CDATA 'default'>\n" 8566 "<!ATTLIST doc zb CDATA 'def2'>\n" 8567 "<!ATTLIST doc zc CDATA 'def3'>\n" 8568 "]>\n" 8569 "<doc a='1'" 8570 " b='2'" 8571 " c='3'" 8572 " d='4'" 8573 " e='5'" 8574 " f='6'" 8575 " g='7'" 8576 " h='8'" 8577 " i='9'" 8578 " j='10'" 8579 " k='11'" 8580 " l='12'" 8581 " m='13'" 8582 " n='14'" 8583 " p='15'" 8584 " q='16'" 8585 " r='17'" 8586 " s='18'>" 8587 "</doc>"; 8588 int i; 8589 const int max_realloc_count = 10; 8590 8591 for (i = 0; i < max_realloc_count; i++) { 8592 reallocation_count = i; 8593 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8594 != XML_STATUS_ERROR) 8595 break; 8596 /* See comment in test_alloc_parse_xdecl() */ 8597 alloc_teardown(); 8598 alloc_setup(); 8599 } 8600 if (i == 0) 8601 fail("Parse succeeded despite no reallocations"); 8602 if (i == max_realloc_count) 8603 fail("Parse failed at max reallocations"); 8604 } 8605 END_TEST 8606 8607 /* Test handling of a public entity with failing allocator */ 8608 START_TEST(test_alloc_public_entity_value) { 8609 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8610 "<doc></doc>\n"; 8611 char dtd_text[] 8612 = "<!ELEMENT doc EMPTY>\n" 8613 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n" 8614 "<!ENTITY % " 8615 /* Each line is 64 characters */ 8616 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8620 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8621 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8623 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8624 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8625 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8626 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8627 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8628 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8629 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8630 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8631 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8632 " '%e1;'>\n" 8633 "%e1;\n"; 8634 int i; 8635 const int max_alloc_count = 50; 8636 8637 for (i = 0; i < max_alloc_count; i++) { 8638 allocation_count = i; 8639 dummy_handler_flags = 0; 8640 XML_SetUserData(g_parser, dtd_text); 8641 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8642 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8643 /* Provoke a particular code path */ 8644 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8645 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8646 != XML_STATUS_ERROR) 8647 break; 8648 /* See comment in test_alloc_parse_xdecl() */ 8649 alloc_teardown(); 8650 alloc_setup(); 8651 } 8652 if (i == 0) 8653 fail("Parsing worked despite failing allocation"); 8654 if (i == max_alloc_count) 8655 fail("Parsing failed at max allocation count"); 8656 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG) 8657 fail("Entity declaration handler not called"); 8658 } 8659 END_TEST 8660 8661 START_TEST(test_alloc_realloc_subst_public_entity_value) { 8662 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8663 "<doc></doc>\n"; 8664 char dtd_text[] 8665 = "<!ELEMENT doc EMPTY>\n" 8666 "<!ENTITY % " 8667 /* Each line is 64 characters */ 8668 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8669 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8670 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8671 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8672 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8673 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8674 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8675 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8676 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8677 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8678 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8679 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8680 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8681 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8682 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8683 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8684 " PUBLIC 'foo' 'bar.ent'>\n" 8685 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8686 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8687 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8688 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8689 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8690 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8691 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8692 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8693 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8694 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8695 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8696 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8697 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8698 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8699 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8700 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;"; 8701 int i; 8702 const int max_realloc_count = 10; 8703 8704 for (i = 0; i < max_realloc_count; i++) { 8705 reallocation_count = i; 8706 XML_SetUserData(g_parser, dtd_text); 8707 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8708 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8709 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8710 != XML_STATUS_ERROR) 8711 break; 8712 /* See comment in test_alloc_parse_xdecl() */ 8713 alloc_teardown(); 8714 alloc_setup(); 8715 } 8716 if (i == 0) 8717 fail("Parsing worked despite failing reallocation"); 8718 if (i == max_realloc_count) 8719 fail("Parsing failed at max reallocation count"); 8720 } 8721 END_TEST 8722 8723 START_TEST(test_alloc_parse_public_doctype) { 8724 const char *text 8725 = "<?xml version='1.0' encoding='utf-8'?>\n" 8726 "<!DOCTYPE doc PUBLIC '" 8727 /* 64 characters per line */ 8728 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 8729 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8730 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8731 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8732 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8733 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8734 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8735 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8736 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8737 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8738 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8739 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8740 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8741 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8742 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8743 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8744 "' 'test'>\n" 8745 "<doc></doc>"; 8746 int i; 8747 const int max_alloc_count = 25; 8748 8749 for (i = 0; i < max_alloc_count; i++) { 8750 allocation_count = i; 8751 dummy_handler_flags = 0; 8752 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8753 dummy_end_doctype_decl_handler); 8754 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8755 != XML_STATUS_ERROR) 8756 break; 8757 /* See comment in test_alloc_parse_xdecl() */ 8758 alloc_teardown(); 8759 alloc_setup(); 8760 } 8761 if (i == 0) 8762 fail("Parse succeeded despite failing allocator"); 8763 if (i == max_alloc_count) 8764 fail("Parse failed at maximum allocation count"); 8765 if (dummy_handler_flags 8766 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG 8767 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG)) 8768 fail("Doctype handler functions not called"); 8769 } 8770 END_TEST 8771 8772 START_TEST(test_alloc_parse_public_doctype_long_name) { 8773 const char *text 8774 = "<?xml version='1.0' encoding='utf-8'?>\n" 8775 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '" 8776 /* 64 characters per line */ 8777 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8778 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8779 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8780 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8781 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8782 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8783 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8784 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8785 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8786 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8787 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8788 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8789 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8790 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8791 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8792 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8793 "'>\n" 8794 "<doc></doc>"; 8795 int i; 8796 const int max_alloc_count = 25; 8797 8798 for (i = 0; i < max_alloc_count; i++) { 8799 allocation_count = i; 8800 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8801 dummy_end_doctype_decl_handler); 8802 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8803 != XML_STATUS_ERROR) 8804 break; 8805 /* See comment in test_alloc_parse_xdecl() */ 8806 alloc_teardown(); 8807 alloc_setup(); 8808 } 8809 if (i == 0) 8810 fail("Parse succeeded despite failing allocator"); 8811 if (i == max_alloc_count) 8812 fail("Parse failed at maximum allocation count"); 8813 } 8814 END_TEST 8815 8816 static int XMLCALL 8817 external_entity_alloc(XML_Parser parser, const XML_Char *context, 8818 const XML_Char *base, const XML_Char *systemId, 8819 const XML_Char *publicId) { 8820 const char *text = (const char *)XML_GetUserData(parser); 8821 XML_Parser ext_parser; 8822 int parse_res; 8823 8824 UNUSED_P(base); 8825 UNUSED_P(systemId); 8826 UNUSED_P(publicId); 8827 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8828 if (ext_parser == NULL) 8829 return XML_STATUS_ERROR; 8830 parse_res 8831 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8832 XML_ParserFree(ext_parser); 8833 return parse_res; 8834 } 8835 8836 /* Test foreign DTD handling */ 8837 START_TEST(test_alloc_set_foreign_dtd) { 8838 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 8839 "<doc>&entity;</doc>"; 8840 char text2[] = "<!ELEMENT doc (#PCDATA)*>"; 8841 int i; 8842 const int max_alloc_count = 25; 8843 8844 for (i = 0; i < max_alloc_count; i++) { 8845 allocation_count = i; 8846 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8847 XML_SetUserData(g_parser, &text2); 8848 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8849 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 8850 fail("Could not set foreign DTD"); 8851 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE) 8852 != XML_STATUS_ERROR) 8853 break; 8854 /* See comment in test_alloc_parse_xdecl() */ 8855 alloc_teardown(); 8856 alloc_setup(); 8857 } 8858 if (i == 0) 8859 fail("Parse succeeded despite failing allocator"); 8860 if (i == max_alloc_count) 8861 fail("Parse failed at maximum allocation count"); 8862 } 8863 END_TEST 8864 8865 /* Test based on ibm/valid/P32/ibm32v04.xml */ 8866 START_TEST(test_alloc_attribute_enum_value) { 8867 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8868 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8869 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 8870 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n" 8871 "<!ELEMENT a EMPTY>\n" 8872 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>"; 8873 int i; 8874 const int max_alloc_count = 30; 8875 8876 for (i = 0; i < max_alloc_count; i++) { 8877 allocation_count = i; 8878 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8879 XML_SetUserData(g_parser, dtd_text); 8880 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8881 /* An attribute list handler provokes a different code path */ 8882 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8883 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8884 != XML_STATUS_ERROR) 8885 break; 8886 /* See comment in test_alloc_parse_xdecl() */ 8887 alloc_teardown(); 8888 alloc_setup(); 8889 } 8890 if (i == 0) 8891 fail("Parse succeeded despite failing allocator"); 8892 if (i == max_alloc_count) 8893 fail("Parse failed at maximum allocation count"); 8894 } 8895 END_TEST 8896 8897 /* Test attribute enums sufficient to overflow the string pool */ 8898 START_TEST(test_alloc_realloc_attribute_enum_value) { 8899 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8900 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8901 "<animal>This is a yellow tiger</animal>"; 8902 /* We wish to define a collection of attribute enums that will 8903 * cause the string pool storing them to have to expand. This 8904 * means more than 1024 bytes, including the parentheses and 8905 * separator bars. 8906 */ 8907 char dtd_text[] 8908 = "<!ELEMENT animal (#PCDATA)*>\n" 8909 "<!ATTLIST animal thing " 8910 "(default" 8911 /* Each line is 64 characters */ 8912 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8913 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8914 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8915 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8916 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8917 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8918 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8919 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8920 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8921 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8922 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8923 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8924 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8925 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8926 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8927 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)" 8928 " 'default'>"; 8929 int i; 8930 const int max_realloc_count = 10; 8931 8932 for (i = 0; i < max_realloc_count; i++) { 8933 reallocation_count = i; 8934 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8935 XML_SetUserData(g_parser, dtd_text); 8936 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8937 /* An attribute list handler provokes a different code path */ 8938 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8939 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8940 != XML_STATUS_ERROR) 8941 break; 8942 /* See comment in test_alloc_parse_xdecl() */ 8943 alloc_teardown(); 8944 alloc_setup(); 8945 } 8946 if (i == 0) 8947 fail("Parse succeeded despite failing reallocator"); 8948 if (i == max_realloc_count) 8949 fail("Parse failed at maximum reallocation count"); 8950 } 8951 END_TEST 8952 8953 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */ 8954 START_TEST(test_alloc_realloc_implied_attribute) { 8955 /* Forcing this particular code path is a balancing act. The 8956 * addition of the closing parenthesis and terminal NUL must be 8957 * what pushes the string of enums over the 1024-byte limit, 8958 * otherwise a different code path will pick up the realloc. 8959 */ 8960 const char *text 8961 = "<!DOCTYPE doc [\n" 8962 "<!ELEMENT doc EMPTY>\n" 8963 "<!ATTLIST doc a " 8964 /* Each line is 64 characters */ 8965 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8966 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8967 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8968 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8969 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8970 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8971 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8972 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8973 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8974 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8975 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8976 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8977 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8978 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8979 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8980 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 8981 " #IMPLIED>\n" 8982 "]><doc/>"; 8983 int i; 8984 const int max_realloc_count = 10; 8985 8986 for (i = 0; i < max_realloc_count; i++) { 8987 reallocation_count = i; 8988 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8989 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8990 != XML_STATUS_ERROR) 8991 break; 8992 /* See comment in test_alloc_parse_xdecl() */ 8993 alloc_teardown(); 8994 alloc_setup(); 8995 } 8996 if (i == 0) 8997 fail("Parse succeeded despite failing reallocator"); 8998 if (i == max_realloc_count) 8999 fail("Parse failed at maximum reallocation count"); 9000 } 9001 END_TEST 9002 9003 /* Test attribute enums in a defaulted attribute forcing pool growth */ 9004 START_TEST(test_alloc_realloc_default_attribute) { 9005 /* Forcing this particular code path is a balancing act. The 9006 * addition of the closing parenthesis and terminal NUL must be 9007 * what pushes the string of enums over the 1024-byte limit, 9008 * otherwise a different code path will pick up the realloc. 9009 */ 9010 const char *text 9011 = "<!DOCTYPE doc [\n" 9012 "<!ELEMENT doc EMPTY>\n" 9013 "<!ATTLIST doc a " 9014 /* Each line is 64 characters */ 9015 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9016 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9017 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9018 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9019 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9020 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9021 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9022 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9023 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9024 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9025 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9026 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9027 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9028 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9029 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9030 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 9031 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'" 9032 ">\n]><doc/>"; 9033 int i; 9034 const int max_realloc_count = 10; 9035 9036 for (i = 0; i < max_realloc_count; i++) { 9037 reallocation_count = i; 9038 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9039 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9040 != XML_STATUS_ERROR) 9041 break; 9042 /* See comment in test_alloc_parse_xdecl() */ 9043 alloc_teardown(); 9044 alloc_setup(); 9045 } 9046 if (i == 0) 9047 fail("Parse succeeded despite failing reallocator"); 9048 if (i == max_realloc_count) 9049 fail("Parse failed at maximum reallocation count"); 9050 } 9051 END_TEST 9052 9053 /* Test long notation name with dodgy allocator */ 9054 START_TEST(test_alloc_notation) { 9055 const char *text 9056 = "<!DOCTYPE doc [\n" 9057 "<!NOTATION " 9058 /* Each line is 64 characters */ 9059 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9060 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9061 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9062 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9063 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9064 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9065 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9066 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9067 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9068 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9069 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9070 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9071 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9072 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9073 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9074 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9075 " SYSTEM 'http://example.org/n'>\n" 9076 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA " 9077 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9078 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9079 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9080 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9081 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9082 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9083 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9084 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9085 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9086 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9087 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9088 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9089 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9090 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9091 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9092 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9093 ">\n" 9094 "<!ELEMENT doc EMPTY>\n" 9095 "]>\n<doc/>"; 9096 int i; 9097 const int max_alloc_count = 20; 9098 9099 for (i = 0; i < max_alloc_count; i++) { 9100 allocation_count = i; 9101 dummy_handler_flags = 0; 9102 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9103 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 9104 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9105 != XML_STATUS_ERROR) 9106 break; 9107 /* See comment in test_alloc_parse_xdecl() */ 9108 alloc_teardown(); 9109 alloc_setup(); 9110 } 9111 if (i == 0) 9112 fail("Parse succeeded despite allocation failures"); 9113 if (i == max_alloc_count) 9114 fail("Parse failed at maximum allocation count"); 9115 if (dummy_handler_flags 9116 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG)) 9117 fail("Entity declaration handler not called"); 9118 } 9119 END_TEST 9120 9121 /* Test public notation with dodgy allocator */ 9122 START_TEST(test_alloc_public_notation) { 9123 const char *text 9124 = "<!DOCTYPE doc [\n" 9125 "<!NOTATION note PUBLIC '" 9126 /* 64 characters per line */ 9127 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9128 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9129 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9130 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9131 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9132 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9133 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9134 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9135 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9136 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9137 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9138 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9139 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9140 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9141 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9142 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9143 "' 'foo'>\n" 9144 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9145 "<!ELEMENT doc EMPTY>\n" 9146 "]>\n<doc/>"; 9147 int i; 9148 const int max_alloc_count = 20; 9149 9150 for (i = 0; i < max_alloc_count; i++) { 9151 allocation_count = i; 9152 dummy_handler_flags = 0; 9153 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9154 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9155 != XML_STATUS_ERROR) 9156 break; 9157 /* See comment in test_alloc_parse_xdecl() */ 9158 alloc_teardown(); 9159 alloc_setup(); 9160 } 9161 if (i == 0) 9162 fail("Parse succeeded despite allocation failures"); 9163 if (i == max_alloc_count) 9164 fail("Parse failed at maximum allocation count"); 9165 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9166 fail("Notation handler not called"); 9167 } 9168 END_TEST 9169 9170 /* Test public notation with dodgy allocator */ 9171 START_TEST(test_alloc_system_notation) { 9172 const char *text 9173 = "<!DOCTYPE doc [\n" 9174 "<!NOTATION note SYSTEM '" 9175 /* 64 characters per line */ 9176 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9177 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9178 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9179 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9180 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9181 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9182 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9183 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9184 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9185 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9186 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9187 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9188 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9189 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9190 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9191 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9192 "'>\n" 9193 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9194 "<!ELEMENT doc EMPTY>\n" 9195 "]>\n<doc/>"; 9196 int i; 9197 const int max_alloc_count = 20; 9198 9199 for (i = 0; i < max_alloc_count; i++) { 9200 allocation_count = i; 9201 dummy_handler_flags = 0; 9202 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9203 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9204 != XML_STATUS_ERROR) 9205 break; 9206 /* See comment in test_alloc_parse_xdecl() */ 9207 alloc_teardown(); 9208 alloc_setup(); 9209 } 9210 if (i == 0) 9211 fail("Parse succeeded despite allocation failures"); 9212 if (i == max_alloc_count) 9213 fail("Parse failed at maximum allocation count"); 9214 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9215 fail("Notation handler not called"); 9216 } 9217 END_TEST 9218 9219 START_TEST(test_alloc_nested_groups) { 9220 const char *text 9221 = "<!DOCTYPE doc [\n" 9222 "<!ELEMENT doc " 9223 /* Sixteen elements per line */ 9224 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9225 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9226 "))))))))))))))))))))))))))))))))>\n" 9227 "<!ELEMENT e EMPTY>" 9228 "]>\n" 9229 "<doc><e/></doc>"; 9230 CharData storage; 9231 int i; 9232 const int max_alloc_count = 20; 9233 9234 for (i = 0; i < max_alloc_count; i++) { 9235 allocation_count = i; 9236 CharData_Init(&storage); 9237 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9238 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9239 XML_SetUserData(g_parser, &storage); 9240 dummy_handler_flags = 0; 9241 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9242 != XML_STATUS_ERROR) 9243 break; 9244 /* See comment in test_alloc_parse_xdecl() */ 9245 alloc_teardown(); 9246 alloc_setup(); 9247 } 9248 9249 if (i == 0) 9250 fail("Parse succeeded despite failing reallocator"); 9251 if (i == max_alloc_count) 9252 fail("Parse failed at maximum reallocation count"); 9253 CharData_CheckXMLChars(&storage, XCS("doce")); 9254 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9255 fail("Element handler not fired"); 9256 } 9257 END_TEST 9258 9259 START_TEST(test_alloc_realloc_nested_groups) { 9260 const char *text 9261 = "<!DOCTYPE doc [\n" 9262 "<!ELEMENT doc " 9263 /* Sixteen elements per line */ 9264 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9265 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9266 "))))))))))))))))))))))))))))))))>\n" 9267 "<!ELEMENT e EMPTY>" 9268 "]>\n" 9269 "<doc><e/></doc>"; 9270 CharData storage; 9271 int i; 9272 const int max_realloc_count = 10; 9273 9274 for (i = 0; i < max_realloc_count; i++) { 9275 reallocation_count = i; 9276 CharData_Init(&storage); 9277 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9278 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9279 XML_SetUserData(g_parser, &storage); 9280 dummy_handler_flags = 0; 9281 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9282 != XML_STATUS_ERROR) 9283 break; 9284 /* See comment in test_alloc_parse_xdecl() */ 9285 alloc_teardown(); 9286 alloc_setup(); 9287 } 9288 9289 if (i == 0) 9290 fail("Parse succeeded despite failing reallocator"); 9291 if (i == max_realloc_count) 9292 fail("Parse failed at maximum reallocation count"); 9293 CharData_CheckXMLChars(&storage, XCS("doce")); 9294 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9295 fail("Element handler not fired"); 9296 } 9297 END_TEST 9298 9299 START_TEST(test_alloc_large_group) { 9300 const char *text = "<!DOCTYPE doc [\n" 9301 "<!ELEMENT doc (" 9302 "a1|a2|a3|a4|a5|a6|a7|a8|" 9303 "b1|b2|b3|b4|b5|b6|b7|b8|" 9304 "c1|c2|c3|c4|c5|c6|c7|c8|" 9305 "d1|d2|d3|d4|d5|d6|d7|d8|" 9306 "e1" 9307 ")+>\n" 9308 "]>\n" 9309 "<doc>\n" 9310 "<a1/>\n" 9311 "</doc>\n"; 9312 int i; 9313 const int max_alloc_count = 50; 9314 9315 for (i = 0; i < max_alloc_count; i++) { 9316 allocation_count = i; 9317 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9318 dummy_handler_flags = 0; 9319 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9320 != XML_STATUS_ERROR) 9321 break; 9322 /* See comment in test_alloc_parse_xdecl() */ 9323 alloc_teardown(); 9324 alloc_setup(); 9325 } 9326 if (i == 0) 9327 fail("Parse succeeded despite failing allocator"); 9328 if (i == max_alloc_count) 9329 fail("Parse failed at maximum allocation count"); 9330 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9331 fail("Element handler flag not raised"); 9332 } 9333 END_TEST 9334 9335 START_TEST(test_alloc_realloc_group_choice) { 9336 const char *text = "<!DOCTYPE doc [\n" 9337 "<!ELEMENT doc (" 9338 "a1|a2|a3|a4|a5|a6|a7|a8|" 9339 "b1|b2|b3|b4|b5|b6|b7|b8|" 9340 "c1|c2|c3|c4|c5|c6|c7|c8|" 9341 "d1|d2|d3|d4|d5|d6|d7|d8|" 9342 "e1" 9343 ")+>\n" 9344 "]>\n" 9345 "<doc>\n" 9346 "<a1/>\n" 9347 "<b2 attr='foo'>This is a foo</b2>\n" 9348 "<c3></c3>\n" 9349 "</doc>\n"; 9350 int i; 9351 const int max_realloc_count = 10; 9352 9353 for (i = 0; i < max_realloc_count; i++) { 9354 reallocation_count = i; 9355 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9356 dummy_handler_flags = 0; 9357 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9358 != XML_STATUS_ERROR) 9359 break; 9360 /* See comment in test_alloc_parse_xdecl() */ 9361 alloc_teardown(); 9362 alloc_setup(); 9363 } 9364 if (i == 0) 9365 fail("Parse succeeded despite failing reallocator"); 9366 if (i == max_realloc_count) 9367 fail("Parse failed at maximum reallocation count"); 9368 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9369 fail("Element handler flag not raised"); 9370 } 9371 END_TEST 9372 9373 START_TEST(test_alloc_pi_in_epilog) { 9374 const char *text = "<doc></doc>\n" 9375 "<?pi in epilog?>"; 9376 int i; 9377 const int max_alloc_count = 15; 9378 9379 for (i = 0; i < max_alloc_count; i++) { 9380 allocation_count = i; 9381 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 9382 dummy_handler_flags = 0; 9383 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9384 != XML_STATUS_ERROR) 9385 break; 9386 /* See comment in test_alloc_parse_xdecl() */ 9387 alloc_teardown(); 9388 alloc_setup(); 9389 } 9390 if (i == 0) 9391 fail("Parse completed despite failing allocator"); 9392 if (i == max_alloc_count) 9393 fail("Parse failed at maximum allocation count"); 9394 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG) 9395 fail("Processing instruction handler not invoked"); 9396 } 9397 END_TEST 9398 9399 START_TEST(test_alloc_comment_in_epilog) { 9400 const char *text = "<doc></doc>\n" 9401 "<!-- comment in epilog -->"; 9402 int i; 9403 const int max_alloc_count = 15; 9404 9405 for (i = 0; i < max_alloc_count; i++) { 9406 allocation_count = i; 9407 XML_SetCommentHandler(g_parser, dummy_comment_handler); 9408 dummy_handler_flags = 0; 9409 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9410 != XML_STATUS_ERROR) 9411 break; 9412 /* See comment in test_alloc_parse_xdecl() */ 9413 alloc_teardown(); 9414 alloc_setup(); 9415 } 9416 if (i == 0) 9417 fail("Parse completed despite failing allocator"); 9418 if (i == max_alloc_count) 9419 fail("Parse failed at maximum allocation count"); 9420 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG) 9421 fail("Processing instruction handler not invoked"); 9422 } 9423 END_TEST 9424 9425 START_TEST(test_alloc_realloc_long_attribute_value) { 9426 const char *text 9427 = "<!DOCTYPE doc [<!ENTITY foo '" 9428 /* Each line is 64 characters */ 9429 "This entity will be substituted as an attribute value, and is " 9430 "calculated to be exactly long enough that the terminating NUL " 9431 "that the library adds internally will trigger the string pool to" 9432 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9433 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9434 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9435 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9436 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9437 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9438 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9439 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9440 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9441 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9442 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9443 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9444 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9445 "'>]>\n" 9446 "<doc a='&foo;'></doc>"; 9447 int i; 9448 const int max_realloc_count = 10; 9449 9450 for (i = 0; i < max_realloc_count; i++) { 9451 reallocation_count = i; 9452 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9453 != XML_STATUS_ERROR) 9454 break; 9455 /* See comment in test_alloc_parse_xdecl() */ 9456 alloc_teardown(); 9457 alloc_setup(); 9458 } 9459 if (i == 0) 9460 fail("Parse succeeded despite failing reallocator"); 9461 if (i == max_realloc_count) 9462 fail("Parse failed at maximum reallocation count"); 9463 } 9464 END_TEST 9465 9466 START_TEST(test_alloc_attribute_whitespace) { 9467 const char *text = "<doc a=' '></doc>"; 9468 int i; 9469 const int max_alloc_count = 15; 9470 9471 for (i = 0; i < max_alloc_count; i++) { 9472 allocation_count = i; 9473 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9474 != XML_STATUS_ERROR) 9475 break; 9476 /* See comment in test_alloc_parse_xdecl() */ 9477 alloc_teardown(); 9478 alloc_setup(); 9479 } 9480 if (i == 0) 9481 fail("Parse succeeded despite failing allocator"); 9482 if (i == max_alloc_count) 9483 fail("Parse failed at maximum allocation count"); 9484 } 9485 END_TEST 9486 9487 START_TEST(test_alloc_attribute_predefined_entity) { 9488 const char *text = "<doc a='&'></doc>"; 9489 int i; 9490 const int max_alloc_count = 15; 9491 9492 for (i = 0; i < max_alloc_count; i++) { 9493 allocation_count = i; 9494 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9495 != XML_STATUS_ERROR) 9496 break; 9497 /* See comment in test_alloc_parse_xdecl() */ 9498 alloc_teardown(); 9499 alloc_setup(); 9500 } 9501 if (i == 0) 9502 fail("Parse succeeded despite failing allocator"); 9503 if (i == max_alloc_count) 9504 fail("Parse failed at maximum allocation count"); 9505 } 9506 END_TEST 9507 9508 /* Test that a character reference at the end of a suitably long 9509 * default value for an attribute can trigger pool growth, and recovers 9510 * if the allocator fails on it. 9511 */ 9512 START_TEST(test_alloc_long_attr_default_with_char_ref) { 9513 const char *text 9514 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '" 9515 /* 64 characters per line */ 9516 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9517 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9518 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9519 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9520 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9521 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9522 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9523 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9524 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9525 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9526 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9527 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9528 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9529 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9530 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9531 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI" 9532 "1'>]>\n" 9533 "<doc/>"; 9534 int i; 9535 const int max_alloc_count = 20; 9536 9537 for (i = 0; i < max_alloc_count; i++) { 9538 allocation_count = i; 9539 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9540 != XML_STATUS_ERROR) 9541 break; 9542 /* See comment in test_alloc_parse_xdecl() */ 9543 alloc_teardown(); 9544 alloc_setup(); 9545 } 9546 if (i == 0) 9547 fail("Parse succeeded despite failing allocator"); 9548 if (i == max_alloc_count) 9549 fail("Parse failed at maximum allocation count"); 9550 } 9551 END_TEST 9552 9553 /* Test that a long character reference substitution triggers a pool 9554 * expansion correctly for an attribute value. 9555 */ 9556 START_TEST(test_alloc_long_attr_value) { 9557 const char *text 9558 = "<!DOCTYPE test [<!ENTITY foo '\n" 9559 /* 64 characters per line */ 9560 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9561 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9562 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9563 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9564 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9565 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9566 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9567 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9568 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9569 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9570 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9571 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9572 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9573 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9574 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9575 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9576 "'>]>\n" 9577 "<test a='&foo;'/>"; 9578 int i; 9579 const int max_alloc_count = 25; 9580 9581 for (i = 0; i < max_alloc_count; i++) { 9582 allocation_count = i; 9583 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9584 != XML_STATUS_ERROR) 9585 break; 9586 /* See comment in test_alloc_parse_xdecl() */ 9587 alloc_teardown(); 9588 alloc_setup(); 9589 } 9590 if (i == 0) 9591 fail("Parse succeeded despite failing allocator"); 9592 if (i == max_alloc_count) 9593 fail("Parse failed at maximum allocation count"); 9594 } 9595 END_TEST 9596 9597 /* Test that an error in a nested parameter entity substitution is 9598 * handled correctly. It seems unlikely that the code path being 9599 * exercised can be reached purely by carefully crafted XML, but an 9600 * allocation error in the right place will definitely do it. 9601 */ 9602 START_TEST(test_alloc_nested_entities) { 9603 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 9604 "<doc />"; 9605 ExtFaults test_data 9606 = {"<!ENTITY % pe1 '" 9607 /* 64 characters per line */ 9608 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9609 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9610 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9611 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9612 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9613 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9614 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9615 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9616 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9620 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9621 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9623 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9624 "'>\n" 9625 "<!ENTITY % pe2 '%pe1;'>\n" 9626 "%pe2;", 9627 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY}; 9628 9629 /* Causes an allocation error in a nested storeEntityValue() */ 9630 allocation_count = 12; 9631 XML_SetUserData(g_parser, &test_data); 9632 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9633 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 9634 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 9635 "Entity allocation failure not noted"); 9636 } 9637 END_TEST 9638 9639 START_TEST(test_alloc_realloc_param_entity_newline) { 9640 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9641 "<doc/>"; 9642 char dtd_text[] 9643 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9644 /* 64 characters per line */ 9645 "This default value is carefully crafted so that the carriage " 9646 "return right at the end of the entity string causes an internal " 9647 "string pool to have to grow. This allows us to test the alloc " 9648 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9649 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9650 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9651 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9652 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9653 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9654 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9655 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9656 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9657 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9658 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9659 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9660 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE" 9661 "\">\n'>" 9662 "%pe;\n"; 9663 int i; 9664 const int max_realloc_count = 5; 9665 9666 for (i = 0; i < max_realloc_count; i++) { 9667 reallocation_count = i; 9668 XML_SetUserData(g_parser, dtd_text); 9669 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9670 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9671 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9672 != XML_STATUS_ERROR) 9673 break; 9674 /* See comment in test_alloc_parse_xdecl() */ 9675 alloc_teardown(); 9676 alloc_setup(); 9677 } 9678 if (i == 0) 9679 fail("Parse succeeded despite failing reallocator"); 9680 if (i == max_realloc_count) 9681 fail("Parse failed at maximum reallocation count"); 9682 } 9683 END_TEST 9684 9685 START_TEST(test_alloc_realloc_ce_extends_pe) { 9686 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9687 "<doc/>"; 9688 char dtd_text[] 9689 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9690 /* 64 characters per line */ 9691 "This default value is carefully crafted so that the character " 9692 "entity at the end causes an internal string pool to have to " 9693 "grow. This allows us to test the allocation failure path from " 9694 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9695 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9696 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9697 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9698 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9699 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9700 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9701 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9702 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9703 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9704 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9705 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9706 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ" 9707 "\">\n'>" 9708 "%pe;\n"; 9709 int i; 9710 const int max_realloc_count = 5; 9711 9712 for (i = 0; i < max_realloc_count; i++) { 9713 reallocation_count = i; 9714 XML_SetUserData(g_parser, dtd_text); 9715 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9716 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9717 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9718 != XML_STATUS_ERROR) 9719 break; 9720 /* See comment in test_alloc_parse_xdecl() */ 9721 alloc_teardown(); 9722 alloc_setup(); 9723 } 9724 if (i == 0) 9725 fail("Parse succeeded despite failing reallocator"); 9726 if (i == max_realloc_count) 9727 fail("Parse failed at maximum reallocation count"); 9728 } 9729 END_TEST 9730 9731 START_TEST(test_alloc_realloc_attributes) { 9732 const char *text = "<!DOCTYPE doc [\n" 9733 " <!ATTLIST doc\n" 9734 " a1 (a|b|c) 'a'\n" 9735 " a2 (foo|bar) #IMPLIED\n" 9736 " a3 NMTOKEN #IMPLIED\n" 9737 " a4 NMTOKENS #IMPLIED\n" 9738 " a5 ID #IMPLIED\n" 9739 " a6 IDREF #IMPLIED\n" 9740 " a7 IDREFS #IMPLIED\n" 9741 " a8 ENTITY #IMPLIED\n" 9742 " a9 ENTITIES #IMPLIED\n" 9743 " a10 CDATA #IMPLIED\n" 9744 " >]>\n" 9745 "<doc>wombat</doc>\n"; 9746 int i; 9747 const int max_realloc_count = 5; 9748 9749 for (i = 0; i < max_realloc_count; i++) { 9750 reallocation_count = i; 9751 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9752 != XML_STATUS_ERROR) 9753 break; 9754 /* See comment in test_alloc_parse_xdecl() */ 9755 alloc_teardown(); 9756 alloc_setup(); 9757 } 9758 9759 if (i == 0) 9760 fail("Parse succeeded despite failing reallocator"); 9761 if (i == max_realloc_count) 9762 fail("Parse failed at maximum reallocation count"); 9763 } 9764 END_TEST 9765 9766 START_TEST(test_alloc_long_doc_name) { 9767 const char *text = 9768 /* 64 characters per line */ 9769 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr" 9770 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9771 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9772 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9773 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9774 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9777 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9778 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9782 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9783 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9784 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9785 " a='1'/>"; 9786 int i; 9787 const int max_alloc_count = 20; 9788 9789 for (i = 0; i < max_alloc_count; i++) { 9790 allocation_count = i; 9791 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9792 != XML_STATUS_ERROR) 9793 break; 9794 /* See comment in test_alloc_parse_xdecl() */ 9795 alloc_teardown(); 9796 alloc_setup(); 9797 } 9798 if (i == 0) 9799 fail("Parsing worked despite failing reallocations"); 9800 else if (i == max_alloc_count) 9801 fail("Parsing failed even at max reallocation count"); 9802 } 9803 END_TEST 9804 9805 START_TEST(test_alloc_long_base) { 9806 const char *text = "<!DOCTYPE doc [\n" 9807 " <!ENTITY e SYSTEM 'foo'>\n" 9808 "]>\n" 9809 "<doc>&e;</doc>"; 9810 char entity_text[] = "Hello world"; 9811 const XML_Char *base = 9812 /* 64 characters per line */ 9813 /* clang-format off */ 9814 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t") 9815 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9816 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9817 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9818 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9819 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9820 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9821 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9822 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9823 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9824 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9825 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9826 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9827 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9828 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9829 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"); 9830 /* clang-format on */ 9831 int i; 9832 const int max_alloc_count = 25; 9833 9834 for (i = 0; i < max_alloc_count; i++) { 9835 allocation_count = i; 9836 XML_SetUserData(g_parser, entity_text); 9837 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9838 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9839 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) { 9840 XML_ParserReset(g_parser, NULL); 9841 continue; 9842 } 9843 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9844 != XML_STATUS_ERROR) 9845 break; 9846 /* See comment in test_alloc_parse_xdecl() */ 9847 alloc_teardown(); 9848 alloc_setup(); 9849 } 9850 if (i == 0) 9851 fail("Parsing worked despite failing allocations"); 9852 else if (i == max_alloc_count) 9853 fail("Parsing failed even at max allocation count"); 9854 } 9855 END_TEST 9856 9857 START_TEST(test_alloc_long_public_id) { 9858 const char *text 9859 = "<!DOCTYPE doc [\n" 9860 " <!ENTITY e PUBLIC '" 9861 /* 64 characters per line */ 9862 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec" 9863 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9864 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9865 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9866 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9867 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9868 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9869 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9870 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9871 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9872 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9873 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9874 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9875 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9876 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9877 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9878 "' 'bar'>\n" 9879 "]>\n" 9880 "<doc>&e;</doc>"; 9881 char entity_text[] = "Hello world"; 9882 int i; 9883 const int max_alloc_count = 40; 9884 9885 for (i = 0; i < max_alloc_count; i++) { 9886 allocation_count = i; 9887 XML_SetUserData(g_parser, entity_text); 9888 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9889 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9890 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9891 != XML_STATUS_ERROR) 9892 break; 9893 /* See comment in test_alloc_parse_xdecl() */ 9894 alloc_teardown(); 9895 alloc_setup(); 9896 } 9897 if (i == 0) 9898 fail("Parsing worked despite failing allocations"); 9899 else if (i == max_alloc_count) 9900 fail("Parsing failed even at max allocation count"); 9901 } 9902 END_TEST 9903 9904 START_TEST(test_alloc_long_entity_value) { 9905 const char *text 9906 = "<!DOCTYPE doc [\n" 9907 " <!ENTITY e1 '" 9908 /* 64 characters per line */ 9909 "Long entity value that should provoke a string pool to grow whil" 9910 "e setting up to parse the external entity below. xyz0123456789AB" 9911 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9913 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9923 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9924 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9925 "'>\n" 9926 " <!ENTITY e2 SYSTEM 'bar'>\n" 9927 "]>\n" 9928 "<doc>&e2;</doc>"; 9929 char entity_text[] = "Hello world"; 9930 int i; 9931 const int max_alloc_count = 40; 9932 9933 for (i = 0; i < max_alloc_count; i++) { 9934 allocation_count = i; 9935 XML_SetUserData(g_parser, entity_text); 9936 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9937 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9938 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9939 != XML_STATUS_ERROR) 9940 break; 9941 /* See comment in test_alloc_parse_xdecl() */ 9942 alloc_teardown(); 9943 alloc_setup(); 9944 } 9945 if (i == 0) 9946 fail("Parsing worked despite failing allocations"); 9947 else if (i == max_alloc_count) 9948 fail("Parsing failed even at max allocation count"); 9949 } 9950 END_TEST 9951 9952 START_TEST(test_alloc_long_notation) { 9953 const char *text 9954 = "<!DOCTYPE doc [\n" 9955 " <!NOTATION note SYSTEM '" 9956 /* 64 characters per line */ 9957 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 9958 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9959 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9960 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9961 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9962 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9963 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9964 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9965 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9966 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9967 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9968 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9969 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9970 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9971 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9972 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9973 "'>\n" 9974 " <!ENTITY e1 SYSTEM 'foo' NDATA " 9975 /* 64 characters per line */ 9976 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 9977 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9978 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9979 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9980 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9981 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9982 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9983 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9984 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9985 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9986 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9987 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9988 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9989 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9990 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9991 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9992 ">\n" 9993 " <!ENTITY e2 SYSTEM 'bar'>\n" 9994 "]>\n" 9995 "<doc>&e2;</doc>"; 9996 ExtOption options[] 9997 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}}; 9998 int i; 9999 const int max_alloc_count = 40; 10000 10001 for (i = 0; i < max_alloc_count; i++) { 10002 allocation_count = i; 10003 XML_SetUserData(g_parser, options); 10004 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10005 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10006 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10007 != XML_STATUS_ERROR) 10008 break; 10009 10010 /* See comment in test_alloc_parse_xdecl() */ 10011 alloc_teardown(); 10012 alloc_setup(); 10013 } 10014 if (i == 0) 10015 fail("Parsing worked despite failing allocations"); 10016 else if (i == max_alloc_count) 10017 fail("Parsing failed even at max allocation count"); 10018 } 10019 END_TEST 10020 10021 static void 10022 nsalloc_setup(void) { 10023 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 10024 XML_Char ns_sep[2] = {' ', '\0'}; 10025 10026 /* Ensure the parser creation will go through */ 10027 allocation_count = ALLOC_ALWAYS_SUCCEED; 10028 reallocation_count = REALLOC_ALWAYS_SUCCEED; 10029 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep); 10030 if (g_parser == NULL) 10031 fail("Parser not created"); 10032 } 10033 10034 static void 10035 nsalloc_teardown(void) { 10036 basic_teardown(); 10037 } 10038 10039 /* Test the effects of allocation failure in simple namespace parsing. 10040 * Based on test_ns_default_with_empty_uri() 10041 */ 10042 START_TEST(test_nsalloc_xmlns) { 10043 const char *text = "<doc xmlns='http://example.org/'>\n" 10044 " <e xmlns=''/>\n" 10045 "</doc>"; 10046 unsigned int i; 10047 const unsigned int max_alloc_count = 30; 10048 10049 for (i = 0; i < max_alloc_count; i++) { 10050 allocation_count = i; 10051 /* Exercise more code paths with a default handler */ 10052 XML_SetDefaultHandler(g_parser, dummy_default_handler); 10053 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10054 != XML_STATUS_ERROR) 10055 break; 10056 /* Resetting the parser is insufficient, because some memory 10057 * allocations are cached within the parser. Instead we use 10058 * the teardown and setup routines to ensure that we have the 10059 * right sort of parser back in our hands. 10060 */ 10061 nsalloc_teardown(); 10062 nsalloc_setup(); 10063 } 10064 if (i == 0) 10065 fail("Parsing worked despite failing allocations"); 10066 else if (i == max_alloc_count) 10067 fail("Parsing failed even at maximum allocation count"); 10068 } 10069 END_TEST 10070 10071 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */ 10072 START_TEST(test_nsalloc_parse_buffer) { 10073 const char *text = "<doc>Hello</doc>"; 10074 void *buffer; 10075 10076 /* Try a parse before the start of the world */ 10077 /* (Exercises new code path) */ 10078 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10079 fail("Pre-init XML_ParseBuffer not faulted"); 10080 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER) 10081 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10082 10083 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */); 10084 if (buffer == NULL) 10085 fail("Could not acquire parse buffer"); 10086 10087 allocation_count = 0; 10088 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10089 fail("Pre-init XML_ParseBuffer not faulted"); 10090 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY) 10091 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10092 10093 /* Now with actual memory allocation */ 10094 allocation_count = ALLOC_ALWAYS_SUCCEED; 10095 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK) 10096 xml_failure(g_parser); 10097 10098 /* Check that resuming an unsuspended parser is faulted */ 10099 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 10100 fail("Resuming unsuspended parser not faulted"); 10101 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED) 10102 xml_failure(g_parser); 10103 10104 /* Get the parser into suspended state */ 10105 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 10106 resumable = XML_TRUE; 10107 buffer = XML_GetBuffer(g_parser, (int)strlen(text)); 10108 if (buffer == NULL) 10109 fail("Could not acquire parse buffer"); 10110 assert(buffer != NULL); 10111 memcpy(buffer, text, strlen(text)); 10112 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10113 != XML_STATUS_SUSPENDED) 10114 xml_failure(g_parser); 10115 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 10116 xml_failure(g_parser); 10117 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10118 != XML_STATUS_ERROR) 10119 fail("Suspended XML_ParseBuffer not faulted"); 10120 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 10121 xml_failure(g_parser); 10122 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10123 fail("Suspended XML_GetBuffer not faulted"); 10124 10125 /* Get it going again and complete the world */ 10126 XML_SetCharacterDataHandler(g_parser, NULL); 10127 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 10128 xml_failure(g_parser); 10129 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10130 != XML_STATUS_ERROR) 10131 fail("Post-finishing XML_ParseBuffer not faulted"); 10132 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED) 10133 xml_failure(g_parser); 10134 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10135 fail("Post-finishing XML_GetBuffer not faulted"); 10136 } 10137 END_TEST 10138 10139 /* Check handling of long prefix names (pool growth) */ 10140 START_TEST(test_nsalloc_long_prefix) { 10141 const char *text 10142 = "<" 10143 /* 64 characters per line */ 10144 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10145 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10146 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10147 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10148 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10149 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10150 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10151 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10152 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10153 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10154 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10155 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10156 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10157 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10158 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10159 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10160 ":foo xmlns:" 10161 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10162 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10163 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10164 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10165 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10166 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10167 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10168 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10169 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10170 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10171 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10172 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10173 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10174 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10175 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10176 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10177 "='http://example.org/'>" 10178 "</" 10179 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10180 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10181 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10182 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10183 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10184 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10185 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10186 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10187 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10188 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10189 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10190 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10192 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10193 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10194 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10195 ":foo>"; 10196 int i; 10197 const int max_alloc_count = 40; 10198 10199 for (i = 0; i < max_alloc_count; i++) { 10200 allocation_count = i; 10201 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10202 != XML_STATUS_ERROR) 10203 break; 10204 /* See comment in test_nsalloc_xmlns() */ 10205 nsalloc_teardown(); 10206 nsalloc_setup(); 10207 } 10208 if (i == 0) 10209 fail("Parsing worked despite failing allocations"); 10210 else if (i == max_alloc_count) 10211 fail("Parsing failed even at max allocation count"); 10212 } 10213 END_TEST 10214 10215 /* Check handling of long uri names (pool growth) */ 10216 START_TEST(test_nsalloc_long_uri) { 10217 const char *text 10218 = "<foo:e xmlns:foo='http://example.org/" 10219 /* 64 characters per line */ 10220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10233 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10234 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10235 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10236 "' bar:a='12'\n" 10237 "xmlns:bar='http://example.org/" 10238 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10239 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10240 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10241 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10242 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10243 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10244 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10245 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10246 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10247 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10248 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10249 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10250 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10251 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10252 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10253 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10254 "'>" 10255 "</foo:e>"; 10256 int i; 10257 const int max_alloc_count = 40; 10258 10259 for (i = 0; i < max_alloc_count; i++) { 10260 allocation_count = i; 10261 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10262 != XML_STATUS_ERROR) 10263 break; 10264 /* See comment in test_nsalloc_xmlns() */ 10265 nsalloc_teardown(); 10266 nsalloc_setup(); 10267 } 10268 if (i == 0) 10269 fail("Parsing worked despite failing allocations"); 10270 else if (i == max_alloc_count) 10271 fail("Parsing failed even at max allocation count"); 10272 } 10273 END_TEST 10274 10275 /* Test handling of long attribute names with prefixes */ 10276 START_TEST(test_nsalloc_long_attr) { 10277 const char *text 10278 = "<foo:e xmlns:foo='http://example.org/' bar:" 10279 /* 64 characters per line */ 10280 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10281 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10282 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10283 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10285 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10286 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10287 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10288 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10289 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10290 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10291 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10292 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10293 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10294 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10295 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10296 "='12'\n" 10297 "xmlns:bar='http://example.org/'>" 10298 "</foo:e>"; 10299 int i; 10300 const int max_alloc_count = 40; 10301 10302 for (i = 0; i < max_alloc_count; i++) { 10303 allocation_count = i; 10304 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10305 != XML_STATUS_ERROR) 10306 break; 10307 /* See comment in test_nsalloc_xmlns() */ 10308 nsalloc_teardown(); 10309 nsalloc_setup(); 10310 } 10311 if (i == 0) 10312 fail("Parsing worked despite failing allocations"); 10313 else if (i == max_alloc_count) 10314 fail("Parsing failed even at max allocation count"); 10315 } 10316 END_TEST 10317 10318 /* Test handling of an attribute name with a long namespace prefix */ 10319 START_TEST(test_nsalloc_long_attr_prefix) { 10320 const char *text 10321 = "<foo:e xmlns:foo='http://example.org/' " 10322 /* 64 characters per line */ 10323 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10324 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10325 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10326 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10327 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10328 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10329 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10330 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10331 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10332 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10333 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10334 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10335 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10336 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10338 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10339 ":a='12'\n" 10340 "xmlns:" 10341 /* 64 characters per line */ 10342 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10343 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10344 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10345 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10346 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10347 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10348 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10349 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10350 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10351 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10352 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10354 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10355 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10356 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10357 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10358 "='http://example.org/'>" 10359 "</foo:e>"; 10360 const XML_Char *elemstr[] = { 10361 /* clang-format off */ 10362 XCS("http://example.org/ e foo"), 10363 XCS("http://example.org/ a ") 10364 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10365 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10366 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10367 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10368 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10369 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10370 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10371 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10372 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10373 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10374 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10375 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10376 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10377 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10378 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10379 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10380 /* clang-format on */ 10381 }; 10382 int i; 10383 const int max_alloc_count = 40; 10384 10385 for (i = 0; i < max_alloc_count; i++) { 10386 allocation_count = i; 10387 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10388 XML_SetUserData(g_parser, (void *)elemstr); 10389 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10390 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10391 != XML_STATUS_ERROR) 10392 break; 10393 /* See comment in test_nsalloc_xmlns() */ 10394 nsalloc_teardown(); 10395 nsalloc_setup(); 10396 } 10397 if (i == 0) 10398 fail("Parsing worked despite failing allocations"); 10399 else if (i == max_alloc_count) 10400 fail("Parsing failed even at max allocation count"); 10401 } 10402 END_TEST 10403 10404 /* Test attribute handling in the face of a dodgy reallocator */ 10405 START_TEST(test_nsalloc_realloc_attributes) { 10406 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 10407 " xmlns:bar='http://example.org/'>" 10408 "</foo:e>"; 10409 int i; 10410 const int max_realloc_count = 10; 10411 10412 for (i = 0; i < max_realloc_count; i++) { 10413 reallocation_count = i; 10414 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10415 != XML_STATUS_ERROR) 10416 break; 10417 /* See comment in test_nsalloc_xmlns() */ 10418 nsalloc_teardown(); 10419 nsalloc_setup(); 10420 } 10421 if (i == 0) 10422 fail("Parsing worked despite failing reallocations"); 10423 else if (i == max_realloc_count) 10424 fail("Parsing failed at max reallocation count"); 10425 } 10426 END_TEST 10427 10428 /* Test long element names with namespaces under a failing allocator */ 10429 START_TEST(test_nsalloc_long_element) { 10430 const char *text 10431 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 10432 " xmlns:foo='http://example.org/' bar:a='12'\n" 10433 " xmlns:bar='http://example.org/'>" 10434 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 10435 const XML_Char *elemstr[] 10436 = {XCS("http://example.org/") 10437 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 10438 XCS("http://example.org/ a bar")}; 10439 int i; 10440 const int max_alloc_count = 30; 10441 10442 for (i = 0; i < max_alloc_count; i++) { 10443 allocation_count = i; 10444 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10445 XML_SetUserData(g_parser, (void *)elemstr); 10446 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10447 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10448 != XML_STATUS_ERROR) 10449 break; 10450 /* See comment in test_nsalloc_xmlns() */ 10451 nsalloc_teardown(); 10452 nsalloc_setup(); 10453 } 10454 if (i == 0) 10455 fail("Parsing worked despite failing reallocations"); 10456 else if (i == max_alloc_count) 10457 fail("Parsing failed at max reallocation count"); 10458 } 10459 END_TEST 10460 10461 /* Test the effects of reallocation failure when reassigning a 10462 * binding. 10463 * 10464 * XML_ParserReset does not free the BINDING structures used by a 10465 * parser, but instead adds them to an internal free list to be reused 10466 * as necessary. Likewise the URI buffers allocated for the binding 10467 * aren't freed, but kept attached to their existing binding. If the 10468 * new binding has a longer URI, it will need reallocation. This test 10469 * provokes that reallocation, and tests the control path if it fails. 10470 */ 10471 START_TEST(test_nsalloc_realloc_binding_uri) { 10472 const char *first = "<doc xmlns='http://example.org/'>\n" 10473 " <e xmlns='' />\n" 10474 "</doc>"; 10475 const char *second 10476 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n" 10477 " <e xmlns='' />\n" 10478 "</doc>"; 10479 unsigned i; 10480 const unsigned max_realloc_count = 10; 10481 10482 /* First, do a full parse that will leave bindings around */ 10483 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE) 10484 == XML_STATUS_ERROR) 10485 xml_failure(g_parser); 10486 10487 /* Now repeat with a longer URI and a duff reallocator */ 10488 for (i = 0; i < max_realloc_count; i++) { 10489 XML_ParserReset(g_parser, NULL); 10490 reallocation_count = i; 10491 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE) 10492 != XML_STATUS_ERROR) 10493 break; 10494 } 10495 if (i == 0) 10496 fail("Parsing worked despite failing reallocation"); 10497 else if (i == max_realloc_count) 10498 fail("Parsing failed at max reallocation count"); 10499 } 10500 END_TEST 10501 10502 /* Check handling of long prefix names (pool growth) */ 10503 START_TEST(test_nsalloc_realloc_long_prefix) { 10504 const char *text 10505 = "<" 10506 /* 64 characters per line */ 10507 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10508 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10509 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10510 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10511 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10512 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10513 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10514 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10515 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10516 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10517 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10518 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10519 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10520 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10521 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10522 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10523 ":foo xmlns:" 10524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10525 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10526 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10527 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10528 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10529 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10530 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10531 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10533 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10540 "='http://example.org/'>" 10541 "</" 10542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10544 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10545 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10546 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10548 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10549 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10550 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10551 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10552 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10553 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10554 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10555 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10556 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10557 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10558 ":foo>"; 10559 int i; 10560 const int max_realloc_count = 12; 10561 10562 for (i = 0; i < max_realloc_count; i++) { 10563 reallocation_count = i; 10564 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10565 != XML_STATUS_ERROR) 10566 break; 10567 /* See comment in test_nsalloc_xmlns() */ 10568 nsalloc_teardown(); 10569 nsalloc_setup(); 10570 } 10571 if (i == 0) 10572 fail("Parsing worked despite failing reallocations"); 10573 else if (i == max_realloc_count) 10574 fail("Parsing failed even at max reallocation count"); 10575 } 10576 END_TEST 10577 10578 /* Check handling of even long prefix names (different code path) */ 10579 START_TEST(test_nsalloc_realloc_longer_prefix) { 10580 const char *text 10581 = "<" 10582 /* 64 characters per line */ 10583 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10584 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10585 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10586 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10587 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10588 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10589 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10590 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10591 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10592 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10593 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10594 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10595 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10596 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10597 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10598 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10599 "Q:foo xmlns:" 10600 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10601 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10602 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10603 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10604 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10605 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10606 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10607 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10608 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10609 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10610 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10611 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10612 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10613 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10614 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10615 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10616 "Q='http://example.org/'>" 10617 "</" 10618 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10619 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10620 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10621 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10622 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10623 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10624 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10625 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10626 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10627 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10628 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10629 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10630 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10631 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10632 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10633 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10634 "Q:foo>"; 10635 int i; 10636 const int max_realloc_count = 12; 10637 10638 for (i = 0; i < max_realloc_count; i++) { 10639 reallocation_count = i; 10640 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10641 != XML_STATUS_ERROR) 10642 break; 10643 /* See comment in test_nsalloc_xmlns() */ 10644 nsalloc_teardown(); 10645 nsalloc_setup(); 10646 } 10647 if (i == 0) 10648 fail("Parsing worked despite failing reallocations"); 10649 else if (i == max_realloc_count) 10650 fail("Parsing failed even at max reallocation count"); 10651 } 10652 END_TEST 10653 10654 START_TEST(test_nsalloc_long_namespace) { 10655 const char *text1 10656 = "<" 10657 /* 64 characters per line */ 10658 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10659 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10660 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10661 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10662 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10663 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10664 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10665 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10666 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10667 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10668 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10669 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10670 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10671 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10672 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10673 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10674 ":e xmlns:" 10675 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10676 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10677 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10678 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10679 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10680 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10681 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10682 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10683 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10684 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10685 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10686 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10687 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10688 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10689 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10690 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10691 "='http://example.org/'>\n"; 10692 const char *text2 10693 = "<" 10694 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10695 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10696 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10697 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10698 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10699 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10700 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10701 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10702 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10703 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10704 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10705 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10706 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10707 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10708 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10709 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10710 ":f " 10711 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10712 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10713 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10714 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10715 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10716 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10717 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10718 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10719 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10720 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10721 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10723 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10724 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10725 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10726 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10727 ":attr='foo'/>\n" 10728 "</" 10729 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10730 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10731 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10732 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10733 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10734 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10735 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10736 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10737 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10738 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10739 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10740 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10741 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10742 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10743 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10744 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10745 ":e>"; 10746 int i; 10747 const int max_alloc_count = 40; 10748 10749 for (i = 0; i < max_alloc_count; i++) { 10750 allocation_count = i; 10751 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 10752 != XML_STATUS_ERROR 10753 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 10754 XML_TRUE) 10755 != XML_STATUS_ERROR) 10756 break; 10757 /* See comment in test_nsalloc_xmlns() */ 10758 nsalloc_teardown(); 10759 nsalloc_setup(); 10760 } 10761 if (i == 0) 10762 fail("Parsing worked despite failing allocations"); 10763 else if (i == max_alloc_count) 10764 fail("Parsing failed even at max allocation count"); 10765 } 10766 END_TEST 10767 10768 /* Using a slightly shorter namespace name provokes allocations in 10769 * slightly different places in the code. 10770 */ 10771 START_TEST(test_nsalloc_less_long_namespace) { 10772 const char *text 10773 = "<" 10774 /* 64 characters per line */ 10775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10777 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10778 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10782 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10783 ":e xmlns:" 10784 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10785 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10786 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10787 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10788 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10789 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10790 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10791 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10792 "='http://example.org/'>\n" 10793 "<" 10794 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10795 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10796 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10797 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10798 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10799 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10800 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10801 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10802 ":f " 10803 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10804 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10805 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10806 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10807 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10808 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10809 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10810 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10811 ":att='foo'/>\n" 10812 "</" 10813 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10814 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10815 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10816 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10817 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10818 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10819 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10820 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10821 ":e>"; 10822 int i; 10823 const int max_alloc_count = 40; 10824 10825 for (i = 0; i < max_alloc_count; i++) { 10826 allocation_count = i; 10827 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10828 != XML_STATUS_ERROR) 10829 break; 10830 /* See comment in test_nsalloc_xmlns() */ 10831 nsalloc_teardown(); 10832 nsalloc_setup(); 10833 } 10834 if (i == 0) 10835 fail("Parsing worked despite failing allocations"); 10836 else if (i == max_alloc_count) 10837 fail("Parsing failed even at max allocation count"); 10838 } 10839 END_TEST 10840 10841 START_TEST(test_nsalloc_long_context) { 10842 const char *text 10843 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10844 " <!ATTLIST doc baz ID #REQUIRED>\n" 10845 " <!ENTITY en SYSTEM 'bar'>\n" 10846 "]>\n" 10847 "<doc xmlns='http://example.org/" 10848 /* 64 characters per line */ 10849 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10850 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10851 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10852 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10853 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10854 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10855 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10856 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10857 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10858 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10859 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10860 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10861 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10862 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10863 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10864 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 10865 "' baz='2'>\n" 10866 "&en;" 10867 "</doc>"; 10868 ExtOption options[] = { 10869 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10870 int i; 10871 const int max_alloc_count = 70; 10872 10873 for (i = 0; i < max_alloc_count; i++) { 10874 allocation_count = i; 10875 XML_SetUserData(g_parser, options); 10876 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10877 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10878 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10879 != XML_STATUS_ERROR) 10880 break; 10881 10882 /* See comment in test_nsalloc_xmlns() */ 10883 nsalloc_teardown(); 10884 nsalloc_setup(); 10885 } 10886 if (i == 0) 10887 fail("Parsing worked despite failing allocations"); 10888 else if (i == max_alloc_count) 10889 fail("Parsing failed even at max allocation count"); 10890 } 10891 END_TEST 10892 10893 /* This function is void; it will throw a fail() on error, so if it 10894 * returns normally it must have succeeded. 10895 */ 10896 static void 10897 context_realloc_test(const char *text) { 10898 ExtOption options[] = { 10899 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10900 int i; 10901 const int max_realloc_count = 6; 10902 10903 for (i = 0; i < max_realloc_count; i++) { 10904 reallocation_count = i; 10905 XML_SetUserData(g_parser, options); 10906 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10907 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10908 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10909 != XML_STATUS_ERROR) 10910 break; 10911 /* See comment in test_nsalloc_xmlns() */ 10912 nsalloc_teardown(); 10913 nsalloc_setup(); 10914 } 10915 if (i == 0) 10916 fail("Parsing worked despite failing reallocations"); 10917 else if (i == max_realloc_count) 10918 fail("Parsing failed even at max reallocation count"); 10919 } 10920 10921 START_TEST(test_nsalloc_realloc_long_context) { 10922 const char *text 10923 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10924 " <!ENTITY en SYSTEM 'bar'>\n" 10925 "]>\n" 10926 "<doc xmlns='http://example.org/" 10927 /* 64 characters per line */ 10928 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10929 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10930 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10931 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10932 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10933 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10934 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10935 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10936 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10937 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10938 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10939 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10940 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10941 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10942 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10943 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 10944 "'>\n" 10945 "&en;" 10946 "</doc>"; 10947 10948 context_realloc_test(text); 10949 } 10950 END_TEST 10951 10952 START_TEST(test_nsalloc_realloc_long_context_2) { 10953 const char *text 10954 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10955 " <!ENTITY en SYSTEM 'bar'>\n" 10956 "]>\n" 10957 "<doc xmlns='http://example.org/" 10958 /* 64 characters per line */ 10959 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10960 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10961 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10962 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10963 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10964 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10965 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10966 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10967 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10968 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10969 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10970 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10971 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10972 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10973 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10974 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK" 10975 "'>\n" 10976 "&en;" 10977 "</doc>"; 10978 10979 context_realloc_test(text); 10980 } 10981 END_TEST 10982 10983 START_TEST(test_nsalloc_realloc_long_context_3) { 10984 const char *text 10985 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10986 " <!ENTITY en SYSTEM 'bar'>\n" 10987 "]>\n" 10988 "<doc xmlns='http://example.org/" 10989 /* 64 characters per line */ 10990 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10991 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10992 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10993 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10994 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10995 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10996 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10997 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10998 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10999 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11000 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11001 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11002 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11003 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11004 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11005 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH" 11006 "'>\n" 11007 "&en;" 11008 "</doc>"; 11009 11010 context_realloc_test(text); 11011 } 11012 END_TEST 11013 11014 START_TEST(test_nsalloc_realloc_long_context_4) { 11015 const char *text 11016 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11017 " <!ENTITY en SYSTEM 'bar'>\n" 11018 "]>\n" 11019 "<doc xmlns='http://example.org/" 11020 /* 64 characters per line */ 11021 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11022 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11023 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11024 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11025 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11026 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11027 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11028 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11029 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11030 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11031 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11032 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11033 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11034 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11035 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11036 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO" 11037 "'>\n" 11038 "&en;" 11039 "</doc>"; 11040 11041 context_realloc_test(text); 11042 } 11043 END_TEST 11044 11045 START_TEST(test_nsalloc_realloc_long_context_5) { 11046 const char *text 11047 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11048 " <!ENTITY en SYSTEM 'bar'>\n" 11049 "]>\n" 11050 "<doc xmlns='http://example.org/" 11051 /* 64 characters per line */ 11052 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11053 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11054 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11055 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11056 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11057 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11058 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11059 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11060 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11061 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11062 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11063 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11064 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11065 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11066 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11067 "ABC" 11068 "'>\n" 11069 "&en;" 11070 "</doc>"; 11071 11072 context_realloc_test(text); 11073 } 11074 END_TEST 11075 11076 START_TEST(test_nsalloc_realloc_long_context_6) { 11077 const char *text 11078 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11079 " <!ENTITY en SYSTEM 'bar'>\n" 11080 "]>\n" 11081 "<doc xmlns='http://example.org/" 11082 /* 64 characters per line */ 11083 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11084 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11085 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11086 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11087 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11088 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11089 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11090 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11091 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11092 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11093 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11094 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11095 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11096 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11097 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 11098 "'>\n" 11099 "&en;" 11100 "</doc>"; 11101 11102 context_realloc_test(text); 11103 } 11104 END_TEST 11105 11106 START_TEST(test_nsalloc_realloc_long_context_7) { 11107 const char *text 11108 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11109 " <!ENTITY en SYSTEM 'bar'>\n" 11110 "]>\n" 11111 "<doc xmlns='http://example.org/" 11112 /* 64 characters per line */ 11113 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11114 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11115 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11116 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11117 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11118 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11119 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11120 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11121 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11122 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11123 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11124 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11125 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11126 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11128 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM" 11129 "'>\n" 11130 "&en;" 11131 "</doc>"; 11132 11133 context_realloc_test(text); 11134 } 11135 END_TEST 11136 11137 START_TEST(test_nsalloc_realloc_long_ge_name) { 11138 const char *text 11139 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11140 " <!ENTITY " 11141 /* 64 characters per line */ 11142 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11143 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11144 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11145 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11146 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11147 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11148 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11149 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11150 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11151 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11152 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11153 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11154 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11155 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11156 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11157 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11158 " SYSTEM 'bar'>\n" 11159 "]>\n" 11160 "<doc xmlns='http://example.org/baz'>\n" 11161 "&" 11162 /* 64 characters per line */ 11163 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11164 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11165 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11166 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11167 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11168 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11169 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11170 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11171 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11172 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11173 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11174 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11175 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11176 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11177 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11178 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11179 ";" 11180 "</doc>"; 11181 ExtOption options[] = { 11182 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}}; 11183 int i; 11184 const int max_realloc_count = 10; 11185 11186 for (i = 0; i < max_realloc_count; i++) { 11187 reallocation_count = i; 11188 XML_SetUserData(g_parser, options); 11189 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11190 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11191 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11192 != XML_STATUS_ERROR) 11193 break; 11194 /* See comment in test_nsalloc_xmlns() */ 11195 nsalloc_teardown(); 11196 nsalloc_setup(); 11197 } 11198 if (i == 0) 11199 fail("Parsing worked despite failing reallocations"); 11200 else if (i == max_realloc_count) 11201 fail("Parsing failed even at max reallocation count"); 11202 } 11203 END_TEST 11204 11205 /* Test that when a namespace is passed through the context mechanism 11206 * to an external entity parser, the parsers handle reallocation 11207 * failures correctly. The prefix is exactly the right length to 11208 * provoke particular uncommon code paths. 11209 */ 11210 START_TEST(test_nsalloc_realloc_long_context_in_dtd) { 11211 const char *text1 11212 = "<!DOCTYPE " 11213 /* 64 characters per line */ 11214 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11215 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11216 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11217 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11218 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11219 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11220 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11221 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11222 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11223 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11224 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11225 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11226 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11227 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11228 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11229 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11230 ":doc [\n" 11231 " <!ENTITY First SYSTEM 'foo/First'>\n" 11232 "]>\n" 11233 "<" 11234 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11235 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11236 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11237 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11238 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11239 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11240 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11241 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11242 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11243 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11244 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11245 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11246 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11247 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11248 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11249 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11250 ":doc xmlns:" 11251 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11252 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11253 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11254 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11255 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11256 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11257 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11258 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11259 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11260 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11261 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11262 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11263 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11264 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11265 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11266 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11267 "='foo/Second'>&First;"; 11268 const char *text2 11269 = "</" 11270 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11271 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11272 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11273 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11274 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11275 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11276 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11277 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11278 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11279 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11280 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11281 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11282 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11283 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11284 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11285 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11286 ":doc>"; 11287 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}}; 11288 int i; 11289 const int max_realloc_count = 20; 11290 11291 for (i = 0; i < max_realloc_count; i++) { 11292 reallocation_count = i; 11293 XML_SetUserData(g_parser, options); 11294 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11295 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11296 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 11297 != XML_STATUS_ERROR 11298 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 11299 XML_TRUE) 11300 != XML_STATUS_ERROR) 11301 break; 11302 /* See comment in test_nsalloc_xmlns() */ 11303 nsalloc_teardown(); 11304 nsalloc_setup(); 11305 } 11306 if (i == 0) 11307 fail("Parsing worked despite failing reallocations"); 11308 else if (i == max_realloc_count) 11309 fail("Parsing failed even at max reallocation count"); 11310 } 11311 END_TEST 11312 11313 START_TEST(test_nsalloc_long_default_in_ext) { 11314 const char *text 11315 = "<!DOCTYPE doc [\n" 11316 " <!ATTLIST e a1 CDATA '" 11317 /* 64 characters per line */ 11318 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11319 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11320 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11321 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11322 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11323 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11324 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11325 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11326 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11327 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11328 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11329 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11330 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11331 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11332 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11333 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11334 "'>\n" 11335 " <!ENTITY x SYSTEM 'foo'>\n" 11336 "]>\n" 11337 "<doc>&x;</doc>"; 11338 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}}; 11339 int i; 11340 const int max_alloc_count = 50; 11341 11342 for (i = 0; i < max_alloc_count; i++) { 11343 allocation_count = i; 11344 XML_SetUserData(g_parser, options); 11345 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11346 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11347 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11348 != XML_STATUS_ERROR) 11349 break; 11350 11351 /* See comment in test_nsalloc_xmlns() */ 11352 nsalloc_teardown(); 11353 nsalloc_setup(); 11354 } 11355 if (i == 0) 11356 fail("Parsing worked despite failing allocations"); 11357 else if (i == max_alloc_count) 11358 fail("Parsing failed even at max allocation count"); 11359 } 11360 END_TEST 11361 11362 START_TEST(test_nsalloc_long_systemid_in_ext) { 11363 const char *text 11364 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11365 " <!ENTITY en SYSTEM '" 11366 /* 64 characters per line */ 11367 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11368 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11369 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11370 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11371 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11372 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11373 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11374 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11375 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11376 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11377 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11378 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11379 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11380 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11381 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11382 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11383 "'>\n" 11384 "]>\n" 11385 "<doc>&en;</doc>"; 11386 ExtOption options[] = { 11387 {XCS("foo"), "<!ELEMENT e EMPTY>"}, 11388 {/* clang-format off */ 11389 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11390 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11391 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11392 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11393 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11394 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11395 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11396 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11397 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11398 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11399 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11400 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11401 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11402 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11403 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11404 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"), 11405 /* clang-format on */ 11406 "<e/>"}, 11407 {NULL, NULL}}; 11408 int i; 11409 const int max_alloc_count = 55; 11410 11411 for (i = 0; i < max_alloc_count; i++) { 11412 allocation_count = i; 11413 XML_SetUserData(g_parser, options); 11414 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11415 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11416 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11417 != XML_STATUS_ERROR) 11418 break; 11419 11420 /* See comment in test_nsalloc_xmlns() */ 11421 nsalloc_teardown(); 11422 nsalloc_setup(); 11423 } 11424 if (i == 0) 11425 fail("Parsing worked despite failing allocations"); 11426 else if (i == max_alloc_count) 11427 fail("Parsing failed even at max allocation count"); 11428 } 11429 END_TEST 11430 11431 /* Test the effects of allocation failure on parsing an element in a 11432 * namespace. Based on test_nsalloc_long_context. 11433 */ 11434 START_TEST(test_nsalloc_prefixed_element) { 11435 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n" 11436 " <!ATTLIST pfx:element baz ID #REQUIRED>\n" 11437 " <!ENTITY en SYSTEM 'bar'>\n" 11438 "]>\n" 11439 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n" 11440 "&en;" 11441 "</pfx:element>"; 11442 ExtOption options[] = { 11443 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 11444 int i; 11445 const int max_alloc_count = 70; 11446 11447 for (i = 0; i < max_alloc_count; i++) { 11448 allocation_count = i; 11449 XML_SetUserData(g_parser, options); 11450 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11451 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11452 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11453 != XML_STATUS_ERROR) 11454 break; 11455 11456 /* See comment in test_nsalloc_xmlns() */ 11457 nsalloc_teardown(); 11458 nsalloc_setup(); 11459 } 11460 if (i == 0) 11461 fail("Success despite failing allocator"); 11462 else if (i == max_alloc_count) 11463 fail("Failed even at full allocation count"); 11464 } 11465 END_TEST 11466 11467 #if defined(XML_DTD) 11468 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int); 11469 11470 struct AccountingTestCase { 11471 const char *primaryText; 11472 const char *firstExternalText; /* often NULL */ 11473 const char *secondExternalText; /* often NULL */ 11474 const unsigned long long expectedCountBytesIndirectExtra; 11475 XML_Bool singleBytesWanted; 11476 }; 11477 11478 static int 11479 accounting_external_entity_ref_handler(XML_Parser parser, 11480 const XML_Char *context, 11481 const XML_Char *base, 11482 const XML_Char *systemId, 11483 const XML_Char *publicId) { 11484 UNUSED_P(context); 11485 UNUSED_P(base); 11486 UNUSED_P(publicId); 11487 11488 const struct AccountingTestCase *const testCase 11489 = (const struct AccountingTestCase *)XML_GetUserData(parser); 11490 11491 const char *externalText = NULL; 11492 if (xcstrcmp(systemId, XCS("first.ent")) == 0) { 11493 externalText = testCase->firstExternalText; 11494 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) { 11495 externalText = testCase->secondExternalText; 11496 } else { 11497 assert(! "systemId is neither \"first.ent\" nor \"second.ent\""); 11498 } 11499 assert(externalText); 11500 11501 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 11502 assert(entParser); 11503 11504 const XmlParseFunction xmlParseFunction 11505 = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11506 11507 const enum XML_Status status = xmlParseFunction( 11508 entParser, externalText, (int)strlen(externalText), XML_TRUE); 11509 11510 XML_ParserFree(entParser); 11511 return status; 11512 } 11513 11514 START_TEST(test_accounting_precision) { 11515 const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */ 11516 struct AccountingTestCase cases[] = { 11517 {"<e/>", NULL, NULL, 0, 0}, 11518 {"<e></e>", NULL, NULL, 0, 0}, 11519 11520 /* Attributes */ 11521 {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later}, 11522 {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0}, 11523 {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0, 11524 filled_later}, 11525 {"<e k=\"&'><"\" />", NULL, NULL, 11526 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11527 {"<e1 xmlns='https://example.org/'>\n" 11528 " <e2 xmlns=''/>\n" 11529 "</e1>", 11530 NULL, NULL, 0, filled_later}, 11531 11532 /* Text */ 11533 {"<e>text</e>", NULL, NULL, 0, filled_later}, 11534 {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later}, 11535 {"<e>&'><"</e>", NULL, NULL, 11536 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11537 {"<e>A)</e>", NULL, NULL, 0, filled_later}, 11538 11539 /* Prolog */ 11540 {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later}, 11541 11542 /* Whitespace */ 11543 {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later}, 11544 {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later}, 11545 {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later}, 11546 11547 /* Comments */ 11548 {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later}, 11549 11550 /* Processing instructions */ 11551 {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>", 11552 NULL, NULL, 0, filled_later}, 11553 {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>", 11554 "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>", 11555 0, filled_later}, 11556 11557 /* CDATA */ 11558 {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later}, 11559 /* The following is the essence of this OSS-Fuzz finding: 11560 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302 11561 https://oss-fuzz.com/testcase-detail/4860575394955264 11562 */ 11563 {"<!DOCTYPE r [\n" 11564 "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n" 11565 "]>\n" 11566 "<r>&e;</r>\n", 11567 NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"), 11568 filled_later}, 11569 11570 /* Conditional sections */ 11571 {"<!DOCTYPE r [\n" 11572 "<!ENTITY % draft 'INCLUDE'>\n" 11573 "<!ENTITY % final 'IGNORE'>\n" 11574 "<!ENTITY % import SYSTEM \"first.ent\">\n" 11575 "%import;\n" 11576 "]>\n" 11577 "<r/>\n", 11578 "<![%draft;[<!--1-->]]>\n" 11579 "<![%final;[<!--22-->]]>", 11580 NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")), 11581 filled_later}, 11582 11583 /* General entities */ 11584 {"<!DOCTYPE root [\n" 11585 "<!ENTITY nine \"123456789\">\n" 11586 "]>\n" 11587 "<root>&nine;</root>", 11588 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11589 {"<!DOCTYPE root [\n" 11590 "<!ENTITY nine \"123456789\">\n" 11591 "]>\n" 11592 "<root k1=\"&nine;\"/>", 11593 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11594 {"<!DOCTYPE root [\n" 11595 "<!ENTITY nine \"123456789\">\n" 11596 "<!ENTITY nine2 \"&nine;&nine;\">\n" 11597 "]>\n" 11598 "<root>&nine2;&nine2;&nine2;</root>", 11599 NULL, NULL, 11600 sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */ 11601 * (strlen("&nine;") + strlen("123456789")), 11602 filled_later}, 11603 {"<!DOCTYPE r [\n" 11604 " <!ENTITY five SYSTEM 'first.ent'>\n" 11605 "]>\n" 11606 "<r>&five;</r>", 11607 "12345", NULL, 0, filled_later}, 11608 11609 /* Parameter entities */ 11610 {"<!DOCTYPE r [\n" 11611 "<!ENTITY % comment \"<!---->\">\n" 11612 "%comment;\n" 11613 "]>\n" 11614 "<r/>", 11615 NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later}, 11616 {"<!DOCTYPE r [\n" 11617 "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n" 11618 "%ninedef;\n" 11619 "]>\n" 11620 "<r>&nine;</r>", 11621 NULL, NULL, 11622 sizeof(XML_Char) 11623 * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")), 11624 filled_later}, 11625 {"<!DOCTYPE r [\n" 11626 "<!ENTITY % comment \"<!--1-->\">\n" 11627 "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n" 11628 "%comment2;\n" 11629 "]>\n" 11630 "<r/>\n", 11631 NULL, NULL, 11632 sizeof(XML_Char) 11633 * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")), 11634 filled_later}, 11635 {"<!DOCTYPE r [\n" 11636 " <!ENTITY % five \"12345\">\n" 11637 " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n" 11638 " %five2def;\n" 11639 "]>\n" 11640 "<r>&five2;</r>", 11641 NULL, NULL, /* from "%five2def;": */ 11642 sizeof(XML_Char) 11643 * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">") 11644 + 2 /* calls to "%five;" */ * strlen("12345") 11645 + /* from "&five2;": */ strlen("[12345][12345]]]]")), 11646 filled_later}, 11647 {"<!DOCTYPE r SYSTEM \"first.ent\">\n" 11648 "<r/>", 11649 "<!ENTITY % comment '<!--1-->'>\n" 11650 "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n" 11651 "%comment2;", 11652 NULL, 11653 sizeof(XML_Char) 11654 * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->") 11655 + 2 /* calls to "%comment;" */ * strlen("<!---->")), 11656 filled_later}, 11657 {"<!DOCTYPE r SYSTEM 'first.ent'>\n" 11658 "<r/>", 11659 "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n" 11660 "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n" 11661 "%e2;\n", 11662 "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"), 11663 filled_later}, 11664 { 11665 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11666 "<r/>", 11667 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11668 "<!ENTITY % e2 '%e1;'>", 11669 "<?xml version='1.0' encoding='utf-8'?>\n" 11670 "hello\n" 11671 "xml" /* without trailing newline! */, 11672 0, 11673 filled_later, 11674 }, 11675 { 11676 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11677 "<r/>", 11678 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11679 "<!ENTITY % e2 '%e1;'>", 11680 "<?xml version='1.0' encoding='utf-8'?>\n" 11681 "hello\n" 11682 "xml\n" /* with trailing newline! */, 11683 0, 11684 filled_later, 11685 }, 11686 {"<!DOCTYPE doc SYSTEM 'first.ent'>\n" 11687 "<doc></doc>\n", 11688 "<!ELEMENT doc EMPTY>\n" 11689 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11690 "<!ENTITY % e2 '%e1;'>\n" 11691 "%e1;\n", 11692 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */, 11693 strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later}, 11694 {"<!DOCTYPE r [\n" 11695 " <!ENTITY five SYSTEM 'first.ent'>\n" 11696 "]>\n" 11697 "<r>&five;</r>", 11698 "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later}, 11699 }; 11700 11701 const size_t countCases = sizeof(cases) / sizeof(cases[0]); 11702 size_t u = 0; 11703 for (; u < countCases; u++) { 11704 size_t v = 0; 11705 for (; v < 2; v++) { 11706 const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE; 11707 const unsigned long long expectedCountBytesDirect 11708 = strlen(cases[u].primaryText); 11709 const unsigned long long expectedCountBytesIndirect 11710 = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText) 11711 : 0) 11712 + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText) 11713 : 0) 11714 + cases[u].expectedCountBytesIndirectExtra; 11715 11716 XML_Parser parser = XML_ParserCreate(NULL); 11717 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11718 if (cases[u].firstExternalText) { 11719 XML_SetExternalEntityRefHandler(parser, 11720 accounting_external_entity_ref_handler); 11721 XML_SetUserData(parser, (void *)&cases[u]); 11722 cases[u].singleBytesWanted = singleBytesWanted; 11723 } 11724 11725 const XmlParseFunction xmlParseFunction 11726 = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11727 11728 enum XML_Status status 11729 = xmlParseFunction(parser, cases[u].primaryText, 11730 (int)strlen(cases[u].primaryText), XML_TRUE); 11731 if (status != XML_STATUS_OK) { 11732 _xml_failure(parser, __FILE__, __LINE__); 11733 } 11734 11735 const unsigned long long actualCountBytesDirect 11736 = testingAccountingGetCountBytesDirect(parser); 11737 const unsigned long long actualCountBytesIndirect 11738 = testingAccountingGetCountBytesIndirect(parser); 11739 11740 XML_ParserFree(parser); 11741 11742 if (actualCountBytesDirect != expectedCountBytesDirect) { 11743 fprintf( 11744 stderr, 11745 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11746 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11747 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11748 expectedCountBytesDirect, actualCountBytesDirect); 11749 fail("Count of direct bytes is off"); 11750 } 11751 11752 if (actualCountBytesIndirect != expectedCountBytesIndirect) { 11753 fprintf( 11754 stderr, 11755 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11756 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11757 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11758 expectedCountBytesIndirect, actualCountBytesIndirect); 11759 fail("Count of indirect bytes is off"); 11760 } 11761 } 11762 } 11763 } 11764 END_TEST 11765 11766 static float 11767 portableNAN() { 11768 return strtof("nan", NULL); 11769 } 11770 11771 static float 11772 portableINFINITY() { 11773 return strtof("infinity", NULL); 11774 } 11775 11776 START_TEST(test_billion_laughs_attack_protection_api) { 11777 XML_Parser parserWithoutParent = XML_ParserCreate(NULL); 11778 XML_Parser parserWithParent 11779 = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL); 11780 if (parserWithoutParent == NULL) 11781 fail("parserWithoutParent is NULL"); 11782 if (parserWithParent == NULL) 11783 fail("parserWithParent is NULL"); 11784 11785 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases 11786 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f) 11787 == XML_TRUE) 11788 fail("Call with NULL parser is NOT supposed to succeed"); 11789 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent, 11790 123.0f) 11791 == XML_TRUE) 11792 fail("Call with non-root parser is NOT supposed to succeed"); 11793 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11794 parserWithoutParent, portableNAN()) 11795 == XML_TRUE) 11796 fail("Call with NaN limit is NOT supposed to succeed"); 11797 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11798 parserWithoutParent, -1.0f) 11799 == XML_TRUE) 11800 fail("Call with negative limit is NOT supposed to succeed"); 11801 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11802 parserWithoutParent, 0.9f) 11803 == XML_TRUE) 11804 fail("Call with positive limit <1.0 is NOT supposed to succeed"); 11805 11806 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases 11807 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11808 parserWithoutParent, 1.0f) 11809 == XML_FALSE) 11810 fail("Call with positive limit >=1.0 is supposed to succeed"); 11811 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11812 parserWithoutParent, 123456.789f) 11813 == XML_FALSE) 11814 fail("Call with positive limit >=1.0 is supposed to succeed"); 11815 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11816 parserWithoutParent, portableINFINITY()) 11817 == XML_FALSE) 11818 fail("Call with positive limit >=1.0 is supposed to succeed"); 11819 11820 // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases 11821 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123) 11822 == XML_TRUE) 11823 fail("Call with NULL parser is NOT supposed to succeed"); 11824 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent, 11825 123) 11826 == XML_TRUE) 11827 fail("Call with non-root parser is NOT supposed to succeed"); 11828 11829 // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases 11830 if (XML_SetBillionLaughsAttackProtectionActivationThreshold( 11831 parserWithoutParent, 123) 11832 == XML_FALSE) 11833 fail("Call with non-NULL parentless parser is supposed to succeed"); 11834 11835 XML_ParserFree(parserWithParent); 11836 XML_ParserFree(parserWithoutParent); 11837 } 11838 END_TEST 11839 11840 START_TEST(test_helper_unsigned_char_to_printable) { 11841 // Smoke test 11842 unsigned char uc = 0; 11843 for (; uc < (unsigned char)-1; uc++) { 11844 const char *const printable = unsignedCharToPrintable(uc); 11845 if (printable == NULL) 11846 fail("unsignedCharToPrintable returned NULL"); 11847 if (strlen(printable) < (size_t)1) 11848 fail("unsignedCharToPrintable returned empty string"); 11849 } 11850 11851 // Two concrete samples 11852 if (strcmp(unsignedCharToPrintable('A'), "A") != 0) 11853 fail("unsignedCharToPrintable result mistaken"); 11854 if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0) 11855 fail("unsignedCharToPrintable result mistaken"); 11856 } 11857 END_TEST 11858 #endif // defined(XML_DTD) 11859 11860 static Suite * 11861 make_suite(void) { 11862 Suite *s = suite_create("basic"); 11863 TCase *tc_basic = tcase_create("basic tests"); 11864 TCase *tc_namespace = tcase_create("XML namespaces"); 11865 TCase *tc_misc = tcase_create("miscellaneous tests"); 11866 TCase *tc_alloc = tcase_create("allocation tests"); 11867 TCase *tc_nsalloc = tcase_create("namespace allocation tests"); 11868 #if defined(XML_DTD) 11869 TCase *tc_accounting = tcase_create("accounting tests"); 11870 #endif 11871 11872 suite_add_tcase(s, tc_basic); 11873 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown); 11874 tcase_add_test(tc_basic, test_nul_byte); 11875 tcase_add_test(tc_basic, test_u0000_char); 11876 tcase_add_test(tc_basic, test_siphash_self); 11877 tcase_add_test(tc_basic, test_siphash_spec); 11878 tcase_add_test(tc_basic, test_bom_utf8); 11879 tcase_add_test(tc_basic, test_bom_utf16_be); 11880 tcase_add_test(tc_basic, test_bom_utf16_le); 11881 tcase_add_test(tc_basic, test_nobom_utf16_le); 11882 tcase_add_test(tc_basic, test_illegal_utf8); 11883 tcase_add_test(tc_basic, test_utf8_auto_align); 11884 tcase_add_test(tc_basic, test_utf16); 11885 tcase_add_test(tc_basic, test_utf16_le_epilog_newline); 11886 tcase_add_test(tc_basic, test_not_utf16); 11887 tcase_add_test(tc_basic, test_bad_encoding); 11888 tcase_add_test(tc_basic, test_latin1_umlauts); 11889 tcase_add_test(tc_basic, test_long_utf8_character); 11890 tcase_add_test(tc_basic, test_long_latin1_attribute); 11891 tcase_add_test(tc_basic, test_long_ascii_attribute); 11892 /* Regression test for SF bug #491986. */ 11893 tcase_add_test(tc_basic, test_danish_latin1); 11894 /* Regression test for SF bug #514281. */ 11895 tcase_add_test(tc_basic, test_french_charref_hexidecimal); 11896 tcase_add_test(tc_basic, test_french_charref_decimal); 11897 tcase_add_test(tc_basic, test_french_latin1); 11898 tcase_add_test(tc_basic, test_french_utf8); 11899 tcase_add_test(tc_basic, test_utf8_false_rejection); 11900 tcase_add_test(tc_basic, test_line_number_after_parse); 11901 tcase_add_test(tc_basic, test_column_number_after_parse); 11902 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers); 11903 tcase_add_test(tc_basic, test_line_number_after_error); 11904 tcase_add_test(tc_basic, test_column_number_after_error); 11905 tcase_add_test(tc_basic, test_really_long_lines); 11906 tcase_add_test(tc_basic, test_really_long_encoded_lines); 11907 tcase_add_test(tc_basic, test_end_element_events); 11908 tcase_add_test(tc_basic, test_attr_whitespace_normalization); 11909 tcase_add_test(tc_basic, test_xmldecl_misplaced); 11910 tcase_add_test(tc_basic, test_xmldecl_invalid); 11911 tcase_add_test(tc_basic, test_xmldecl_missing_attr); 11912 tcase_add_test(tc_basic, test_xmldecl_missing_value); 11913 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity); 11914 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity); 11915 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset); 11916 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset); 11917 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone); 11918 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset); 11919 tcase_add_test(tc_basic, test_not_standalone_handler_reject); 11920 tcase_add_test(tc_basic, test_not_standalone_handler_accept); 11921 tcase_add_test(tc_basic, 11922 test_wfc_undeclared_entity_with_external_subset_standalone); 11923 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone); 11924 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs); 11925 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding); 11926 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler); 11927 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom); 11928 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding); 11929 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2); 11930 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse); 11931 tcase_add_test__ifdef_xml_dtd(tc_basic, 11932 test_ext_entity_invalid_suspended_parse); 11933 tcase_add_test(tc_basic, test_dtd_default_handling); 11934 tcase_add_test(tc_basic, test_dtd_attr_handling); 11935 tcase_add_test(tc_basic, test_empty_ns_without_namespaces); 11936 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces); 11937 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls); 11938 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls); 11939 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls); 11940 tcase_add_test(tc_basic, test_good_cdata_ascii); 11941 tcase_add_test(tc_basic, test_good_cdata_utf16); 11942 tcase_add_test(tc_basic, test_good_cdata_utf16_le); 11943 tcase_add_test(tc_basic, test_long_cdata_utf16); 11944 tcase_add_test(tc_basic, test_multichar_cdata_utf16); 11945 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair); 11946 tcase_add_test(tc_basic, test_bad_cdata); 11947 tcase_add_test(tc_basic, test_bad_cdata_utf16); 11948 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls); 11949 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls); 11950 tcase_add_test(tc_basic, test_memory_allocation); 11951 tcase_add_test(tc_basic, test_default_current); 11952 tcase_add_test(tc_basic, test_dtd_elements); 11953 tcase_add_test(tc_basic, test_dtd_elements_nesting); 11954 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd); 11955 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone); 11956 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd); 11957 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype); 11958 tcase_add_test__ifdef_xml_dtd(tc_basic, 11959 test_foreign_dtd_without_external_subset); 11960 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd); 11961 tcase_add_test(tc_basic, test_set_base); 11962 tcase_add_test(tc_basic, test_attributes); 11963 tcase_add_test(tc_basic, test_reset_in_entity); 11964 tcase_add_test(tc_basic, test_resume_invalid_parse); 11965 tcase_add_test(tc_basic, test_resume_resuspended); 11966 tcase_add_test(tc_basic, test_cdata_default); 11967 tcase_add_test(tc_basic, test_subordinate_reset); 11968 tcase_add_test(tc_basic, test_subordinate_suspend); 11969 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend); 11970 tcase_add_test(tc_basic, test_subordinate_xdecl_abort); 11971 tcase_add_test(tc_basic, test_explicit_encoding); 11972 tcase_add_test(tc_basic, test_trailing_cr); 11973 tcase_add_test(tc_basic, test_ext_entity_trailing_cr); 11974 tcase_add_test(tc_basic, test_trailing_rsqb); 11975 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb); 11976 tcase_add_test(tc_basic, test_ext_entity_good_cdata); 11977 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters); 11978 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter); 11979 tcase_add_test(tc_basic, test_empty_parse); 11980 tcase_add_test(tc_basic, test_get_buffer_1); 11981 tcase_add_test(tc_basic, test_get_buffer_2); 11982 #if defined(XML_CONTEXT_BYTES) 11983 tcase_add_test(tc_basic, test_get_buffer_3_overflow); 11984 #endif 11985 tcase_add_test(tc_basic, test_byte_info_at_end); 11986 tcase_add_test(tc_basic, test_byte_info_at_error); 11987 tcase_add_test(tc_basic, test_byte_info_at_cdata); 11988 tcase_add_test(tc_basic, test_predefined_entities); 11989 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd); 11990 tcase_add_test(tc_basic, test_not_predefined_entities); 11991 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section); 11992 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16); 11993 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be); 11994 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section); 11995 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values); 11996 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone); 11997 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort); 11998 tcase_add_test(tc_basic, test_bad_public_doctype); 11999 tcase_add_test(tc_basic, test_attribute_enum_value); 12000 tcase_add_test(tc_basic, test_predefined_entity_redefinition); 12001 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing); 12002 tcase_add_test(tc_basic, test_public_notation_no_sysid); 12003 tcase_add_test(tc_basic, test_nested_groups); 12004 tcase_add_test(tc_basic, test_group_choice); 12005 tcase_add_test(tc_basic, test_standalone_parameter_entity); 12006 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity); 12007 tcase_add_test__ifdef_xml_dtd(tc_basic, 12008 test_recursive_external_parameter_entity); 12009 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd); 12010 tcase_add_test(tc_basic, test_suspend_xdecl); 12011 tcase_add_test(tc_basic, test_abort_epilog); 12012 tcase_add_test(tc_basic, test_abort_epilog_2); 12013 tcase_add_test(tc_basic, test_suspend_epilog); 12014 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag); 12015 tcase_add_test(tc_basic, test_unfinished_epilog); 12016 tcase_add_test(tc_basic, test_partial_char_in_epilog); 12017 tcase_add_test(tc_basic, test_hash_collision); 12018 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity); 12019 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error); 12020 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity); 12021 tcase_add_test(tc_basic, test_restart_on_error); 12022 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value); 12023 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value); 12024 tcase_add_test(tc_basic, test_trailing_cr_in_att_value); 12025 tcase_add_test(tc_basic, test_standalone_internal_entity); 12026 tcase_add_test(tc_basic, test_skipped_external_entity); 12027 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity); 12028 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity); 12029 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr); 12030 tcase_add_test(tc_basic, test_invalid_character_entity); 12031 tcase_add_test(tc_basic, test_invalid_character_entity_2); 12032 tcase_add_test(tc_basic, test_invalid_character_entity_3); 12033 tcase_add_test(tc_basic, test_invalid_character_entity_4); 12034 tcase_add_test(tc_basic, test_pi_handled_in_default); 12035 tcase_add_test(tc_basic, test_comment_handled_in_default); 12036 tcase_add_test(tc_basic, test_pi_yml); 12037 tcase_add_test(tc_basic, test_pi_xnl); 12038 tcase_add_test(tc_basic, test_pi_xmm); 12039 tcase_add_test(tc_basic, test_utf16_pi); 12040 tcase_add_test(tc_basic, test_utf16_be_pi); 12041 tcase_add_test(tc_basic, test_utf16_be_comment); 12042 tcase_add_test(tc_basic, test_utf16_le_comment); 12043 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn); 12044 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn); 12045 tcase_add_test(tc_basic, test_unknown_encoding_success); 12046 tcase_add_test(tc_basic, test_unknown_encoding_bad_name); 12047 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2); 12048 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1); 12049 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2); 12050 tcase_add_test(tc_basic, test_invalid_unknown_encoding); 12051 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok); 12052 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail); 12053 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length); 12054 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit); 12055 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate); 12056 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high); 12057 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value); 12058 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom); 12059 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom); 12060 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2); 12061 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2); 12062 tcase_add_test(tc_basic, test_ext_entity_utf16_be); 12063 tcase_add_test(tc_basic, test_ext_entity_utf16_le); 12064 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown); 12065 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom); 12066 tcase_add_test(tc_basic, test_utf8_in_cdata_section); 12067 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2); 12068 tcase_add_test(tc_basic, test_utf8_in_start_tags); 12069 tcase_add_test(tc_basic, test_trailing_spaces_in_elements); 12070 tcase_add_test(tc_basic, test_utf16_attribute); 12071 tcase_add_test(tc_basic, test_utf16_second_attr); 12072 tcase_add_test(tc_basic, test_attr_after_solidus); 12073 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe); 12074 tcase_add_test(tc_basic, test_bad_attr_desc_keyword); 12075 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16); 12076 tcase_add_test(tc_basic, test_bad_doctype); 12077 tcase_add_test(tc_basic, test_bad_doctype_utf8); 12078 tcase_add_test(tc_basic, test_bad_doctype_utf16); 12079 tcase_add_test(tc_basic, test_bad_doctype_plus); 12080 tcase_add_test(tc_basic, test_bad_doctype_star); 12081 tcase_add_test(tc_basic, test_bad_doctype_query); 12082 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore); 12083 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr); 12084 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr); 12085 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be); 12086 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le); 12087 tcase_add_test(tc_basic, test_short_doctype); 12088 tcase_add_test(tc_basic, test_short_doctype_2); 12089 tcase_add_test(tc_basic, test_short_doctype_3); 12090 tcase_add_test(tc_basic, test_long_doctype); 12091 tcase_add_test(tc_basic, test_bad_entity); 12092 tcase_add_test(tc_basic, test_bad_entity_2); 12093 tcase_add_test(tc_basic, test_bad_entity_3); 12094 tcase_add_test(tc_basic, test_bad_entity_4); 12095 tcase_add_test(tc_basic, test_bad_notation); 12096 tcase_add_test(tc_basic, test_default_doctype_handler); 12097 tcase_add_test(tc_basic, test_empty_element_abort); 12098 12099 suite_add_tcase(s, tc_namespace); 12100 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown); 12101 tcase_add_test(tc_namespace, test_return_ns_triplet); 12102 tcase_add_test(tc_namespace, test_ns_tagname_overwrite); 12103 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet); 12104 tcase_add_test(tc_namespace, test_start_ns_clears_start_element); 12105 tcase_add_test__ifdef_xml_dtd(tc_namespace, 12106 test_default_ns_from_ext_subset_and_ext_ge); 12107 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1); 12108 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2); 12109 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3); 12110 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4); 12111 tcase_add_test(tc_namespace, test_ns_unbound_prefix); 12112 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri); 12113 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes); 12114 tcase_add_test(tc_namespace, test_ns_duplicate_hashes); 12115 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute); 12116 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element); 12117 tcase_add_test(tc_namespace, test_ns_parser_reset); 12118 tcase_add_test(tc_namespace, test_ns_long_element); 12119 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts); 12120 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer); 12121 tcase_add_test(tc_namespace, test_ns_reserved_attributes); 12122 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2); 12123 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix); 12124 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success); 12125 tcase_add_test(tc_namespace, test_ns_double_colon); 12126 tcase_add_test(tc_namespace, test_ns_double_colon_element); 12127 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname); 12128 tcase_add_test(tc_namespace, test_ns_bad_element_leafname); 12129 tcase_add_test(tc_namespace, test_ns_utf16_leafname); 12130 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname); 12131 tcase_add_test(tc_namespace, test_ns_utf16_doctype); 12132 tcase_add_test(tc_namespace, test_ns_invalid_doctype); 12133 tcase_add_test(tc_namespace, test_ns_double_colon_doctype); 12134 tcase_add_test(tc_namespace, test_ns_separator_in_uri); 12135 12136 suite_add_tcase(s, tc_misc); 12137 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); 12138 tcase_add_test(tc_misc, test_misc_alloc_create_parser); 12139 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding); 12140 tcase_add_test(tc_misc, test_misc_null_parser); 12141 tcase_add_test(tc_misc, test_misc_error_string); 12142 tcase_add_test(tc_misc, test_misc_version); 12143 tcase_add_test(tc_misc, test_misc_features); 12144 tcase_add_test(tc_misc, test_misc_attribute_leak); 12145 tcase_add_test(tc_misc, test_misc_utf16le); 12146 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1); 12147 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2); 12148 tcase_add_test__ifdef_xml_dtd( 12149 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317); 12150 12151 suite_add_tcase(s, tc_alloc); 12152 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); 12153 tcase_add_test(tc_alloc, test_alloc_parse_xdecl); 12154 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2); 12155 tcase_add_test(tc_alloc, test_alloc_parse_pi); 12156 tcase_add_test(tc_alloc, test_alloc_parse_pi_2); 12157 tcase_add_test(tc_alloc, test_alloc_parse_pi_3); 12158 tcase_add_test(tc_alloc, test_alloc_parse_comment); 12159 tcase_add_test(tc_alloc, test_alloc_parse_comment_2); 12160 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser); 12161 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser); 12162 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts); 12163 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity); 12164 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding); 12165 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity); 12166 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling); 12167 tcase_add_test(tc_alloc, test_alloc_explicit_encoding); 12168 tcase_add_test(tc_alloc, test_alloc_set_base); 12169 tcase_add_test(tc_alloc, test_alloc_realloc_buffer); 12170 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer); 12171 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes); 12172 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value); 12173 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12174 test_alloc_realloc_subst_public_entity_value); 12175 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype); 12176 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name); 12177 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd); 12178 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value); 12179 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12180 test_alloc_realloc_attribute_enum_value); 12181 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute); 12182 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute); 12183 tcase_add_test(tc_alloc, test_alloc_notation); 12184 tcase_add_test(tc_alloc, test_alloc_public_notation); 12185 tcase_add_test(tc_alloc, test_alloc_system_notation); 12186 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups); 12187 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups); 12188 tcase_add_test(tc_alloc, test_alloc_large_group); 12189 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice); 12190 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog); 12191 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog); 12192 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12193 test_alloc_realloc_long_attribute_value); 12194 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace); 12195 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity); 12196 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref); 12197 tcase_add_test(tc_alloc, test_alloc_long_attr_value); 12198 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities); 12199 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12200 test_alloc_realloc_param_entity_newline); 12201 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe); 12202 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes); 12203 tcase_add_test(tc_alloc, test_alloc_long_doc_name); 12204 tcase_add_test(tc_alloc, test_alloc_long_base); 12205 tcase_add_test(tc_alloc, test_alloc_long_public_id); 12206 tcase_add_test(tc_alloc, test_alloc_long_entity_value); 12207 tcase_add_test(tc_alloc, test_alloc_long_notation); 12208 12209 suite_add_tcase(s, tc_nsalloc); 12210 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown); 12211 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns); 12212 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer); 12213 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix); 12214 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri); 12215 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr); 12216 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix); 12217 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes); 12218 tcase_add_test(tc_nsalloc, test_nsalloc_long_element); 12219 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri); 12220 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix); 12221 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix); 12222 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace); 12223 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace); 12224 tcase_add_test(tc_nsalloc, test_nsalloc_long_context); 12225 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context); 12226 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2); 12227 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3); 12228 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4); 12229 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5); 12230 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6); 12231 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7); 12232 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name); 12233 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd); 12234 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext); 12235 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext); 12236 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element); 12237 12238 #if defined(XML_DTD) 12239 suite_add_tcase(s, tc_accounting); 12240 tcase_add_test(tc_accounting, test_accounting_precision); 12241 tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); 12242 tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); 12243 #endif 12244 12245 return s; 12246 } 12247 12248 int 12249 main(int argc, char *argv[]) { 12250 int i, nf; 12251 int verbosity = CK_NORMAL; 12252 Suite *s = make_suite(); 12253 SRunner *sr = srunner_create(s); 12254 12255 /* run the tests for internal helper functions */ 12256 testhelper_is_whitespace_normalized(); 12257 12258 for (i = 1; i < argc; ++i) { 12259 char *opt = argv[i]; 12260 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0) 12261 verbosity = CK_VERBOSE; 12262 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0) 12263 verbosity = CK_SILENT; 12264 else { 12265 fprintf(stderr, "runtests: unknown option '%s'\n", opt); 12266 return 2; 12267 } 12268 } 12269 if (verbosity != CK_SILENT) 12270 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion()); 12271 srunner_run_all(sr, verbosity); 12272 nf = srunner_ntests_failed(sr); 12273 srunner_free(sr); 12274 12275 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 12276 } 12277