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 void 4994 suspending_comment_handler(void *userData, const XML_Char *data) { 4995 UNUSED_P(data); 4996 XML_Parser parser = (XML_Parser)userData; 4997 XML_StopParser(parser, XML_TRUE); 4998 } 4999 5000 START_TEST(test_suspend_resume_internal_entity_issue_629) { 5001 const char *const text 5002 = "<!DOCTYPE a [<!ENTITY e '<!--COMMENT-->a'>]><a>&e;<b>\n" 5003 "<" 5004 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5005 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5006 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5007 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5008 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5009 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5010 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5011 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5012 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5013 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5014 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5015 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5016 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5017 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5018 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5019 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5020 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5021 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5022 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5023 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5024 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5025 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5026 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5027 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5028 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5029 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5030 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5031 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5032 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5033 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5034 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5035 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5036 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5037 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5038 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5039 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5040 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5041 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5042 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5043 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 5044 "/>" 5045 "</b></a>"; 5046 const size_t firstChunkSizeBytes = 54; 5047 5048 XML_Parser parser = XML_ParserCreate(NULL); 5049 XML_SetUserData(parser, parser); 5050 XML_SetCommentHandler(parser, suspending_comment_handler); 5051 5052 if (XML_Parse(parser, text, (int)firstChunkSizeBytes, XML_FALSE) 5053 != XML_STATUS_SUSPENDED) 5054 xml_failure(parser); 5055 if (XML_ResumeParser(parser) != XML_STATUS_OK) 5056 xml_failure(parser); 5057 if (XML_Parse(parser, text + firstChunkSizeBytes, 5058 (int)(strlen(text) - firstChunkSizeBytes), XML_TRUE) 5059 != XML_STATUS_OK) 5060 xml_failure(parser); 5061 XML_ParserFree(parser); 5062 } 5063 END_TEST 5064 5065 /* Test syntax error is caught at parse resumption */ 5066 START_TEST(test_resume_entity_with_syntax_error) { 5067 const char *text = "<!DOCTYPE doc [\n" 5068 "<!ENTITY foo '<suspend>Hi</wombat>'>\n" 5069 "]>\n" 5070 "<doc>&foo;</doc>\n"; 5071 5072 XML_SetStartElementHandler(g_parser, start_element_suspender); 5073 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5074 != XML_STATUS_SUSPENDED) 5075 xml_failure(g_parser); 5076 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 5077 fail("Syntax error in entity not faulted"); 5078 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH) 5079 xml_failure(g_parser); 5080 } 5081 END_TEST 5082 5083 /* Test suspending and resuming in a parameter entity substitution */ 5084 static void XMLCALL 5085 element_decl_suspender(void *userData, const XML_Char *name, 5086 XML_Content *model) { 5087 UNUSED_P(userData); 5088 UNUSED_P(name); 5089 XML_StopParser(g_parser, XML_TRUE); 5090 XML_FreeContentModel(g_parser, model); 5091 } 5092 5093 START_TEST(test_suspend_resume_parameter_entity) { 5094 const char *text = "<!DOCTYPE doc [\n" 5095 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n" 5096 "%foo;\n" 5097 "]>\n" 5098 "<doc>Hello, world</doc>"; 5099 const XML_Char *expected = XCS("Hello, world"); 5100 CharData storage; 5101 5102 CharData_Init(&storage); 5103 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5104 XML_SetElementDeclHandler(g_parser, element_decl_suspender); 5105 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 5106 XML_SetUserData(g_parser, &storage); 5107 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5108 != XML_STATUS_SUSPENDED) 5109 xml_failure(g_parser); 5110 CharData_CheckXMLChars(&storage, XCS("")); 5111 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 5112 xml_failure(g_parser); 5113 CharData_CheckXMLChars(&storage, expected); 5114 } 5115 END_TEST 5116 5117 /* Test attempting to use parser after an error is faulted */ 5118 START_TEST(test_restart_on_error) { 5119 const char *text = "<$doc><doc></doc>"; 5120 5121 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5122 != XML_STATUS_ERROR) 5123 fail("Invalid tag name not faulted"); 5124 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 5125 xml_failure(g_parser); 5126 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 5127 fail("Restarting invalid parse not faulted"); 5128 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 5129 xml_failure(g_parser); 5130 } 5131 END_TEST 5132 5133 /* Test that angle brackets in an attribute default value are faulted */ 5134 START_TEST(test_reject_lt_in_attribute_value) { 5135 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n" 5136 "<doc></doc>"; 5137 5138 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5139 "Bad attribute default not faulted"); 5140 } 5141 END_TEST 5142 5143 START_TEST(test_reject_unfinished_param_in_att_value) { 5144 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n" 5145 "<doc></doc>"; 5146 5147 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5148 "Bad attribute default not faulted"); 5149 } 5150 END_TEST 5151 5152 START_TEST(test_trailing_cr_in_att_value) { 5153 const char *text = "<doc a='value\r'/>"; 5154 5155 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5156 == XML_STATUS_ERROR) 5157 xml_failure(g_parser); 5158 } 5159 END_TEST 5160 5161 /* Try parsing a general entity within a parameter entity in a 5162 * standalone internal DTD. Covers a corner case in the parser. 5163 */ 5164 START_TEST(test_standalone_internal_entity) { 5165 const char *text = "<?xml version='1.0' standalone='yes' ?>\n" 5166 "<!DOCTYPE doc [\n" 5167 " <!ELEMENT doc (#PCDATA)>\n" 5168 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n" 5169 " <!ENTITY ge 'AttDefaultValue'>\n" 5170 " %pe;\n" 5171 "]>\n" 5172 "<doc att2='any'/>"; 5173 5174 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5175 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5176 == XML_STATUS_ERROR) 5177 xml_failure(g_parser); 5178 } 5179 END_TEST 5180 5181 /* Test that a reference to an unknown external entity is skipped */ 5182 START_TEST(test_skipped_external_entity) { 5183 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5184 "<doc></doc>\n"; 5185 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n" 5186 "<!ENTITY % e2 '%e1;'>\n", 5187 NULL, NULL}; 5188 5189 XML_SetUserData(g_parser, &test_data); 5190 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5191 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5192 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5193 == XML_STATUS_ERROR) 5194 xml_failure(g_parser); 5195 } 5196 END_TEST 5197 5198 /* Test a different form of unknown external entity */ 5199 typedef struct ext_hdlr_data { 5200 const char *parse_text; 5201 XML_ExternalEntityRefHandler handler; 5202 } ExtHdlrData; 5203 5204 static int XMLCALL 5205 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context, 5206 const XML_Char *base, const XML_Char *systemId, 5207 const XML_Char *publicId) { 5208 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser); 5209 XML_Parser ext_parser; 5210 5211 UNUSED_P(base); 5212 UNUSED_P(systemId); 5213 UNUSED_P(publicId); 5214 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 5215 if (ext_parser == NULL) 5216 fail("Could not create external entity parser."); 5217 /* Use the requested entity parser for further externals */ 5218 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler); 5219 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text, 5220 (int)strlen(test_data->parse_text), XML_TRUE) 5221 == XML_STATUS_ERROR) { 5222 xml_failure(ext_parser); 5223 } 5224 5225 XML_ParserFree(ext_parser); 5226 return XML_STATUS_OK; 5227 } 5228 5229 START_TEST(test_skipped_null_loaded_ext_entity) { 5230 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5231 "<doc />"; 5232 ExtHdlrData test_data 5233 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5234 "<!ENTITY % pe2 '%pe1;'>\n" 5235 "%pe2;\n", 5236 external_entity_null_loader}; 5237 5238 XML_SetUserData(g_parser, &test_data); 5239 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5240 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5241 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5242 == XML_STATUS_ERROR) 5243 xml_failure(g_parser); 5244 } 5245 END_TEST 5246 5247 START_TEST(test_skipped_unloaded_ext_entity) { 5248 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5249 "<doc />"; 5250 ExtHdlrData test_data 5251 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5252 "<!ENTITY % pe2 '%pe1;'>\n" 5253 "%pe2;\n", 5254 NULL}; 5255 5256 XML_SetUserData(g_parser, &test_data); 5257 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5258 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5259 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5260 == XML_STATUS_ERROR) 5261 xml_failure(g_parser); 5262 } 5263 END_TEST 5264 5265 /* Test that a parameter entity value ending with a carriage return 5266 * has it translated internally into a newline. 5267 */ 5268 START_TEST(test_param_entity_with_trailing_cr) { 5269 #define PARAM_ENTITY_NAME "pe" 5270 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">" 5271 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5272 "<doc/>"; 5273 ExtTest test_data 5274 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n" 5275 "%" PARAM_ENTITY_NAME ";\n", 5276 NULL, NULL}; 5277 5278 XML_SetUserData(g_parser, &test_data); 5279 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5280 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5281 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler); 5282 entity_name_to_match = XCS(PARAM_ENTITY_NAME); 5283 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n"); 5284 entity_match_flag = ENTITY_MATCH_NOT_FOUND; 5285 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5286 == XML_STATUS_ERROR) 5287 xml_failure(g_parser); 5288 if (entity_match_flag == ENTITY_MATCH_FAIL) 5289 fail("Parameter entity CR->NEWLINE conversion failed"); 5290 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND) 5291 fail("Parameter entity not parsed"); 5292 } 5293 #undef PARAM_ENTITY_NAME 5294 #undef PARAM_ENTITY_CORE_VALUE 5295 END_TEST 5296 5297 START_TEST(test_invalid_character_entity) { 5298 const char *text = "<!DOCTYPE doc [\n" 5299 " <!ENTITY entity '�'>\n" 5300 "]>\n" 5301 "<doc>&entity;</doc>"; 5302 5303 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5304 "Out of range character reference not faulted"); 5305 } 5306 END_TEST 5307 5308 START_TEST(test_invalid_character_entity_2) { 5309 const char *text = "<!DOCTYPE doc [\n" 5310 " <!ENTITY entity '&#xg0;'>\n" 5311 "]>\n" 5312 "<doc>&entity;</doc>"; 5313 5314 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5315 "Out of range character reference not faulted"); 5316 } 5317 END_TEST 5318 5319 START_TEST(test_invalid_character_entity_3) { 5320 const char text[] = 5321 /* <!DOCTYPE doc [\n */ 5322 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 5323 /* U+0E04 = KHO KHWAI 5324 * U+0E08 = CHO CHAN */ 5325 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */ 5326 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 " 5327 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n" 5328 /* ]>\n */ 5329 "\0]\0>\0\n" 5330 /* <doc>&entity;</doc> */ 5331 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>"; 5332 5333 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5334 != XML_STATUS_ERROR) 5335 fail("Invalid start of entity name not faulted"); 5336 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY) 5337 xml_failure(g_parser); 5338 } 5339 END_TEST 5340 5341 START_TEST(test_invalid_character_entity_4) { 5342 const char *text = "<!DOCTYPE doc [\n" 5343 " <!ENTITY entity '�'>\n" /* = � */ 5344 "]>\n" 5345 "<doc>&entity;</doc>"; 5346 5347 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5348 "Out of range character reference not faulted"); 5349 } 5350 END_TEST 5351 5352 /* Test that processing instructions are picked up by a default handler */ 5353 START_TEST(test_pi_handled_in_default) { 5354 const char *text = "<?test processing instruction?>\n<doc/>"; 5355 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>"); 5356 CharData storage; 5357 5358 CharData_Init(&storage); 5359 XML_SetDefaultHandler(g_parser, accumulate_characters); 5360 XML_SetUserData(g_parser, &storage); 5361 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5362 == XML_STATUS_ERROR) 5363 xml_failure(g_parser); 5364 CharData_CheckXMLChars(&storage, expected); 5365 } 5366 END_TEST 5367 5368 /* Test that comments are picked up by a default handler */ 5369 START_TEST(test_comment_handled_in_default) { 5370 const char *text = "<!-- This is a comment -->\n<doc/>"; 5371 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>"); 5372 CharData storage; 5373 5374 CharData_Init(&storage); 5375 XML_SetDefaultHandler(g_parser, accumulate_characters); 5376 XML_SetUserData(g_parser, &storage); 5377 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5378 == XML_STATUS_ERROR) 5379 xml_failure(g_parser); 5380 CharData_CheckXMLChars(&storage, expected); 5381 } 5382 END_TEST 5383 5384 /* Test PIs that look almost but not quite like XML declarations */ 5385 static void XMLCALL 5386 accumulate_pi_characters(void *userData, const XML_Char *target, 5387 const XML_Char *data) { 5388 CharData *storage = (CharData *)userData; 5389 5390 CharData_AppendXMLChars(storage, target, -1); 5391 CharData_AppendXMLChars(storage, XCS(": "), 2); 5392 CharData_AppendXMLChars(storage, data, -1); 5393 CharData_AppendXMLChars(storage, XCS("\n"), 1); 5394 } 5395 5396 START_TEST(test_pi_yml) { 5397 const char *text = "<?yml something like data?><doc/>"; 5398 const XML_Char *expected = XCS("yml: something like data\n"); 5399 CharData storage; 5400 5401 CharData_Init(&storage); 5402 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5403 XML_SetUserData(g_parser, &storage); 5404 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5405 == XML_STATUS_ERROR) 5406 xml_failure(g_parser); 5407 CharData_CheckXMLChars(&storage, expected); 5408 } 5409 END_TEST 5410 5411 START_TEST(test_pi_xnl) { 5412 const char *text = "<?xnl nothing like data?><doc/>"; 5413 const XML_Char *expected = XCS("xnl: nothing like data\n"); 5414 CharData storage; 5415 5416 CharData_Init(&storage); 5417 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5418 XML_SetUserData(g_parser, &storage); 5419 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5420 == XML_STATUS_ERROR) 5421 xml_failure(g_parser); 5422 CharData_CheckXMLChars(&storage, expected); 5423 } 5424 END_TEST 5425 5426 START_TEST(test_pi_xmm) { 5427 const char *text = "<?xmm everything like data?><doc/>"; 5428 const XML_Char *expected = XCS("xmm: everything like data\n"); 5429 CharData storage; 5430 5431 CharData_Init(&storage); 5432 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5433 XML_SetUserData(g_parser, &storage); 5434 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5435 == XML_STATUS_ERROR) 5436 xml_failure(g_parser); 5437 CharData_CheckXMLChars(&storage, expected); 5438 } 5439 END_TEST 5440 5441 START_TEST(test_utf16_pi) { 5442 const char text[] = 5443 /* <?{KHO KHWAI}{CHO CHAN}?> 5444 * where {KHO KHWAI} = U+0E04 5445 * and {CHO CHAN} = U+0E08 5446 */ 5447 "<\0?\0\x04\x0e\x08\x0e?\0>\0" 5448 /* <q/> */ 5449 "<\0q\0/\0>\0"; 5450 #ifdef XML_UNICODE 5451 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5452 #else 5453 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5454 #endif 5455 CharData storage; 5456 5457 CharData_Init(&storage); 5458 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 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 START_TEST(test_utf16_be_pi) { 5468 const char text[] = 5469 /* <?{KHO KHWAI}{CHO CHAN}?> 5470 * where {KHO KHWAI} = U+0E04 5471 * and {CHO CHAN} = U+0E08 5472 */ 5473 "\0<\0?\x0e\x04\x0e\x08\0?\0>" 5474 /* <q/> */ 5475 "\0<\0q\0/\0>"; 5476 #ifdef XML_UNICODE 5477 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5478 #else 5479 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5480 #endif 5481 CharData storage; 5482 5483 CharData_Init(&storage); 5484 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5485 XML_SetUserData(g_parser, &storage); 5486 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5487 == XML_STATUS_ERROR) 5488 xml_failure(g_parser); 5489 CharData_CheckXMLChars(&storage, expected); 5490 } 5491 END_TEST 5492 5493 /* Test that comments can be picked up and translated */ 5494 static void XMLCALL 5495 accumulate_comment(void *userData, const XML_Char *data) { 5496 CharData *storage = (CharData *)userData; 5497 5498 CharData_AppendXMLChars(storage, data, -1); 5499 } 5500 5501 START_TEST(test_utf16_be_comment) { 5502 const char text[] = 5503 /* <!-- Comment A --> */ 5504 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n" 5505 /* <doc/> */ 5506 "\0<\0d\0o\0c\0/\0>"; 5507 const XML_Char *expected = XCS(" Comment A "); 5508 CharData storage; 5509 5510 CharData_Init(&storage); 5511 XML_SetCommentHandler(g_parser, accumulate_comment); 5512 XML_SetUserData(g_parser, &storage); 5513 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5514 == XML_STATUS_ERROR) 5515 xml_failure(g_parser); 5516 CharData_CheckXMLChars(&storage, expected); 5517 } 5518 END_TEST 5519 5520 START_TEST(test_utf16_le_comment) { 5521 const char text[] = 5522 /* <!-- Comment B --> */ 5523 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0" 5524 /* <doc/> */ 5525 "<\0d\0o\0c\0/\0>\0"; 5526 const XML_Char *expected = XCS(" Comment B "); 5527 CharData storage; 5528 5529 CharData_Init(&storage); 5530 XML_SetCommentHandler(g_parser, accumulate_comment); 5531 XML_SetUserData(g_parser, &storage); 5532 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5533 == XML_STATUS_ERROR) 5534 xml_failure(g_parser); 5535 CharData_CheckXMLChars(&storage, expected); 5536 } 5537 END_TEST 5538 5539 /* Test that the unknown encoding handler with map entries that expect 5540 * conversion but no conversion function is faulted 5541 */ 5542 static int XMLCALL 5543 failing_converter(void *data, const char *s) { 5544 UNUSED_P(data); 5545 UNUSED_P(s); 5546 /* Always claim to have failed */ 5547 return -1; 5548 } 5549 5550 static int XMLCALL 5551 prefix_converter(void *data, const char *s) { 5552 UNUSED_P(data); 5553 /* If the first byte is 0xff, raise an error */ 5554 if (s[0] == (char)-1) 5555 return -1; 5556 /* Just add the low bits of the first byte to the second */ 5557 return (s[1] + (s[0] & 0x7f)) & 0x01ff; 5558 } 5559 5560 static int XMLCALL 5561 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) { 5562 int i; 5563 int high_map = -2; /* Assume a 2-byte sequence */ 5564 5565 if (! xcstrcmp(encoding, XCS("invalid-9")) 5566 || ! xcstrcmp(encoding, XCS("ascii-like")) 5567 || ! xcstrcmp(encoding, XCS("invalid-len")) 5568 || ! xcstrcmp(encoding, XCS("invalid-a")) 5569 || ! xcstrcmp(encoding, XCS("invalid-surrogate")) 5570 || ! xcstrcmp(encoding, XCS("invalid-high"))) 5571 high_map = -1; 5572 5573 for (i = 0; i < 128; ++i) 5574 info->map[i] = i; 5575 for (; i < 256; ++i) 5576 info->map[i] = high_map; 5577 5578 /* If required, put an invalid value in the ASCII entries */ 5579 if (! xcstrcmp(encoding, XCS("invalid-9"))) 5580 info->map[9] = 5; 5581 /* If required, have a top-bit set character starts a 5-byte sequence */ 5582 if (! xcstrcmp(encoding, XCS("invalid-len"))) 5583 info->map[0x81] = -5; 5584 /* If required, make a top-bit set character a valid ASCII character */ 5585 if (! xcstrcmp(encoding, XCS("invalid-a"))) 5586 info->map[0x82] = 'a'; 5587 /* If required, give a top-bit set character a forbidden value, 5588 * what would otherwise be the first of a surrogate pair. 5589 */ 5590 if (! xcstrcmp(encoding, XCS("invalid-surrogate"))) 5591 info->map[0x83] = 0xd801; 5592 /* If required, give a top-bit set character too high a value */ 5593 if (! xcstrcmp(encoding, XCS("invalid-high"))) 5594 info->map[0x84] = 0x010101; 5595 5596 info->data = data; 5597 info->release = NULL; 5598 if (! xcstrcmp(encoding, XCS("failing-conv"))) 5599 info->convert = failing_converter; 5600 else if (! xcstrcmp(encoding, XCS("prefix-conv"))) 5601 info->convert = prefix_converter; 5602 else 5603 info->convert = NULL; 5604 return XML_STATUS_OK; 5605 } 5606 5607 START_TEST(test_missing_encoding_conversion_fn) { 5608 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n" 5609 "<doc>\x81</doc>"; 5610 5611 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5612 /* MiscEncodingHandler sets up an encoding with every top-bit-set 5613 * character introducing a two-byte sequence. For this, it 5614 * requires a convert function. The above function call doesn't 5615 * pass one through, so when BadEncodingHandler actually gets 5616 * called it should supply an invalid encoding. 5617 */ 5618 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5619 "Encoding with missing convert() not faulted"); 5620 } 5621 END_TEST 5622 5623 START_TEST(test_failing_encoding_conversion_fn) { 5624 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n" 5625 "<doc>\x81</doc>"; 5626 5627 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5628 /* BadEncodingHandler sets up an encoding with every top-bit-set 5629 * character introducing a two-byte sequence. For this, it 5630 * requires a convert function. The above function call passes 5631 * one that insists all possible sequences are invalid anyway. 5632 */ 5633 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5634 "Encoding with failing convert() not faulted"); 5635 } 5636 END_TEST 5637 5638 /* Test unknown encoding conversions */ 5639 START_TEST(test_unknown_encoding_success) { 5640 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5641 /* Equivalent to <eoc>Hello, world</eoc> */ 5642 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>"; 5643 5644 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5645 run_character_check(text, XCS("Hello, world")); 5646 } 5647 END_TEST 5648 5649 /* Test bad name character in unknown encoding */ 5650 START_TEST(test_unknown_encoding_bad_name) { 5651 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5652 "<\xff\x64oc>Hello, world</\xff\x64oc>"; 5653 5654 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5655 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5656 "Bad name start in unknown encoding not faulted"); 5657 } 5658 END_TEST 5659 5660 /* Test bad mid-name character in unknown encoding */ 5661 START_TEST(test_unknown_encoding_bad_name_2) { 5662 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5663 "<d\xffoc>Hello, world</d\xffoc>"; 5664 5665 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5666 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5667 "Bad name in unknown encoding not faulted"); 5668 } 5669 END_TEST 5670 5671 /* Test element name that is long enough to fill the conversion buffer 5672 * in an unknown encoding, finishing with an encoded character. 5673 */ 5674 START_TEST(test_unknown_encoding_long_name_1) { 5675 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5676 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>" 5677 "Hi" 5678 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"; 5679 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5680 CharData storage; 5681 5682 CharData_Init(&storage); 5683 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5684 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5685 XML_SetUserData(g_parser, &storage); 5686 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5687 == XML_STATUS_ERROR) 5688 xml_failure(g_parser); 5689 CharData_CheckXMLChars(&storage, expected); 5690 } 5691 END_TEST 5692 5693 /* Test element name that is long enough to fill the conversion buffer 5694 * in an unknown encoding, finishing with an simple character. 5695 */ 5696 START_TEST(test_unknown_encoding_long_name_2) { 5697 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5698 "<abcdefghabcdefghabcdefghijklmnop>" 5699 "Hi" 5700 "</abcdefghabcdefghabcdefghijklmnop>"; 5701 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5702 CharData storage; 5703 5704 CharData_Init(&storage); 5705 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5706 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5707 XML_SetUserData(g_parser, &storage); 5708 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5709 == XML_STATUS_ERROR) 5710 xml_failure(g_parser); 5711 CharData_CheckXMLChars(&storage, expected); 5712 } 5713 END_TEST 5714 5715 START_TEST(test_invalid_unknown_encoding) { 5716 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n" 5717 "<doc>Hello world</doc>"; 5718 5719 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5720 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5721 "Invalid unknown encoding not faulted"); 5722 } 5723 END_TEST 5724 5725 START_TEST(test_unknown_ascii_encoding_ok) { 5726 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5727 "<doc>Hello, world</doc>"; 5728 5729 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5730 run_character_check(text, XCS("Hello, world")); 5731 } 5732 END_TEST 5733 5734 START_TEST(test_unknown_ascii_encoding_fail) { 5735 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5736 "<doc>Hello, \x80 world</doc>"; 5737 5738 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5739 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5740 "Invalid character not faulted"); 5741 } 5742 END_TEST 5743 5744 START_TEST(test_unknown_encoding_invalid_length) { 5745 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n" 5746 "<doc>Hello, world</doc>"; 5747 5748 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5749 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5750 "Invalid unknown encoding not faulted"); 5751 } 5752 END_TEST 5753 5754 START_TEST(test_unknown_encoding_invalid_topbit) { 5755 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n" 5756 "<doc>Hello, world</doc>"; 5757 5758 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5759 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5760 "Invalid unknown encoding not faulted"); 5761 } 5762 END_TEST 5763 5764 START_TEST(test_unknown_encoding_invalid_surrogate) { 5765 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n" 5766 "<doc>Hello, \x82 world</doc>"; 5767 5768 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5769 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5770 "Invalid unknown encoding not faulted"); 5771 } 5772 END_TEST 5773 5774 START_TEST(test_unknown_encoding_invalid_high) { 5775 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n" 5776 "<doc>Hello, world</doc>"; 5777 5778 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5779 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5780 "Invalid unknown encoding not faulted"); 5781 } 5782 END_TEST 5783 5784 START_TEST(test_unknown_encoding_invalid_attr_value) { 5785 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5786 "<doc attr='\xff\x30'/>"; 5787 5788 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5789 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5790 "Invalid attribute valid not faulted"); 5791 } 5792 END_TEST 5793 5794 /* Test an external entity parser set to use latin-1 detects UTF-16 5795 * BOMs correctly. 5796 */ 5797 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 }; 5798 5799 typedef struct ExtTest2 { 5800 const char *parse_text; 5801 int parse_len; 5802 const XML_Char *encoding; 5803 CharData *storage; 5804 enum ee_parse_flags flags; 5805 } ExtTest2; 5806 5807 static int XMLCALL 5808 external_entity_loader2(XML_Parser parser, const XML_Char *context, 5809 const XML_Char *base, const XML_Char *systemId, 5810 const XML_Char *publicId) { 5811 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser); 5812 XML_Parser extparser; 5813 5814 UNUSED_P(base); 5815 UNUSED_P(systemId); 5816 UNUSED_P(publicId); 5817 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 5818 if (extparser == NULL) 5819 fail("Coulr not create external entity parser"); 5820 if (test_data->encoding != NULL) { 5821 if (! XML_SetEncoding(extparser, test_data->encoding)) 5822 fail("XML_SetEncoding() ignored for external entity"); 5823 } 5824 if (test_data->flags & EE_PARSE_FULL_BUFFER) { 5825 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 5826 XML_TRUE) 5827 == XML_STATUS_ERROR) { 5828 xml_failure(extparser); 5829 } 5830 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text, 5831 test_data->parse_len, XML_TRUE) 5832 == XML_STATUS_ERROR) { 5833 xml_failure(extparser); 5834 } 5835 5836 XML_ParserFree(extparser); 5837 return XML_STATUS_OK; 5838 } 5839 5840 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */ 5841 static void XMLCALL 5842 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) { 5843 ExtTest2 *test_data = (ExtTest2 *)userData; 5844 accumulate_characters(test_data->storage, s, len); 5845 } 5846 5847 START_TEST(test_ext_entity_latin1_utf16le_bom) { 5848 const char *text = "<!DOCTYPE doc [\n" 5849 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5850 "]>\n" 5851 "<doc>&en;</doc>"; 5852 ExtTest2 test_data 5853 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5854 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5855 * 0x4c = L and 0x20 is a space 5856 */ 5857 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5858 #ifdef XML_UNICODE 5859 const XML_Char *expected = XCS("\x00ff\x00feL "); 5860 #else 5861 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5862 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5863 #endif 5864 CharData storage; 5865 5866 CharData_Init(&storage); 5867 test_data.storage = &storage; 5868 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5869 XML_SetUserData(g_parser, &test_data); 5870 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5871 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5872 == XML_STATUS_ERROR) 5873 xml_failure(g_parser); 5874 CharData_CheckXMLChars(&storage, expected); 5875 } 5876 END_TEST 5877 5878 START_TEST(test_ext_entity_latin1_utf16be_bom) { 5879 const char *text = "<!DOCTYPE doc [\n" 5880 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5881 "]>\n" 5882 "<doc>&en;</doc>"; 5883 ExtTest2 test_data 5884 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5885 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5886 * 0x4c = L and 0x20 is a space 5887 */ 5888 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5889 #ifdef XML_UNICODE 5890 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5891 #else 5892 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5893 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L"); 5894 #endif 5895 CharData storage; 5896 5897 CharData_Init(&storage); 5898 test_data.storage = &storage; 5899 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5900 XML_SetUserData(g_parser, &test_data); 5901 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5902 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5903 == XML_STATUS_ERROR) 5904 xml_failure(g_parser); 5905 CharData_CheckXMLChars(&storage, expected); 5906 } 5907 END_TEST 5908 5909 /* Parsing the full buffer rather than a byte at a time makes a 5910 * difference to the encoding scanning code, so repeat the above tests 5911 * without breaking them down by byte. 5912 */ 5913 START_TEST(test_ext_entity_latin1_utf16le_bom2) { 5914 const char *text = "<!DOCTYPE doc [\n" 5915 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5916 "]>\n" 5917 "<doc>&en;</doc>"; 5918 ExtTest2 test_data 5919 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5920 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5921 * 0x4c = L and 0x20 is a space 5922 */ 5923 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5924 #ifdef XML_UNICODE 5925 const XML_Char *expected = XCS("\x00ff\x00feL "); 5926 #else 5927 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5928 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5929 #endif 5930 CharData storage; 5931 5932 CharData_Init(&storage); 5933 test_data.storage = &storage; 5934 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5935 XML_SetUserData(g_parser, &test_data); 5936 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5937 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5938 == XML_STATUS_ERROR) 5939 xml_failure(g_parser); 5940 CharData_CheckXMLChars(&storage, expected); 5941 } 5942 END_TEST 5943 5944 START_TEST(test_ext_entity_latin1_utf16be_bom2) { 5945 const char *text = "<!DOCTYPE doc [\n" 5946 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5947 "]>\n" 5948 "<doc>&en;</doc>"; 5949 ExtTest2 test_data 5950 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5951 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5952 * 0x4c = L and 0x20 is a space 5953 */ 5954 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5955 #ifdef XML_UNICODE 5956 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5957 #else 5958 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5959 const XML_Char *expected = "\xc3\xbe\xc3\xbf L"; 5960 #endif 5961 CharData storage; 5962 5963 CharData_Init(&storage); 5964 test_data.storage = &storage; 5965 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5966 XML_SetUserData(g_parser, &test_data); 5967 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5968 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5969 == XML_STATUS_ERROR) 5970 xml_failure(g_parser); 5971 CharData_CheckXMLChars(&storage, expected); 5972 } 5973 END_TEST 5974 5975 /* Test little-endian UTF-16 given an explicit big-endian encoding */ 5976 START_TEST(test_ext_entity_utf16_be) { 5977 const char *text = "<!DOCTYPE doc [\n" 5978 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5979 "]>\n" 5980 "<doc>&en;</doc>"; 5981 ExtTest2 test_data 5982 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE}; 5983 #ifdef XML_UNICODE 5984 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 5985 #else 5986 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 5987 "\xe6\x94\x80" /* U+6500 */ 5988 "\xe2\xbc\x80" /* U+2F00 */ 5989 "\xe3\xb8\x80"); /* U+3E00 */ 5990 #endif 5991 CharData storage; 5992 5993 CharData_Init(&storage); 5994 test_data.storage = &storage; 5995 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5996 XML_SetUserData(g_parser, &test_data); 5997 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5998 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5999 == XML_STATUS_ERROR) 6000 xml_failure(g_parser); 6001 CharData_CheckXMLChars(&storage, expected); 6002 } 6003 END_TEST 6004 6005 /* Test big-endian UTF-16 given an explicit little-endian encoding */ 6006 START_TEST(test_ext_entity_utf16_le) { 6007 const char *text = "<!DOCTYPE doc [\n" 6008 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 6009 "]>\n" 6010 "<doc>&en;</doc>"; 6011 ExtTest2 test_data 6012 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE}; 6013 #ifdef XML_UNICODE 6014 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 6015 #else 6016 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 6017 "\xe6\x94\x80" /* U+6500 */ 6018 "\xe2\xbc\x80" /* U+2F00 */ 6019 "\xe3\xb8\x80"); /* U+3E00 */ 6020 #endif 6021 CharData storage; 6022 6023 CharData_Init(&storage); 6024 test_data.storage = &storage; 6025 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6026 XML_SetUserData(g_parser, &test_data); 6027 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6028 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6029 == XML_STATUS_ERROR) 6030 xml_failure(g_parser); 6031 CharData_CheckXMLChars(&storage, expected); 6032 } 6033 END_TEST 6034 6035 /* Test little-endian UTF-16 given no explicit encoding. 6036 * The existing default encoding (UTF-8) is assumed to hold without a 6037 * BOM to contradict it, so the entity value will in fact provoke an 6038 * error because 0x00 is not a valid XML character. We parse the 6039 * whole buffer in one go rather than feeding it in byte by byte to 6040 * exercise different code paths in the initial scanning routines. 6041 */ 6042 typedef struct ExtFaults2 { 6043 const char *parse_text; 6044 int parse_len; 6045 const char *fail_text; 6046 const XML_Char *encoding; 6047 enum XML_Error error; 6048 } ExtFaults2; 6049 6050 static int XMLCALL 6051 external_entity_faulter2(XML_Parser parser, const XML_Char *context, 6052 const XML_Char *base, const XML_Char *systemId, 6053 const XML_Char *publicId) { 6054 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser); 6055 XML_Parser extparser; 6056 6057 UNUSED_P(base); 6058 UNUSED_P(systemId); 6059 UNUSED_P(publicId); 6060 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 6061 if (extparser == NULL) 6062 fail("Could not create external entity parser"); 6063 if (test_data->encoding != NULL) { 6064 if (! XML_SetEncoding(extparser, test_data->encoding)) 6065 fail("XML_SetEncoding() ignored for external entity"); 6066 } 6067 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 6068 XML_TRUE) 6069 != XML_STATUS_ERROR) 6070 fail(test_data->fail_text); 6071 if (XML_GetErrorCode(extparser) != test_data->error) 6072 xml_failure(extparser); 6073 6074 XML_ParserFree(extparser); 6075 return XML_STATUS_ERROR; 6076 } 6077 6078 START_TEST(test_ext_entity_utf16_unknown) { 6079 const char *text = "<!DOCTYPE doc [\n" 6080 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 6081 "]>\n" 6082 "<doc>&en;</doc>"; 6083 ExtFaults2 test_data 6084 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL, 6085 XML_ERROR_INVALID_TOKEN}; 6086 6087 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2); 6088 XML_SetUserData(g_parser, &test_data); 6089 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 6090 "Invalid character should not have been accepted"); 6091 } 6092 END_TEST 6093 6094 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */ 6095 START_TEST(test_ext_entity_utf8_non_bom) { 6096 const char *text = "<!DOCTYPE doc [\n" 6097 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 6098 "]>\n" 6099 "<doc>&en;</doc>"; 6100 ExtTest2 test_data 6101 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */ 6102 3, NULL, NULL, EE_PARSE_NONE}; 6103 #ifdef XML_UNICODE 6104 const XML_Char *expected = XCS("\xfec0"); 6105 #else 6106 const XML_Char *expected = XCS("\xef\xbb\x80"); 6107 #endif 6108 CharData storage; 6109 6110 CharData_Init(&storage); 6111 test_data.storage = &storage; 6112 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6113 XML_SetUserData(g_parser, &test_data); 6114 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6115 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6116 == XML_STATUS_ERROR) 6117 xml_failure(g_parser); 6118 CharData_CheckXMLChars(&storage, expected); 6119 } 6120 END_TEST 6121 6122 /* Test that UTF-8 in a CDATA section is correctly passed through */ 6123 START_TEST(test_utf8_in_cdata_section) { 6124 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>"; 6125 #ifdef XML_UNICODE 6126 const XML_Char *expected = XCS("one \x00e9 two"); 6127 #else 6128 const XML_Char *expected = XCS("one \xc3\xa9 two"); 6129 #endif 6130 6131 run_character_check(text, expected); 6132 } 6133 END_TEST 6134 6135 /* Test that little-endian UTF-16 in a CDATA section is handled */ 6136 START_TEST(test_utf8_in_cdata_section_2) { 6137 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>"; 6138 #ifdef XML_UNICODE 6139 const XML_Char *expected = XCS("\x00e9]\x00e9two"); 6140 #else 6141 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two"); 6142 #endif 6143 6144 run_character_check(text, expected); 6145 } 6146 END_TEST 6147 6148 START_TEST(test_utf8_in_start_tags) { 6149 struct test_case { 6150 bool goodName; 6151 bool goodNameStart; 6152 const char *tagName; 6153 }; 6154 6155 // The idea with the tests below is this: 6156 // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences 6157 // go to isNever and are hence not a concern. 6158 // 6159 // We start with a character that is a valid name character 6160 // (or even name-start character, see XML 1.0r4 spec) and then we flip 6161 // single bits at places where (1) the result leaves the UTF-8 encoding space 6162 // and (2) we stay in the same n-byte sequence family. 6163 // 6164 // The flipped bits are highlighted in angle brackets in comments, 6165 // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped 6166 // the most significant bit to 1 to leave UTF-8 encoding space. 6167 struct test_case cases[] = { 6168 // 1-byte UTF-8: [0xxx xxxx] 6169 {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':' 6170 {false, false, "\xBA"}, // [<1>011 1010] 6171 {true, false, "\x39"}, // [0011 1001] = ASCII nine '9' 6172 {false, false, "\xB9"}, // [<1>011 1001] 6173 6174 // 2-byte UTF-8: [110x xxxx] [10xx xxxx] 6175 {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] = 6176 // Arabic small waw U+06E5 6177 {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101] 6178 {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101] 6179 {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101] 6180 {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] = 6181 // combining char U+0301 6182 {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001] 6183 {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001] 6184 {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001] 6185 6186 // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx] 6187 {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] = 6188 // Devanagari Letter A U+0905 6189 {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101] 6190 {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101] 6191 {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101] 6192 {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101] 6193 {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101] 6194 {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] = 6195 // combining char U+0901 6196 {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001] 6197 {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001] 6198 {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001] 6199 {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001] 6200 {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001] 6201 }; 6202 const bool atNameStart[] = {true, false}; 6203 6204 size_t i = 0; 6205 char doc[1024]; 6206 size_t failCount = 0; 6207 6208 for (; i < sizeof(cases) / sizeof(cases[0]); i++) { 6209 size_t j = 0; 6210 for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) { 6211 const bool expectedSuccess 6212 = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName; 6213 sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName); 6214 XML_Parser parser = XML_ParserCreate(NULL); 6215 6216 const enum XML_Status status 6217 = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE); 6218 6219 bool success = true; 6220 if ((status == XML_STATUS_OK) != expectedSuccess) { 6221 success = false; 6222 } 6223 if ((status == XML_STATUS_ERROR) 6224 && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) { 6225 success = false; 6226 } 6227 6228 if (! success) { 6229 fprintf( 6230 stderr, 6231 "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n", 6232 (unsigned)i + 1u, atNameStart[j] ? " " : "not ", 6233 (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser)); 6234 failCount++; 6235 } 6236 6237 XML_ParserFree(parser); 6238 } 6239 } 6240 6241 if (failCount > 0) { 6242 fail("UTF-8 regression detected"); 6243 } 6244 } 6245 END_TEST 6246 6247 /* Test trailing spaces in elements are accepted */ 6248 static void XMLCALL 6249 record_element_end_handler(void *userData, const XML_Char *name) { 6250 CharData *storage = (CharData *)userData; 6251 6252 CharData_AppendXMLChars(storage, XCS("/"), 1); 6253 CharData_AppendXMLChars(storage, name, -1); 6254 } 6255 6256 START_TEST(test_trailing_spaces_in_elements) { 6257 const char *text = "<doc >Hi</doc >"; 6258 const XML_Char *expected = XCS("doc/doc"); 6259 CharData storage; 6260 6261 CharData_Init(&storage); 6262 XML_SetElementHandler(g_parser, record_element_start_handler, 6263 record_element_end_handler); 6264 XML_SetUserData(g_parser, &storage); 6265 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6266 == XML_STATUS_ERROR) 6267 xml_failure(g_parser); 6268 CharData_CheckXMLChars(&storage, expected); 6269 } 6270 END_TEST 6271 6272 START_TEST(test_utf16_attribute) { 6273 const char text[] = 6274 /* <d {KHO KHWAI}{CHO CHAN}='a'/> 6275 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6276 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6277 */ 6278 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0"; 6279 const XML_Char *expected = XCS("a"); 6280 CharData storage; 6281 6282 CharData_Init(&storage); 6283 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6284 XML_SetUserData(g_parser, &storage); 6285 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6286 == XML_STATUS_ERROR) 6287 xml_failure(g_parser); 6288 CharData_CheckXMLChars(&storage, expected); 6289 } 6290 END_TEST 6291 6292 START_TEST(test_utf16_second_attr) { 6293 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/> 6294 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6295 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6296 */ 6297 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0" 6298 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0"; 6299 const XML_Char *expected = XCS("1"); 6300 CharData storage; 6301 6302 CharData_Init(&storage); 6303 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6304 XML_SetUserData(g_parser, &storage); 6305 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6306 == XML_STATUS_ERROR) 6307 xml_failure(g_parser); 6308 CharData_CheckXMLChars(&storage, expected); 6309 } 6310 END_TEST 6311 6312 START_TEST(test_attr_after_solidus) { 6313 const char *text = "<doc attr1='a' / attr2='b'>"; 6314 6315 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted"); 6316 } 6317 END_TEST 6318 6319 static void XMLCALL 6320 accumulate_entity_decl(void *userData, const XML_Char *entityName, 6321 int is_parameter_entity, const XML_Char *value, 6322 int value_length, const XML_Char *base, 6323 const XML_Char *systemId, const XML_Char *publicId, 6324 const XML_Char *notationName) { 6325 CharData *storage = (CharData *)userData; 6326 6327 UNUSED_P(is_parameter_entity); 6328 UNUSED_P(base); 6329 UNUSED_P(systemId); 6330 UNUSED_P(publicId); 6331 UNUSED_P(notationName); 6332 CharData_AppendXMLChars(storage, entityName, -1); 6333 CharData_AppendXMLChars(storage, XCS("="), 1); 6334 CharData_AppendXMLChars(storage, value, value_length); 6335 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6336 } 6337 6338 START_TEST(test_utf16_pe) { 6339 /* <!DOCTYPE doc [ 6340 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'> 6341 * %{KHO KHWAI}{CHO CHAN}; 6342 * ]> 6343 * <doc></doc> 6344 * 6345 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6346 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6347 */ 6348 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 6349 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 " 6350 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 " 6351 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n" 6352 "\0%\x0e\x04\x0e\x08\0;\0\n" 6353 "\0]\0>\0\n" 6354 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>"; 6355 #ifdef XML_UNICODE 6356 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n"); 6357 #else 6358 const XML_Char *expected 6359 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n"); 6360 #endif 6361 CharData storage; 6362 6363 CharData_Init(&storage); 6364 XML_SetUserData(g_parser, &storage); 6365 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl); 6366 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6367 == XML_STATUS_ERROR) 6368 xml_failure(g_parser); 6369 CharData_CheckXMLChars(&storage, expected); 6370 } 6371 END_TEST 6372 6373 /* Test that duff attribute description keywords are rejected */ 6374 START_TEST(test_bad_attr_desc_keyword) { 6375 const char *text = "<!DOCTYPE doc [\n" 6376 " <!ATTLIST doc attr CDATA #!IMPLIED>\n" 6377 "]>\n" 6378 "<doc />"; 6379 6380 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6381 "Bad keyword !IMPLIED not faulted"); 6382 } 6383 END_TEST 6384 6385 /* Test that an invalid attribute description keyword consisting of 6386 * UTF-16 characters with their top bytes non-zero are correctly 6387 * faulted 6388 */ 6389 START_TEST(test_bad_attr_desc_keyword_utf16) { 6390 /* <!DOCTYPE d [ 6391 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}> 6392 * ]><d/> 6393 * 6394 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6395 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6396 */ 6397 const char text[] 6398 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6399 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 " 6400 "\0#\x0e\x04\x0e\x08\0>\0\n" 6401 "\0]\0>\0<\0d\0/\0>"; 6402 6403 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6404 != XML_STATUS_ERROR) 6405 fail("Invalid UTF16 attribute keyword not faulted"); 6406 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6407 xml_failure(g_parser); 6408 } 6409 END_TEST 6410 6411 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this 6412 * using prefix-encoding (see above) to trigger specific code paths 6413 */ 6414 START_TEST(test_bad_doctype) { 6415 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 6416 "<!DOCTYPE doc [ \x80\x44 ]><doc/>"; 6417 6418 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6419 expect_failure(text, XML_ERROR_SYNTAX, 6420 "Invalid bytes in DOCTYPE not faulted"); 6421 } 6422 END_TEST 6423 6424 START_TEST(test_bad_doctype_utf8) { 6425 const char *text = "<!DOCTYPE \xDB\x25" 6426 "doc><doc/>"; // [1101 1011] [<0>010 0101] 6427 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6428 "Invalid UTF-8 in DOCTYPE not faulted"); 6429 } 6430 END_TEST 6431 6432 START_TEST(test_bad_doctype_utf16) { 6433 const char text[] = 6434 /* <!DOCTYPE doc [ \x06f2 ]><doc/> 6435 * 6436 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number 6437 * (name character) but not a valid letter (name start character) 6438 */ 6439 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 " 6440 "\x06\xf2" 6441 "\0 \0]\0>\0<\0d\0o\0c\0/\0>"; 6442 6443 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6444 != XML_STATUS_ERROR) 6445 fail("Invalid bytes in DOCTYPE not faulted"); 6446 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6447 xml_failure(g_parser); 6448 } 6449 END_TEST 6450 6451 START_TEST(test_bad_doctype_plus) { 6452 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n" 6453 "<1+>&foo;</1+>"; 6454 6455 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6456 "'+' in document name not faulted"); 6457 } 6458 END_TEST 6459 6460 START_TEST(test_bad_doctype_star) { 6461 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n" 6462 "<1*>&foo;</1*>"; 6463 6464 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6465 "'*' in document name not faulted"); 6466 } 6467 END_TEST 6468 6469 START_TEST(test_bad_doctype_query) { 6470 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n" 6471 "<1?>&foo;</1?>"; 6472 6473 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6474 "'?' in document name not faulted"); 6475 } 6476 END_TEST 6477 6478 START_TEST(test_unknown_encoding_bad_ignore) { 6479 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>" 6480 "<!DOCTYPE doc SYSTEM 'foo'>" 6481 "<doc><e>&entity;</e></doc>"; 6482 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>", 6483 "Invalid character not faulted", XCS("prefix-conv"), 6484 XML_ERROR_INVALID_TOKEN}; 6485 6486 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6487 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6488 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 6489 XML_SetUserData(g_parser, &fault); 6490 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 6491 "Bad IGNORE section with unknown encoding not failed"); 6492 } 6493 END_TEST 6494 6495 START_TEST(test_entity_in_utf16_be_attr) { 6496 const char text[] = 6497 /* <e a='ä ä'></e> */ 6498 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 " 6499 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>"; 6500 #ifdef XML_UNICODE 6501 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6502 #else 6503 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6504 #endif 6505 CharData storage; 6506 6507 CharData_Init(&storage); 6508 XML_SetUserData(g_parser, &storage); 6509 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6510 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6511 == XML_STATUS_ERROR) 6512 xml_failure(g_parser); 6513 CharData_CheckXMLChars(&storage, expected); 6514 } 6515 END_TEST 6516 6517 START_TEST(test_entity_in_utf16_le_attr) { 6518 const char text[] = 6519 /* <e a='ä ä'></e> */ 6520 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0" 6521 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0"; 6522 #ifdef XML_UNICODE 6523 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6524 #else 6525 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6526 #endif 6527 CharData storage; 6528 6529 CharData_Init(&storage); 6530 XML_SetUserData(g_parser, &storage); 6531 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6532 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6533 == XML_STATUS_ERROR) 6534 xml_failure(g_parser); 6535 CharData_CheckXMLChars(&storage, expected); 6536 } 6537 END_TEST 6538 6539 START_TEST(test_entity_public_utf16_be) { 6540 const char text[] = 6541 /* <!DOCTYPE d [ */ 6542 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6543 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6544 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 " 6545 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n" 6546 /* %e; */ 6547 "\0%\0e\0;\0\n" 6548 /* ]> */ 6549 "\0]\0>\0\n" 6550 /* <d>&j;</d> */ 6551 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>"; 6552 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6553 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>", 6554 34, NULL, NULL, EE_PARSE_NONE}; 6555 const XML_Char *expected = XCS("baz"); 6556 CharData storage; 6557 6558 CharData_Init(&storage); 6559 test_data.storage = &storage; 6560 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6561 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6562 XML_SetUserData(g_parser, &test_data); 6563 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6564 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6565 == XML_STATUS_ERROR) 6566 xml_failure(g_parser); 6567 CharData_CheckXMLChars(&storage, expected); 6568 } 6569 END_TEST 6570 6571 START_TEST(test_entity_public_utf16_le) { 6572 const char text[] = 6573 /* <!DOCTYPE d [ */ 6574 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0" 6575 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6576 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0" 6577 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0" 6578 /* %e; */ 6579 "%\0e\0;\0\n\0" 6580 /* ]> */ 6581 "]\0>\0\n\0" 6582 /* <d>&j;</d> */ 6583 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0"; 6584 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6585 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0", 6586 34, NULL, NULL, EE_PARSE_NONE}; 6587 const XML_Char *expected = XCS("baz"); 6588 CharData storage; 6589 6590 CharData_Init(&storage); 6591 test_data.storage = &storage; 6592 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6593 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6594 XML_SetUserData(g_parser, &test_data); 6595 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6596 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6597 == XML_STATUS_ERROR) 6598 xml_failure(g_parser); 6599 CharData_CheckXMLChars(&storage, expected); 6600 } 6601 END_TEST 6602 6603 /* Test that a doctype with neither an internal nor external subset is 6604 * faulted 6605 */ 6606 START_TEST(test_short_doctype) { 6607 const char *text = "<!DOCTYPE doc></doc>"; 6608 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6609 "DOCTYPE without subset not rejected"); 6610 } 6611 END_TEST 6612 6613 START_TEST(test_short_doctype_2) { 6614 const char *text = "<!DOCTYPE doc PUBLIC></doc>"; 6615 expect_failure(text, XML_ERROR_SYNTAX, 6616 "DOCTYPE without Public ID not rejected"); 6617 } 6618 END_TEST 6619 6620 START_TEST(test_short_doctype_3) { 6621 const char *text = "<!DOCTYPE doc SYSTEM></doc>"; 6622 expect_failure(text, XML_ERROR_SYNTAX, 6623 "DOCTYPE without System ID not rejected"); 6624 } 6625 END_TEST 6626 6627 START_TEST(test_long_doctype) { 6628 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>"; 6629 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected"); 6630 } 6631 END_TEST 6632 6633 START_TEST(test_bad_entity) { 6634 const char *text = "<!DOCTYPE doc [\n" 6635 " <!ENTITY foo PUBLIC>\n" 6636 "]>\n" 6637 "<doc/>"; 6638 expect_failure(text, XML_ERROR_SYNTAX, 6639 "ENTITY without Public ID is not rejected"); 6640 } 6641 END_TEST 6642 6643 /* Test unquoted value is faulted */ 6644 START_TEST(test_bad_entity_2) { 6645 const char *text = "<!DOCTYPE doc [\n" 6646 " <!ENTITY % foo bar>\n" 6647 "]>\n" 6648 "<doc/>"; 6649 expect_failure(text, XML_ERROR_SYNTAX, 6650 "ENTITY without Public ID is not rejected"); 6651 } 6652 END_TEST 6653 6654 START_TEST(test_bad_entity_3) { 6655 const char *text = "<!DOCTYPE doc [\n" 6656 " <!ENTITY % foo PUBLIC>\n" 6657 "]>\n" 6658 "<doc/>"; 6659 expect_failure(text, XML_ERROR_SYNTAX, 6660 "Parameter ENTITY without Public ID is not rejected"); 6661 } 6662 END_TEST 6663 6664 START_TEST(test_bad_entity_4) { 6665 const char *text = "<!DOCTYPE doc [\n" 6666 " <!ENTITY % foo SYSTEM>\n" 6667 "]>\n" 6668 "<doc/>"; 6669 expect_failure(text, XML_ERROR_SYNTAX, 6670 "Parameter ENTITY without Public ID is not rejected"); 6671 } 6672 END_TEST 6673 6674 START_TEST(test_bad_notation) { 6675 const char *text = "<!DOCTYPE doc [\n" 6676 " <!NOTATION n SYSTEM>\n" 6677 "]>\n" 6678 "<doc/>"; 6679 expect_failure(text, XML_ERROR_SYNTAX, 6680 "Notation without System ID is not rejected"); 6681 } 6682 END_TEST 6683 6684 /* Test for issue #11, wrongly suppressed default handler */ 6685 typedef struct default_check { 6686 const XML_Char *expected; 6687 const int expectedLen; 6688 XML_Bool seen; 6689 } DefaultCheck; 6690 6691 static void XMLCALL 6692 checking_default_handler(void *userData, const XML_Char *s, int len) { 6693 DefaultCheck *data = (DefaultCheck *)userData; 6694 int i; 6695 6696 for (i = 0; data[i].expected != NULL; i++) { 6697 if (data[i].expectedLen == len 6698 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) { 6699 data[i].seen = XML_TRUE; 6700 break; 6701 } 6702 } 6703 } 6704 6705 START_TEST(test_default_doctype_handler) { 6706 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n" 6707 " <!ENTITY foo 'bar'>\n" 6708 "]>\n" 6709 "<doc>&foo;</doc>"; 6710 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE}, 6711 {XCS("'test.dtd'"), 10, XML_FALSE}, 6712 {NULL, 0, XML_FALSE}}; 6713 int i; 6714 6715 XML_SetUserData(g_parser, &test_data); 6716 XML_SetDefaultHandler(g_parser, checking_default_handler); 6717 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 6718 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6719 == XML_STATUS_ERROR) 6720 xml_failure(g_parser); 6721 for (i = 0; test_data[i].expected != NULL; i++) 6722 if (! test_data[i].seen) 6723 fail("Default handler not run for public !DOCTYPE"); 6724 } 6725 END_TEST 6726 6727 START_TEST(test_empty_element_abort) { 6728 const char *text = "<abort/>"; 6729 6730 XML_SetStartElementHandler(g_parser, start_element_suspender); 6731 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6732 != XML_STATUS_ERROR) 6733 fail("Expected to error on abort"); 6734 } 6735 END_TEST 6736 6737 /* 6738 * Namespaces tests. 6739 */ 6740 6741 static void 6742 namespace_setup(void) { 6743 g_parser = XML_ParserCreateNS(NULL, XCS(' ')); 6744 if (g_parser == NULL) 6745 fail("Parser not created."); 6746 } 6747 6748 static void 6749 namespace_teardown(void) { 6750 basic_teardown(); 6751 } 6752 6753 /* Check that an element name and attribute name match the expected values. 6754 The expected values are passed as an array reference of string pointers 6755 provided as the userData argument; the first is the expected 6756 element name, and the second is the expected attribute name. 6757 */ 6758 static int triplet_start_flag = XML_FALSE; 6759 static int triplet_end_flag = XML_FALSE; 6760 6761 static void XMLCALL 6762 triplet_start_checker(void *userData, const XML_Char *name, 6763 const XML_Char **atts) { 6764 XML_Char **elemstr = (XML_Char **)userData; 6765 char buffer[1024]; 6766 if (xcstrcmp(elemstr[0], name) != 0) { 6767 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name); 6768 fail(buffer); 6769 } 6770 if (xcstrcmp(elemstr[1], atts[0]) != 0) { 6771 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]); 6772 fail(buffer); 6773 } 6774 triplet_start_flag = XML_TRUE; 6775 } 6776 6777 /* Check that the element name passed to the end-element handler matches 6778 the expected value. The expected value is passed as the first element 6779 in an array of strings passed as the userData argument. 6780 */ 6781 static void XMLCALL 6782 triplet_end_checker(void *userData, const XML_Char *name) { 6783 XML_Char **elemstr = (XML_Char **)userData; 6784 if (xcstrcmp(elemstr[0], name) != 0) { 6785 char buffer[1024]; 6786 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name); 6787 fail(buffer); 6788 } 6789 triplet_end_flag = XML_TRUE; 6790 } 6791 6792 START_TEST(test_return_ns_triplet) { 6793 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 6794 " xmlns:bar='http://example.org/'>"; 6795 const char *epilog = "</foo:e>"; 6796 const XML_Char *elemstr[] 6797 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")}; 6798 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6799 XML_SetUserData(g_parser, (void *)elemstr); 6800 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 6801 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler, 6802 dummy_end_namespace_decl_handler); 6803 triplet_start_flag = XML_FALSE; 6804 triplet_end_flag = XML_FALSE; 6805 dummy_handler_flags = 0; 6806 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 6807 == XML_STATUS_ERROR) 6808 xml_failure(g_parser); 6809 if (! triplet_start_flag) 6810 fail("triplet_start_checker not invoked"); 6811 /* Check that unsetting "return triplets" fails while still parsing */ 6812 XML_SetReturnNSTriplet(g_parser, XML_FALSE); 6813 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 6814 == XML_STATUS_ERROR) 6815 xml_failure(g_parser); 6816 if (! triplet_end_flag) 6817 fail("triplet_end_checker not invoked"); 6818 if (dummy_handler_flags 6819 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG)) 6820 fail("Namespace handlers not called"); 6821 } 6822 END_TEST 6823 6824 static void XMLCALL 6825 overwrite_start_checker(void *userData, const XML_Char *name, 6826 const XML_Char **atts) { 6827 CharData *storage = (CharData *)userData; 6828 CharData_AppendXMLChars(storage, XCS("start "), 6); 6829 CharData_AppendXMLChars(storage, name, -1); 6830 while (*atts != NULL) { 6831 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11); 6832 CharData_AppendXMLChars(storage, *atts, -1); 6833 atts += 2; 6834 } 6835 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6836 } 6837 6838 static void XMLCALL 6839 overwrite_end_checker(void *userData, const XML_Char *name) { 6840 CharData *storage = (CharData *)userData; 6841 CharData_AppendXMLChars(storage, XCS("end "), 4); 6842 CharData_AppendXMLChars(storage, name, -1); 6843 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6844 } 6845 6846 static void 6847 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) { 6848 CharData storage; 6849 CharData_Init(&storage); 6850 XML_SetUserData(g_parser, &storage); 6851 XML_SetElementHandler(g_parser, overwrite_start_checker, 6852 overwrite_end_checker); 6853 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6854 == XML_STATUS_ERROR) 6855 xml_failure(g_parser); 6856 CharData_CheckXMLChars(&storage, result); 6857 } 6858 6859 /* Regression test for SF bug #566334. */ 6860 START_TEST(test_ns_tagname_overwrite) { 6861 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6862 " <n:f n:attr='foo'/>\n" 6863 " <n:g n:attr2='bar'/>\n" 6864 "</n:e>"; 6865 const XML_Char *result = XCS("start http://example.org/ e\n") 6866 XCS("start http://example.org/ f\n") 6867 XCS("attribute http://example.org/ attr\n") 6868 XCS("end http://example.org/ f\n") 6869 XCS("start http://example.org/ g\n") 6870 XCS("attribute http://example.org/ attr2\n") 6871 XCS("end http://example.org/ g\n") 6872 XCS("end http://example.org/ e\n"); 6873 run_ns_tagname_overwrite_test(text, result); 6874 } 6875 END_TEST 6876 6877 /* Regression test for SF bug #566334. */ 6878 START_TEST(test_ns_tagname_overwrite_triplet) { 6879 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6880 " <n:f n:attr='foo'/>\n" 6881 " <n:g n:attr2='bar'/>\n" 6882 "</n:e>"; 6883 const XML_Char *result = XCS("start http://example.org/ e n\n") 6884 XCS("start http://example.org/ f n\n") 6885 XCS("attribute http://example.org/ attr n\n") 6886 XCS("end http://example.org/ f n\n") 6887 XCS("start http://example.org/ g n\n") 6888 XCS("attribute http://example.org/ attr2 n\n") 6889 XCS("end http://example.org/ g n\n") 6890 XCS("end http://example.org/ e n\n"); 6891 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6892 run_ns_tagname_overwrite_test(text, result); 6893 } 6894 END_TEST 6895 6896 /* Regression test for SF bug #620343. */ 6897 static void XMLCALL 6898 start_element_fail(void *userData, const XML_Char *name, 6899 const XML_Char **atts) { 6900 UNUSED_P(userData); 6901 UNUSED_P(name); 6902 UNUSED_P(atts); 6903 6904 /* We should never get here. */ 6905 fail("should never reach start_element_fail()"); 6906 } 6907 6908 static void XMLCALL 6909 start_ns_clearing_start_element(void *userData, const XML_Char *prefix, 6910 const XML_Char *uri) { 6911 UNUSED_P(prefix); 6912 UNUSED_P(uri); 6913 XML_SetStartElementHandler((XML_Parser)userData, NULL); 6914 } 6915 6916 START_TEST(test_start_ns_clears_start_element) { 6917 /* This needs to use separate start/end tags; using the empty tag 6918 syntax doesn't cause the problematic path through Expat to be 6919 taken. 6920 */ 6921 const char *text = "<e xmlns='http://example.org/'></e>"; 6922 6923 XML_SetStartElementHandler(g_parser, start_element_fail); 6924 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element); 6925 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 6926 XML_UseParserAsHandlerArg(g_parser); 6927 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6928 == XML_STATUS_ERROR) 6929 xml_failure(g_parser); 6930 } 6931 END_TEST 6932 6933 /* Regression test for SF bug #616863. */ 6934 static int XMLCALL 6935 external_entity_handler(XML_Parser parser, const XML_Char *context, 6936 const XML_Char *base, const XML_Char *systemId, 6937 const XML_Char *publicId) { 6938 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser); 6939 const char *text; 6940 XML_Parser p2; 6941 6942 UNUSED_P(base); 6943 UNUSED_P(systemId); 6944 UNUSED_P(publicId); 6945 if (callno == 1) 6946 text = ("<!ELEMENT doc (e+)>\n" 6947 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 6948 "<!ELEMENT e EMPTY>\n"); 6949 else 6950 text = ("<?xml version='1.0' encoding='us-ascii'?>" 6951 "<e/>"); 6952 6953 XML_SetUserData(parser, (void *)callno); 6954 p2 = XML_ExternalEntityParserCreate(parser, context, NULL); 6955 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE) 6956 == XML_STATUS_ERROR) { 6957 xml_failure(p2); 6958 return XML_STATUS_ERROR; 6959 } 6960 XML_ParserFree(p2); 6961 return XML_STATUS_OK; 6962 } 6963 6964 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) { 6965 const char *text = "<?xml version='1.0'?>\n" 6966 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 6967 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 6968 "]>\n" 6969 "<doc xmlns='http://example.org/ns1'>\n" 6970 "&en;\n" 6971 "</doc>"; 6972 6973 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6974 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler); 6975 /* We actually need to set this handler to tickle this bug. */ 6976 XML_SetStartElementHandler(g_parser, dummy_start_element); 6977 XML_SetUserData(g_parser, NULL); 6978 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6979 == XML_STATUS_ERROR) 6980 xml_failure(g_parser); 6981 } 6982 END_TEST 6983 6984 /* Regression test #1 for SF bug #673791. */ 6985 START_TEST(test_ns_prefix_with_empty_uri_1) { 6986 const char *text = "<doc xmlns:prefix='http://example.org/'>\n" 6987 " <e xmlns:prefix=''/>\n" 6988 "</doc>"; 6989 6990 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6991 "Did not report re-setting namespace" 6992 " URI with prefix to ''."); 6993 } 6994 END_TEST 6995 6996 /* Regression test #2 for SF bug #673791. */ 6997 START_TEST(test_ns_prefix_with_empty_uri_2) { 6998 const char *text = "<?xml version='1.0'?>\n" 6999 "<docelem xmlns:pre=''/>"; 7000 7001 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 7002 "Did not report setting namespace URI with prefix to ''."); 7003 } 7004 END_TEST 7005 7006 /* Regression test #3 for SF bug #673791. */ 7007 START_TEST(test_ns_prefix_with_empty_uri_3) { 7008 const char *text = "<!DOCTYPE doc [\n" 7009 " <!ELEMENT doc EMPTY>\n" 7010 " <!ATTLIST doc\n" 7011 " xmlns:prefix CDATA ''>\n" 7012 "]>\n" 7013 "<doc/>"; 7014 7015 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 7016 "Didn't report attr default setting NS w/ prefix to ''."); 7017 } 7018 END_TEST 7019 7020 /* Regression test #4 for SF bug #673791. */ 7021 START_TEST(test_ns_prefix_with_empty_uri_4) { 7022 const char *text = "<!DOCTYPE doc [\n" 7023 " <!ELEMENT prefix:doc EMPTY>\n" 7024 " <!ATTLIST prefix:doc\n" 7025 " xmlns:prefix CDATA 'http://example.org/'>\n" 7026 "]>\n" 7027 "<prefix:doc/>"; 7028 /* Packaged info expected by the end element handler; 7029 the weird structuring lets us re-use the triplet_end_checker() 7030 function also used for another test. */ 7031 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")}; 7032 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 7033 XML_SetUserData(g_parser, (void *)elemstr); 7034 XML_SetEndElementHandler(g_parser, triplet_end_checker); 7035 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7036 == XML_STATUS_ERROR) 7037 xml_failure(g_parser); 7038 } 7039 END_TEST 7040 7041 /* Test with non-xmlns prefix */ 7042 START_TEST(test_ns_unbound_prefix) { 7043 const char *text = "<!DOCTYPE doc [\n" 7044 " <!ELEMENT prefix:doc EMPTY>\n" 7045 " <!ATTLIST prefix:doc\n" 7046 " notxmlns:prefix CDATA 'http://example.org/'>\n" 7047 "]>\n" 7048 "<prefix:doc/>"; 7049 7050 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7051 != XML_STATUS_ERROR) 7052 fail("Unbound prefix incorrectly passed"); 7053 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX) 7054 xml_failure(g_parser); 7055 } 7056 END_TEST 7057 7058 START_TEST(test_ns_default_with_empty_uri) { 7059 const char *text = "<doc xmlns='http://example.org/'>\n" 7060 " <e xmlns=''/>\n" 7061 "</doc>"; 7062 /* Add some handlers to exercise extra code paths */ 7063 XML_SetStartNamespaceDeclHandler(g_parser, 7064 dummy_start_namespace_decl_handler); 7065 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 7066 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7067 == XML_STATUS_ERROR) 7068 xml_failure(g_parser); 7069 } 7070 END_TEST 7071 7072 /* Regression test for SF bug #692964: two prefixes for one namespace. */ 7073 START_TEST(test_ns_duplicate_attrs_diff_prefixes) { 7074 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7075 " xmlns:b='http://example.org/a'\n" 7076 " a:a='v' b:a='v' />"; 7077 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE, 7078 "did not report multiple attributes with same URI+name"); 7079 } 7080 END_TEST 7081 7082 START_TEST(test_ns_duplicate_hashes) { 7083 /* The hash of an attribute is calculated as the hash of its URI 7084 * concatenated with a space followed by its name (after the 7085 * colon). We wish to generate attributes with the same hash 7086 * value modulo the attribute table size so that we can check that 7087 * the attribute hash table works correctly. The attribute hash 7088 * table size will be the smallest power of two greater than the 7089 * number of attributes, but at least eight. There is 7090 * unfortunately no programmatic way of getting the hash or the 7091 * table size at user level, but the test code coverage percentage 7092 * will drop if the hashes cease to point to the same row. 7093 * 7094 * The cunning plan is to have few enough attributes to have a 7095 * reliable table size of 8, and have the single letter attribute 7096 * names be 8 characters apart, producing a hash which will be the 7097 * same modulo 8. 7098 */ 7099 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7100 " a:a='v' a:i='w' />"; 7101 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7102 == XML_STATUS_ERROR) 7103 xml_failure(g_parser); 7104 } 7105 END_TEST 7106 7107 /* Regression test for SF bug #695401: unbound prefix. */ 7108 START_TEST(test_ns_unbound_prefix_on_attribute) { 7109 const char *text = "<doc a:attr=''/>"; 7110 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7111 "did not report unbound prefix on attribute"); 7112 } 7113 END_TEST 7114 7115 /* Regression test for SF bug #695401: unbound prefix. */ 7116 START_TEST(test_ns_unbound_prefix_on_element) { 7117 const char *text = "<a:doc/>"; 7118 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7119 "did not report unbound prefix on element"); 7120 } 7121 END_TEST 7122 7123 /* Test that the parsing status is correctly reset by XML_ParserReset(). 7124 * We usE test_return_ns_triplet() for our example parse to improve 7125 * coverage of tidying up code executed. 7126 */ 7127 START_TEST(test_ns_parser_reset) { 7128 XML_ParsingStatus status; 7129 7130 XML_GetParsingStatus(g_parser, &status); 7131 if (status.parsing != XML_INITIALIZED) 7132 fail("parsing status doesn't start INITIALIZED"); 7133 test_return_ns_triplet(); 7134 XML_GetParsingStatus(g_parser, &status); 7135 if (status.parsing != XML_FINISHED) 7136 fail("parsing status doesn't end FINISHED"); 7137 XML_ParserReset(g_parser, NULL); 7138 XML_GetParsingStatus(g_parser, &status); 7139 if (status.parsing != XML_INITIALIZED) 7140 fail("parsing status doesn't reset to INITIALIZED"); 7141 } 7142 END_TEST 7143 7144 /* Test that long element names with namespaces are handled correctly */ 7145 START_TEST(test_ns_long_element) { 7146 const char *text 7147 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 7148 " xmlns:foo='http://example.org/' bar:a='12'\n" 7149 " xmlns:bar='http://example.org/'>" 7150 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 7151 const XML_Char *elemstr[] 7152 = {XCS("http://example.org/") 7153 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 7154 XCS("http://example.org/ a bar")}; 7155 7156 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 7157 XML_SetUserData(g_parser, (void *)elemstr); 7158 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 7159 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7160 == XML_STATUS_ERROR) 7161 xml_failure(g_parser); 7162 } 7163 END_TEST 7164 7165 /* Test mixed population of prefixed and unprefixed attributes */ 7166 START_TEST(test_ns_mixed_prefix_atts) { 7167 const char *text = "<e a='12' bar:b='13'\n" 7168 " xmlns:bar='http://example.org/'>" 7169 "</e>"; 7170 7171 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7172 == XML_STATUS_ERROR) 7173 xml_failure(g_parser); 7174 } 7175 END_TEST 7176 7177 /* Test having a long namespaced element name inside a short one. 7178 * This exercises some internal buffer reallocation that is shared 7179 * across elements with the same namespace URI. 7180 */ 7181 START_TEST(test_ns_extend_uri_buffer) { 7182 const char *text = "<foo:e xmlns:foo='http://example.org/'>" 7183 " <foo:thisisalongenoughnametotriggerallocationaction" 7184 " foo:a='12' />" 7185 "</foo:e>"; 7186 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7187 == XML_STATUS_ERROR) 7188 xml_failure(g_parser); 7189 } 7190 END_TEST 7191 7192 /* Test that xmlns is correctly rejected as an attribute in the xmlns 7193 * namespace, but not in other namespaces 7194 */ 7195 START_TEST(test_ns_reserved_attributes) { 7196 const char *text1 7197 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />"; 7198 const char *text2 7199 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />"; 7200 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS, 7201 "xmlns not rejected as an attribute"); 7202 XML_ParserReset(g_parser, NULL); 7203 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7204 == XML_STATUS_ERROR) 7205 xml_failure(g_parser); 7206 } 7207 END_TEST 7208 7209 /* Test more reserved attributes */ 7210 START_TEST(test_ns_reserved_attributes_2) { 7211 const char *text1 = "<foo:e xmlns:foo='http://example.org/'" 7212 " xmlns:xml='http://example.org/' />"; 7213 const char *text2 7214 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />"; 7215 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />"; 7216 7217 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML, 7218 "xml not rejected as an attribute"); 7219 XML_ParserReset(g_parser, NULL); 7220 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI, 7221 "Use of w3.org URL not faulted"); 7222 XML_ParserReset(g_parser, NULL); 7223 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI, 7224 "Use of w3.org xmlns URL not faulted"); 7225 } 7226 END_TEST 7227 7228 /* Test string pool handling of namespace names of 2048 characters */ 7229 /* Exercises a particular string pool growth path */ 7230 START_TEST(test_ns_extremely_long_prefix) { 7231 /* C99 compilers are only required to support 4095-character 7232 * strings, so the following needs to be split in two to be safe 7233 * for all compilers. 7234 */ 7235 const char *text1 7236 = "<doc " 7237 /* 64 character on each line */ 7238 /* ...gives a total length of 2048 */ 7239 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7240 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7241 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7242 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7243 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7244 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7245 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7246 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7247 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7248 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7249 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7250 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7251 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7252 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7253 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7254 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7255 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7256 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7257 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7258 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7259 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7260 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7261 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7262 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7263 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7264 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7265 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7266 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7267 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7268 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7269 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7270 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7271 ":a='12'"; 7272 const char *text2 7273 = " xmlns:" 7274 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7275 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7276 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7277 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7278 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7279 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7280 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7281 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7282 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7283 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7284 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7285 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7286 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7287 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7288 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7289 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7290 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7291 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7292 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7293 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7294 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7295 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7296 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7297 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7298 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7299 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7300 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7301 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7302 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7303 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7304 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7305 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7306 "='foo'\n>" 7307 "</doc>"; 7308 7309 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 7310 == XML_STATUS_ERROR) 7311 xml_failure(g_parser); 7312 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7313 == XML_STATUS_ERROR) 7314 xml_failure(g_parser); 7315 } 7316 END_TEST 7317 7318 /* Test unknown encoding handlers in namespace setup */ 7319 START_TEST(test_ns_unknown_encoding_success) { 7320 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 7321 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>"; 7322 7323 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7324 run_character_check(text, XCS("Hi")); 7325 } 7326 END_TEST 7327 7328 /* Test that too many colons are rejected */ 7329 START_TEST(test_ns_double_colon) { 7330 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />"; 7331 const enum XML_Status status 7332 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7333 #ifdef XML_NS 7334 if ((status == XML_STATUS_OK) 7335 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7336 fail("Double colon in attribute name not faulted" 7337 " (despite active namespace support)"); 7338 } 7339 #else 7340 if (status != XML_STATUS_OK) { 7341 fail("Double colon in attribute name faulted" 7342 " (despite inactive namespace support"); 7343 } 7344 #endif 7345 } 7346 END_TEST 7347 7348 START_TEST(test_ns_double_colon_element) { 7349 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />"; 7350 const enum XML_Status status 7351 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7352 #ifdef XML_NS 7353 if ((status == XML_STATUS_OK) 7354 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7355 fail("Double colon in element name not faulted" 7356 " (despite active namespace support)"); 7357 } 7358 #else 7359 if (status != XML_STATUS_OK) { 7360 fail("Double colon in element name faulted" 7361 " (despite inactive namespace support"); 7362 } 7363 #endif 7364 } 7365 END_TEST 7366 7367 /* Test that non-name characters after a colon are rejected */ 7368 START_TEST(test_ns_bad_attr_leafname) { 7369 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />"; 7370 7371 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7372 "Invalid character in leafname not faulted"); 7373 } 7374 END_TEST 7375 7376 START_TEST(test_ns_bad_element_leafname) { 7377 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />"; 7378 7379 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7380 "Invalid character in element leafname not faulted"); 7381 } 7382 END_TEST 7383 7384 /* Test high-byte-set UTF-16 characters are valid in a leafname */ 7385 START_TEST(test_ns_utf16_leafname) { 7386 const char text[] = 7387 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' /> 7388 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7389 */ 7390 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0" 7391 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0"; 7392 const XML_Char *expected = XCS("a"); 7393 CharData storage; 7394 7395 CharData_Init(&storage); 7396 XML_SetStartElementHandler(g_parser, accumulate_attribute); 7397 XML_SetUserData(g_parser, &storage); 7398 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7399 == XML_STATUS_ERROR) 7400 xml_failure(g_parser); 7401 CharData_CheckXMLChars(&storage, expected); 7402 } 7403 END_TEST 7404 7405 START_TEST(test_ns_utf16_element_leafname) { 7406 const char text[] = 7407 /* <n:{KHO KHWAI} xmlns:n='URI'/> 7408 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7409 */ 7410 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>"; 7411 #ifdef XML_UNICODE 7412 const XML_Char *expected = XCS("URI \x0e04"); 7413 #else 7414 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7415 #endif 7416 CharData storage; 7417 7418 CharData_Init(&storage); 7419 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7420 XML_SetUserData(g_parser, &storage); 7421 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7422 == XML_STATUS_ERROR) 7423 xml_failure(g_parser); 7424 CharData_CheckXMLChars(&storage, expected); 7425 } 7426 END_TEST 7427 7428 START_TEST(test_ns_utf16_doctype) { 7429 const char text[] = 7430 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n 7431 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7432 */ 7433 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 " 7434 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 " 7435 "\0]\0>\0\n" 7436 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */ 7437 "\0<\0f\0o\0o\0:\x0e\x04\0 " 7438 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>" 7439 "\0&\0b\0a\0r\0;" 7440 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>"; 7441 #ifdef XML_UNICODE 7442 const XML_Char *expected = XCS("URI \x0e04"); 7443 #else 7444 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7445 #endif 7446 CharData storage; 7447 7448 CharData_Init(&storage); 7449 XML_SetUserData(g_parser, &storage); 7450 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7451 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7452 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7453 == XML_STATUS_ERROR) 7454 xml_failure(g_parser); 7455 CharData_CheckXMLChars(&storage, expected); 7456 } 7457 END_TEST 7458 7459 START_TEST(test_ns_invalid_doctype) { 7460 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n" 7461 "<foo:!bad>&bar;</foo:!bad>"; 7462 7463 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7464 "Invalid character in document local name not faulted"); 7465 } 7466 END_TEST 7467 7468 START_TEST(test_ns_double_colon_doctype) { 7469 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n" 7470 "<foo:a:doc>&bar;</foo:a:doc>"; 7471 7472 expect_failure(text, XML_ERROR_SYNTAX, 7473 "Double colon in document name not faulted"); 7474 } 7475 END_TEST 7476 7477 START_TEST(test_ns_separator_in_uri) { 7478 struct test_case { 7479 enum XML_Status expectedStatus; 7480 const char *doc; 7481 XML_Char namesep; 7482 }; 7483 struct test_case cases[] = { 7484 {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')}, 7485 {XML_STATUS_ERROR, "<doc xmlns='one
two' />", XCS('\n')}, 7486 {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')}, 7487 }; 7488 7489 size_t i = 0; 7490 size_t failCount = 0; 7491 for (; i < sizeof(cases) / sizeof(cases[0]); i++) { 7492 XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep); 7493 XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); 7494 if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), 7495 /*isFinal*/ XML_TRUE) 7496 != cases[i].expectedStatus) { 7497 failCount++; 7498 } 7499 XML_ParserFree(parser); 7500 } 7501 7502 if (failCount) { 7503 fail("Namespace separator handling is broken"); 7504 } 7505 } 7506 END_TEST 7507 7508 /* Control variable; the number of times duff_allocator() will successfully 7509 * allocate */ 7510 #define ALLOC_ALWAYS_SUCCEED (-1) 7511 #define REALLOC_ALWAYS_SUCCEED (-1) 7512 7513 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED; 7514 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED; 7515 7516 /* Crocked allocator for allocation failure tests */ 7517 static void * 7518 duff_allocator(size_t size) { 7519 if (allocation_count == 0) 7520 return NULL; 7521 if (allocation_count != ALLOC_ALWAYS_SUCCEED) 7522 allocation_count--; 7523 return malloc(size); 7524 } 7525 7526 /* Crocked reallocator for allocation failure tests */ 7527 static void * 7528 duff_reallocator(void *ptr, size_t size) { 7529 if (reallocation_count == 0) 7530 return NULL; 7531 if (reallocation_count != REALLOC_ALWAYS_SUCCEED) 7532 reallocation_count--; 7533 return realloc(ptr, size); 7534 } 7535 7536 /* Test that a failure to allocate the parser structure fails gracefully */ 7537 START_TEST(test_misc_alloc_create_parser) { 7538 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7539 unsigned int i; 7540 const unsigned int max_alloc_count = 10; 7541 7542 /* Something this simple shouldn't need more than 10 allocations */ 7543 for (i = 0; i < max_alloc_count; i++) { 7544 allocation_count = i; 7545 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7546 if (g_parser != NULL) 7547 break; 7548 } 7549 if (i == 0) 7550 fail("Parser unexpectedly ignored failing allocator"); 7551 else if (i == max_alloc_count) 7552 fail("Parser not created with max allocation count"); 7553 } 7554 END_TEST 7555 7556 /* Test memory allocation failures for a parser with an encoding */ 7557 START_TEST(test_misc_alloc_create_parser_with_encoding) { 7558 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7559 unsigned int i; 7560 const unsigned int max_alloc_count = 10; 7561 7562 /* Try several levels of allocation */ 7563 for (i = 0; i < max_alloc_count; i++) { 7564 allocation_count = i; 7565 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL); 7566 if (g_parser != NULL) 7567 break; 7568 } 7569 if (i == 0) 7570 fail("Parser ignored failing allocator"); 7571 else if (i == max_alloc_count) 7572 fail("Parser not created with max allocation count"); 7573 } 7574 END_TEST 7575 7576 /* Test that freeing a NULL parser doesn't cause an explosion. 7577 * (Not actually tested anywhere else) 7578 */ 7579 START_TEST(test_misc_null_parser) { 7580 XML_ParserFree(NULL); 7581 } 7582 END_TEST 7583 7584 /* Test that XML_ErrorString rejects out-of-range codes */ 7585 START_TEST(test_misc_error_string) { 7586 if (XML_ErrorString((enum XML_Error) - 1) != NULL) 7587 fail("Negative error code not rejected"); 7588 if (XML_ErrorString((enum XML_Error)100) != NULL) 7589 fail("Large error code not rejected"); 7590 } 7591 END_TEST 7592 7593 /* Test the version information is consistent */ 7594 7595 /* Since we are working in XML_LChars (potentially 16-bits), we 7596 * can't use the standard C library functions for character 7597 * manipulation and have to roll our own. 7598 */ 7599 static int 7600 parse_version(const XML_LChar *version_text, 7601 XML_Expat_Version *version_struct) { 7602 if (! version_text) 7603 return XML_FALSE; 7604 7605 while (*version_text != 0x00) { 7606 if (*version_text >= ASCII_0 && *version_text <= ASCII_9) 7607 break; 7608 version_text++; 7609 } 7610 if (*version_text == 0x00) 7611 return XML_FALSE; 7612 7613 /* version_struct->major = strtoul(version_text, 10, &version_text) */ 7614 version_struct->major = 0; 7615 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7616 version_struct->major 7617 = 10 * version_struct->major + (*version_text++ - ASCII_0); 7618 } 7619 if (*version_text++ != ASCII_PERIOD) 7620 return XML_FALSE; 7621 7622 /* Now for the minor version number */ 7623 version_struct->minor = 0; 7624 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7625 version_struct->minor 7626 = 10 * version_struct->minor + (*version_text++ - ASCII_0); 7627 } 7628 if (*version_text++ != ASCII_PERIOD) 7629 return XML_FALSE; 7630 7631 /* Finally the micro version number */ 7632 version_struct->micro = 0; 7633 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7634 version_struct->micro 7635 = 10 * version_struct->micro + (*version_text++ - ASCII_0); 7636 } 7637 if (*version_text != 0x00) 7638 return XML_FALSE; 7639 return XML_TRUE; 7640 } 7641 7642 static int 7643 versions_equal(const XML_Expat_Version *first, 7644 const XML_Expat_Version *second) { 7645 return (first->major == second->major && first->minor == second->minor 7646 && first->micro == second->micro); 7647 } 7648 7649 START_TEST(test_misc_version) { 7650 XML_Expat_Version read_version = XML_ExpatVersionInfo(); 7651 /* Silence compiler warning with the following assignment */ 7652 XML_Expat_Version parsed_version = {0, 0, 0}; 7653 const XML_LChar *version_text = XML_ExpatVersion(); 7654 7655 if (version_text == NULL) 7656 fail("Could not obtain version text"); 7657 assert(version_text != NULL); 7658 if (! parse_version(version_text, &parsed_version)) 7659 fail("Unable to parse version text"); 7660 if (! versions_equal(&read_version, &parsed_version)) 7661 fail("Version mismatch"); 7662 7663 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) 7664 if (xcstrcmp(version_text, XCS("expat_2.4.9"))) /* needs bump on releases */ 7665 fail("XML_*_VERSION in expat.h out of sync?\n"); 7666 #else 7667 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T 7668 * then XML_LChar is defined as char, for some reason. 7669 */ 7670 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */ 7671 fail("XML_*_VERSION in expat.h out of sync?\n"); 7672 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */ 7673 } 7674 END_TEST 7675 7676 /* Test feature information */ 7677 START_TEST(test_misc_features) { 7678 const XML_Feature *features = XML_GetFeatureList(); 7679 7680 /* Prevent problems with double-freeing parsers */ 7681 g_parser = NULL; 7682 if (features == NULL) { 7683 fail("Failed to get feature information"); 7684 } else { 7685 /* Loop through the features checking what we can */ 7686 while (features->feature != XML_FEATURE_END) { 7687 switch (features->feature) { 7688 case XML_FEATURE_SIZEOF_XML_CHAR: 7689 if (features->value != sizeof(XML_Char)) 7690 fail("Incorrect size of XML_Char"); 7691 break; 7692 case XML_FEATURE_SIZEOF_XML_LCHAR: 7693 if (features->value != sizeof(XML_LChar)) 7694 fail("Incorrect size of XML_LChar"); 7695 break; 7696 default: 7697 break; 7698 } 7699 features++; 7700 } 7701 } 7702 } 7703 END_TEST 7704 7705 /* Regression test for GitHub Issue #17: memory leak parsing attribute 7706 * values with mixed bound and unbound namespaces. 7707 */ 7708 START_TEST(test_misc_attribute_leak) { 7709 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>"; 7710 XML_Memory_Handling_Suite memsuite 7711 = {tracking_malloc, tracking_realloc, tracking_free}; 7712 7713 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n")); 7714 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found"); 7715 XML_ParserFree(g_parser); 7716 /* Prevent the teardown trying to double free */ 7717 g_parser = NULL; 7718 7719 if (! tracking_report()) 7720 fail("Memory leak found"); 7721 } 7722 END_TEST 7723 7724 /* Test parser created for UTF-16LE is successful */ 7725 START_TEST(test_misc_utf16le) { 7726 const char text[] = 7727 /* <?xml version='1.0'?><q>Hi</q> */ 7728 "<\0?\0x\0m\0l\0 \0" 7729 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0" 7730 "<\0q\0>\0H\0i\0<\0/\0q\0>\0"; 7731 const XML_Char *expected = XCS("Hi"); 7732 CharData storage; 7733 7734 g_parser = XML_ParserCreate(XCS("UTF-16LE")); 7735 if (g_parser == NULL) 7736 fail("Parser not created"); 7737 7738 CharData_Init(&storage); 7739 XML_SetUserData(g_parser, &storage); 7740 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 7741 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7742 == XML_STATUS_ERROR) 7743 xml_failure(g_parser); 7744 CharData_CheckXMLChars(&storage, expected); 7745 } 7746 END_TEST 7747 7748 typedef struct { 7749 XML_Parser parser; 7750 int deep; 7751 } DataIssue240; 7752 7753 static void 7754 start_element_issue_240(void *userData, const XML_Char *name, 7755 const XML_Char **atts) { 7756 DataIssue240 *mydata = (DataIssue240 *)userData; 7757 UNUSED_P(name); 7758 UNUSED_P(atts); 7759 mydata->deep++; 7760 } 7761 7762 static void 7763 end_element_issue_240(void *userData, const XML_Char *name) { 7764 DataIssue240 *mydata = (DataIssue240 *)userData; 7765 7766 UNUSED_P(name); 7767 mydata->deep--; 7768 if (mydata->deep == 0) { 7769 XML_StopParser(mydata->parser, 0); 7770 } 7771 } 7772 7773 START_TEST(test_misc_stop_during_end_handler_issue_240_1) { 7774 XML_Parser parser; 7775 DataIssue240 *mydata; 7776 enum XML_Status result; 7777 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>"; 7778 7779 parser = XML_ParserCreate(NULL); 7780 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7781 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7782 mydata->parser = parser; 7783 mydata->deep = 0; 7784 XML_SetUserData(parser, mydata); 7785 7786 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1); 7787 XML_ParserFree(parser); 7788 free(mydata); 7789 if (result != XML_STATUS_ERROR) 7790 fail("Stopping the parser did not work as expected"); 7791 } 7792 END_TEST 7793 7794 START_TEST(test_misc_stop_during_end_handler_issue_240_2) { 7795 XML_Parser parser; 7796 DataIssue240 *mydata; 7797 enum XML_Status result; 7798 const char *const doc2 = "<doc><elem/></doc>"; 7799 7800 parser = XML_ParserCreate(NULL); 7801 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7802 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7803 mydata->parser = parser; 7804 mydata->deep = 0; 7805 XML_SetUserData(parser, mydata); 7806 7807 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1); 7808 XML_ParserFree(parser); 7809 free(mydata); 7810 if (result != XML_STATUS_ERROR) 7811 fail("Stopping the parser did not work as expected"); 7812 } 7813 END_TEST 7814 7815 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { 7816 const char *const inputOne = "<!DOCTYPE d [\n" 7817 "<!ENTITY % e ']><d/>'>\n" 7818 "\n" 7819 "%e;"; 7820 const char *const inputTwo = "<!DOCTYPE d [\n" 7821 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n" 7822 "\n" 7823 "%e2;"; 7824 const char *const inputThree = "<!DOCTYPE d [\n" 7825 "<!ENTITY % e ']><d'>\n" 7826 "\n" 7827 "%e;"; 7828 const char *const inputIssue317 = "<!DOCTYPE doc [\n" 7829 "<!ENTITY % foo ']>\n" 7830 "<doc>Hell<oc (#PCDATA)*>'>\n" 7831 "%foo;\n" 7832 "]>\n" 7833 "<doc>Hello, world</dVc>"; 7834 7835 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317}; 7836 size_t inputIndex = 0; 7837 7838 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) { 7839 XML_Parser parser; 7840 enum XML_Status parseResult; 7841 int setParamEntityResult; 7842 XML_Size lineNumber; 7843 XML_Size columnNumber; 7844 const char *const input = inputs[inputIndex]; 7845 7846 parser = XML_ParserCreate(NULL); 7847 setParamEntityResult 7848 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7849 if (setParamEntityResult != 1) 7850 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS."); 7851 7852 parseResult = XML_Parse(parser, input, (int)strlen(input), 0); 7853 if (parseResult != XML_STATUS_ERROR) { 7854 parseResult = XML_Parse(parser, "", 0, 1); 7855 if (parseResult != XML_STATUS_ERROR) { 7856 fail("Parsing was expected to fail but succeeded."); 7857 } 7858 } 7859 7860 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) 7861 fail("Error code does not match XML_ERROR_INVALID_TOKEN"); 7862 7863 lineNumber = XML_GetCurrentLineNumber(parser); 7864 if (lineNumber != 4) 7865 fail("XML_GetCurrentLineNumber does not work as expected."); 7866 7867 columnNumber = XML_GetCurrentColumnNumber(parser); 7868 if (columnNumber != 0) 7869 fail("XML_GetCurrentColumnNumber does not work as expected."); 7870 7871 XML_ParserFree(parser); 7872 } 7873 } 7874 END_TEST 7875 7876 static void 7877 alloc_setup(void) { 7878 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 7879 7880 /* Ensure the parser creation will go through */ 7881 allocation_count = ALLOC_ALWAYS_SUCCEED; 7882 reallocation_count = REALLOC_ALWAYS_SUCCEED; 7883 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7884 if (g_parser == NULL) 7885 fail("Parser not created"); 7886 } 7887 7888 static void 7889 alloc_teardown(void) { 7890 basic_teardown(); 7891 } 7892 7893 /* Test the effects of allocation failures on xml declaration processing */ 7894 START_TEST(test_alloc_parse_xdecl) { 7895 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7896 "<doc>Hello, world</doc>"; 7897 int i; 7898 const int max_alloc_count = 15; 7899 7900 for (i = 0; i < max_alloc_count; i++) { 7901 allocation_count = i; 7902 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7903 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7904 != XML_STATUS_ERROR) 7905 break; 7906 /* Resetting the parser is insufficient, because some memory 7907 * allocations are cached within the parser. Instead we use 7908 * the teardown and setup routines to ensure that we have the 7909 * right sort of parser back in our hands. 7910 */ 7911 alloc_teardown(); 7912 alloc_setup(); 7913 } 7914 if (i == 0) 7915 fail("Parse succeeded despite failing allocator"); 7916 if (i == max_alloc_count) 7917 fail("Parse failed with max allocations"); 7918 } 7919 END_TEST 7920 7921 /* As above, but with an encoding big enough to cause storing the 7922 * version information to expand the string pool being used. 7923 */ 7924 static int XMLCALL 7925 long_encoding_handler(void *userData, const XML_Char *encoding, 7926 XML_Encoding *info) { 7927 int i; 7928 7929 UNUSED_P(userData); 7930 UNUSED_P(encoding); 7931 for (i = 0; i < 256; i++) 7932 info->map[i] = i; 7933 info->data = NULL; 7934 info->convert = NULL; 7935 info->release = NULL; 7936 return XML_STATUS_OK; 7937 } 7938 7939 START_TEST(test_alloc_parse_xdecl_2) { 7940 const char *text 7941 = "<?xml version='1.0' encoding='" 7942 /* Each line is 64 characters */ 7943 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456" 7944 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7945 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7946 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7947 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7948 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7949 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7950 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7951 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7952 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7953 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7954 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7955 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7956 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7957 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7958 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN" 7959 "'?>" 7960 "<doc>Hello, world</doc>"; 7961 int i; 7962 const int max_alloc_count = 20; 7963 7964 for (i = 0; i < max_alloc_count; i++) { 7965 allocation_count = i; 7966 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7967 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL); 7968 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7969 != XML_STATUS_ERROR) 7970 break; 7971 /* See comment in test_alloc_parse_xdecl() */ 7972 alloc_teardown(); 7973 alloc_setup(); 7974 } 7975 if (i == 0) 7976 fail("Parse succeeded despite failing allocator"); 7977 if (i == max_alloc_count) 7978 fail("Parse failed with max allocations"); 7979 } 7980 END_TEST 7981 7982 /* Test the effects of allocation failures on a straightforward parse */ 7983 START_TEST(test_alloc_parse_pi) { 7984 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7985 "<?pi unknown?>\n" 7986 "<doc>" 7987 "Hello, world" 7988 "</doc>"; 7989 int i; 7990 const int max_alloc_count = 15; 7991 7992 for (i = 0; i < max_alloc_count; i++) { 7993 allocation_count = i; 7994 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7995 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7996 != XML_STATUS_ERROR) 7997 break; 7998 /* See comment in test_alloc_parse_xdecl() */ 7999 alloc_teardown(); 8000 alloc_setup(); 8001 } 8002 if (i == 0) 8003 fail("Parse succeeded despite failing allocator"); 8004 if (i == max_alloc_count) 8005 fail("Parse failed with max allocations"); 8006 } 8007 END_TEST 8008 8009 START_TEST(test_alloc_parse_pi_2) { 8010 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8011 "<doc>" 8012 "Hello, world" 8013 "<?pi unknown?>\n" 8014 "</doc>"; 8015 int i; 8016 const int max_alloc_count = 15; 8017 8018 for (i = 0; i < max_alloc_count; i++) { 8019 allocation_count = i; 8020 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8021 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8022 != XML_STATUS_ERROR) 8023 break; 8024 /* See comment in test_alloc_parse_xdecl() */ 8025 alloc_teardown(); 8026 alloc_setup(); 8027 } 8028 if (i == 0) 8029 fail("Parse succeeded despite failing allocator"); 8030 if (i == max_alloc_count) 8031 fail("Parse failed with max allocations"); 8032 } 8033 END_TEST 8034 8035 START_TEST(test_alloc_parse_pi_3) { 8036 const char *text 8037 = "<?" 8038 /* 64 characters per line */ 8039 "This processing instruction should be long enough to ensure that" 8040 "it triggers the growth of an internal string pool when the " 8041 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP" 8042 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8043 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8044 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8045 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8046 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8047 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8048 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8049 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8050 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8051 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8052 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8053 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8054 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8055 "Q?><doc/>"; 8056 int i; 8057 const int max_alloc_count = 20; 8058 8059 for (i = 0; i < max_alloc_count; i++) { 8060 allocation_count = i; 8061 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8062 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8063 != XML_STATUS_ERROR) 8064 break; 8065 /* See comment in test_alloc_parse_xdecl() */ 8066 alloc_teardown(); 8067 alloc_setup(); 8068 } 8069 if (i == 0) 8070 fail("Parse succeeded despite failing allocator"); 8071 if (i == max_alloc_count) 8072 fail("Parse failed with max allocations"); 8073 } 8074 END_TEST 8075 8076 START_TEST(test_alloc_parse_comment) { 8077 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8078 "<!-- Test parsing this comment -->" 8079 "<doc>Hi</doc>"; 8080 int i; 8081 const int max_alloc_count = 15; 8082 8083 for (i = 0; i < max_alloc_count; i++) { 8084 allocation_count = i; 8085 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8086 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8087 != XML_STATUS_ERROR) 8088 break; 8089 /* See comment in test_alloc_parse_xdecl() */ 8090 alloc_teardown(); 8091 alloc_setup(); 8092 } 8093 if (i == 0) 8094 fail("Parse succeeded despite failing allocator"); 8095 if (i == max_alloc_count) 8096 fail("Parse failed with max allocations"); 8097 } 8098 END_TEST 8099 8100 START_TEST(test_alloc_parse_comment_2) { 8101 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8102 "<doc>" 8103 "Hello, world" 8104 "<!-- Parse this comment too -->" 8105 "</doc>"; 8106 int i; 8107 const int max_alloc_count = 15; 8108 8109 for (i = 0; i < max_alloc_count; i++) { 8110 allocation_count = i; 8111 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8112 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8113 != XML_STATUS_ERROR) 8114 break; 8115 /* See comment in test_alloc_parse_xdecl() */ 8116 alloc_teardown(); 8117 alloc_setup(); 8118 } 8119 if (i == 0) 8120 fail("Parse succeeded despite failing allocator"); 8121 if (i == max_alloc_count) 8122 fail("Parse failed with max allocations"); 8123 } 8124 END_TEST 8125 8126 static int XMLCALL 8127 external_entity_duff_loader(XML_Parser parser, const XML_Char *context, 8128 const XML_Char *base, const XML_Char *systemId, 8129 const XML_Char *publicId) { 8130 XML_Parser new_parser; 8131 unsigned int i; 8132 const unsigned int max_alloc_count = 10; 8133 8134 UNUSED_P(base); 8135 UNUSED_P(systemId); 8136 UNUSED_P(publicId); 8137 /* Try a few different allocation levels */ 8138 for (i = 0; i < max_alloc_count; i++) { 8139 allocation_count = i; 8140 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8141 if (new_parser != NULL) { 8142 XML_ParserFree(new_parser); 8143 break; 8144 } 8145 } 8146 if (i == 0) 8147 fail("External parser creation ignored failing allocator"); 8148 else if (i == max_alloc_count) 8149 fail("Extern parser not created with max allocation count"); 8150 8151 /* Make sure other random allocation doesn't now fail */ 8152 allocation_count = ALLOC_ALWAYS_SUCCEED; 8153 8154 /* Make sure the failure code path is executed too */ 8155 return XML_STATUS_ERROR; 8156 } 8157 8158 /* Test that external parser creation running out of memory is 8159 * correctly reported. Based on the external entity test cases. 8160 */ 8161 START_TEST(test_alloc_create_external_parser) { 8162 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8163 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8164 "<doc>&entity;</doc>"; 8165 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8166 8167 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8168 XML_SetUserData(g_parser, foo_text); 8169 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader); 8170 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8171 != XML_STATUS_ERROR) { 8172 fail("External parser allocator returned success incorrectly"); 8173 } 8174 } 8175 END_TEST 8176 8177 /* More external parser memory allocation testing */ 8178 START_TEST(test_alloc_run_external_parser) { 8179 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8180 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8181 "<doc>&entity;</doc>"; 8182 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8183 unsigned int i; 8184 const unsigned int max_alloc_count = 15; 8185 8186 for (i = 0; i < max_alloc_count; i++) { 8187 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8188 XML_SetUserData(g_parser, foo_text); 8189 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 8190 allocation_count = i; 8191 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8192 != XML_STATUS_ERROR) 8193 break; 8194 /* See comment in test_alloc_parse_xdecl() */ 8195 alloc_teardown(); 8196 alloc_setup(); 8197 } 8198 if (i == 0) 8199 fail("Parsing ignored failing allocator"); 8200 else if (i == max_alloc_count) 8201 fail("Parsing failed with allocation count 10"); 8202 } 8203 END_TEST 8204 8205 static int XMLCALL 8206 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context, 8207 const XML_Char *base, const XML_Char *systemId, 8208 const XML_Char *publicId) { 8209 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8210 const char *text; 8211 XML_Parser new_parser; 8212 int i; 8213 const int max_alloc_count = 20; 8214 8215 UNUSED_P(base); 8216 UNUSED_P(systemId); 8217 UNUSED_P(publicId); 8218 if (callno == 0) { 8219 /* First time through, check how many calls to malloc occur */ 8220 text = ("<!ELEMENT doc (e+)>\n" 8221 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8222 "<!ELEMENT e EMPTY>\n"); 8223 allocation_count = 10000; 8224 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8225 if (new_parser == NULL) { 8226 fail("Unable to allocate first external parser"); 8227 return XML_STATUS_ERROR; 8228 } 8229 /* Stash the number of calls in the user data */ 8230 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count)); 8231 } else { 8232 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8233 "<e/>"); 8234 /* Try at varying levels to exercise more code paths */ 8235 for (i = 0; i < max_alloc_count; i++) { 8236 allocation_count = callno + i; 8237 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8238 if (new_parser != NULL) 8239 break; 8240 } 8241 if (i == 0) { 8242 fail("Second external parser unexpectedly created"); 8243 XML_ParserFree(new_parser); 8244 return XML_STATUS_ERROR; 8245 } else if (i == max_alloc_count) { 8246 fail("Second external parser not created"); 8247 return XML_STATUS_ERROR; 8248 } 8249 } 8250 8251 allocation_count = ALLOC_ALWAYS_SUCCEED; 8252 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE) 8253 == XML_STATUS_ERROR) { 8254 xml_failure(new_parser); 8255 return XML_STATUS_ERROR; 8256 } 8257 XML_ParserFree(new_parser); 8258 return XML_STATUS_OK; 8259 } 8260 8261 /* Test that running out of memory in dtdCopy is correctly reported. 8262 * Based on test_default_ns_from_ext_subset_and_ext_ge() 8263 */ 8264 START_TEST(test_alloc_dtd_copy_default_atts) { 8265 const char *text = "<?xml version='1.0'?>\n" 8266 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8267 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8268 "]>\n" 8269 "<doc xmlns='http://example.org/ns1'>\n" 8270 "&en;\n" 8271 "</doc>"; 8272 8273 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8274 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler); 8275 XML_SetUserData(g_parser, NULL); 8276 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8277 == XML_STATUS_ERROR) 8278 xml_failure(g_parser); 8279 } 8280 END_TEST 8281 8282 static int XMLCALL 8283 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context, 8284 const XML_Char *base, const XML_Char *systemId, 8285 const XML_Char *publicId) { 8286 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8287 const char *text; 8288 XML_Parser new_parser; 8289 enum XML_Status rv; 8290 8291 UNUSED_P(base); 8292 UNUSED_P(systemId); 8293 UNUSED_P(publicId); 8294 if (callno == 0) { 8295 /* Try different allocation levels for whole exercise */ 8296 text = ("<!ELEMENT doc (e+)>\n" 8297 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8298 "<!ELEMENT e EMPTY>\n"); 8299 XML_SetUserData(parser, (void *)(intptr_t)1); 8300 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8301 if (new_parser == NULL) 8302 return XML_STATUS_ERROR; 8303 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8304 } else { 8305 /* Just run through once */ 8306 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8307 "<e/>"); 8308 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8309 if (new_parser == NULL) 8310 return XML_STATUS_ERROR; 8311 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8312 } 8313 XML_ParserFree(new_parser); 8314 if (rv == XML_STATUS_ERROR) 8315 return XML_STATUS_ERROR; 8316 return XML_STATUS_OK; 8317 } 8318 8319 /* Test more external entity allocation failure paths */ 8320 START_TEST(test_alloc_external_entity) { 8321 const char *text = "<?xml version='1.0'?>\n" 8322 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8323 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8324 "]>\n" 8325 "<doc xmlns='http://example.org/ns1'>\n" 8326 "&en;\n" 8327 "</doc>"; 8328 int i; 8329 const int alloc_test_max_repeats = 50; 8330 8331 for (i = 0; i < alloc_test_max_repeats; i++) { 8332 allocation_count = -1; 8333 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8334 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2); 8335 XML_SetUserData(g_parser, NULL); 8336 allocation_count = i; 8337 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8338 == XML_STATUS_OK) 8339 break; 8340 /* See comment in test_alloc_parse_xdecl() */ 8341 alloc_teardown(); 8342 alloc_setup(); 8343 } 8344 allocation_count = -1; 8345 if (i == 0) 8346 fail("External entity parsed despite duff allocator"); 8347 if (i == alloc_test_max_repeats) 8348 fail("External entity not parsed at max allocation count"); 8349 } 8350 END_TEST 8351 8352 /* Test more allocation failure paths */ 8353 static int XMLCALL 8354 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context, 8355 const XML_Char *base, 8356 const XML_Char *systemId, 8357 const XML_Char *publicId) { 8358 /* As for external_entity_loader() */ 8359 const char *text = "<?xml encoding='iso-8859-3'?>" 8360 "\xC3\xA9"; 8361 XML_Parser ext_parser; 8362 enum XML_Status status; 8363 8364 UNUSED_P(base); 8365 UNUSED_P(systemId); 8366 UNUSED_P(publicId); 8367 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8368 if (ext_parser == NULL) 8369 return XML_STATUS_ERROR; 8370 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) { 8371 XML_ParserFree(ext_parser); 8372 return XML_STATUS_ERROR; 8373 } 8374 status 8375 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8376 XML_ParserFree(ext_parser); 8377 if (status == XML_STATUS_ERROR) 8378 return XML_STATUS_ERROR; 8379 return XML_STATUS_OK; 8380 } 8381 8382 START_TEST(test_alloc_ext_entity_set_encoding) { 8383 const char *text = "<!DOCTYPE doc [\n" 8384 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8385 "]>\n" 8386 "<doc>&en;</doc>"; 8387 int i; 8388 const int max_allocation_count = 30; 8389 8390 for (i = 0; i < max_allocation_count; i++) { 8391 XML_SetExternalEntityRefHandler(g_parser, 8392 external_entity_alloc_set_encoding); 8393 allocation_count = i; 8394 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8395 == XML_STATUS_OK) 8396 break; 8397 allocation_count = -1; 8398 /* See comment in test_alloc_parse_xdecl() */ 8399 alloc_teardown(); 8400 alloc_setup(); 8401 } 8402 if (i == 0) 8403 fail("Encoding check succeeded despite failing allocator"); 8404 if (i == max_allocation_count) 8405 fail("Encoding failed at max allocation count"); 8406 } 8407 END_TEST 8408 8409 static int XMLCALL 8410 unknown_released_encoding_handler(void *data, const XML_Char *encoding, 8411 XML_Encoding *info) { 8412 UNUSED_P(data); 8413 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) { 8414 int i; 8415 8416 for (i = 0; i < 256; i++) 8417 info->map[i] = i; 8418 info->data = NULL; 8419 info->convert = NULL; 8420 info->release = dummy_release; 8421 return XML_STATUS_OK; 8422 } 8423 return XML_STATUS_ERROR; 8424 } 8425 8426 /* Test the effects of allocation failure in internal entities. 8427 * Based on test_unknown_encoding_internal_entity 8428 */ 8429 START_TEST(test_alloc_internal_entity) { 8430 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 8431 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 8432 "<test a='&foo;'/>"; 8433 unsigned int i; 8434 const unsigned int max_alloc_count = 20; 8435 8436 for (i = 0; i < max_alloc_count; i++) { 8437 allocation_count = i; 8438 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, 8439 NULL); 8440 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8441 != XML_STATUS_ERROR) 8442 break; 8443 /* See comment in test_alloc_parse_xdecl() */ 8444 alloc_teardown(); 8445 alloc_setup(); 8446 } 8447 if (i == 0) 8448 fail("Internal entity worked despite failing allocations"); 8449 else if (i == max_alloc_count) 8450 fail("Internal entity failed at max allocation count"); 8451 } 8452 END_TEST 8453 8454 /* Test the robustness against allocation failure of element handling 8455 * Based on test_dtd_default_handling(). 8456 */ 8457 START_TEST(test_alloc_dtd_default_handling) { 8458 const char *text = "<!DOCTYPE doc [\n" 8459 "<!ENTITY e SYSTEM 'http://example.org/e'>\n" 8460 "<!NOTATION n SYSTEM 'http://example.org/n'>\n" 8461 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n" 8462 "<!ELEMENT doc (#PCDATA)>\n" 8463 "<!ATTLIST doc a CDATA #IMPLIED>\n" 8464 "<?pi in dtd?>\n" 8465 "<!--comment in dtd-->\n" 8466 "]>\n" 8467 "<doc><![CDATA[text in doc]]></doc>"; 8468 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>"); 8469 CharData storage; 8470 int i; 8471 const int max_alloc_count = 25; 8472 8473 for (i = 0; i < max_alloc_count; i++) { 8474 allocation_count = i; 8475 dummy_handler_flags = 0; 8476 XML_SetDefaultHandler(g_parser, accumulate_characters); 8477 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 8478 dummy_end_doctype_handler); 8479 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8480 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8481 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 8482 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8483 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8484 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8485 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler, 8486 dummy_end_cdata_handler); 8487 XML_SetUnparsedEntityDeclHandler(g_parser, 8488 dummy_unparsed_entity_decl_handler); 8489 CharData_Init(&storage); 8490 XML_SetUserData(g_parser, &storage); 8491 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 8492 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8493 != XML_STATUS_ERROR) 8494 break; 8495 /* See comment in test_alloc_parse_xdecl() */ 8496 alloc_teardown(); 8497 alloc_setup(); 8498 } 8499 if (i == 0) 8500 fail("Default DTD parsed despite allocation failures"); 8501 if (i == max_alloc_count) 8502 fail("Default DTD not parsed with maximum alloc count"); 8503 CharData_CheckXMLChars(&storage, expected); 8504 if (dummy_handler_flags 8505 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG 8506 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG 8507 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG 8508 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG 8509 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG 8510 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG)) 8511 fail("Not all handlers were called"); 8512 } 8513 END_TEST 8514 8515 /* Test robustness of XML_SetEncoding() with a failing allocator */ 8516 START_TEST(test_alloc_explicit_encoding) { 8517 int i; 8518 const int max_alloc_count = 5; 8519 8520 for (i = 0; i < max_alloc_count; i++) { 8521 allocation_count = i; 8522 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK) 8523 break; 8524 } 8525 if (i == 0) 8526 fail("Encoding set despite failing allocator"); 8527 else if (i == max_alloc_count) 8528 fail("Encoding not set at max allocation count"); 8529 } 8530 END_TEST 8531 8532 /* Test robustness of XML_SetBase against a failing allocator */ 8533 START_TEST(test_alloc_set_base) { 8534 const XML_Char *new_base = XCS("/local/file/name.xml"); 8535 int i; 8536 const int max_alloc_count = 5; 8537 8538 for (i = 0; i < max_alloc_count; i++) { 8539 allocation_count = i; 8540 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK) 8541 break; 8542 } 8543 if (i == 0) 8544 fail("Base set despite failing allocator"); 8545 else if (i == max_alloc_count) 8546 fail("Base not set with max allocation count"); 8547 } 8548 END_TEST 8549 8550 /* Test buffer extension in the face of a duff reallocator */ 8551 START_TEST(test_alloc_realloc_buffer) { 8552 const char *text = get_buffer_test_text; 8553 void *buffer; 8554 int i; 8555 const int max_realloc_count = 10; 8556 8557 /* Get a smallish buffer */ 8558 for (i = 0; i < max_realloc_count; i++) { 8559 reallocation_count = i; 8560 buffer = XML_GetBuffer(g_parser, 1536); 8561 if (buffer == NULL) 8562 fail("1.5K buffer reallocation failed"); 8563 assert(buffer != NULL); 8564 memcpy(buffer, text, strlen(text)); 8565 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 8566 == XML_STATUS_OK) 8567 break; 8568 /* See comment in test_alloc_parse_xdecl() */ 8569 alloc_teardown(); 8570 alloc_setup(); 8571 } 8572 reallocation_count = -1; 8573 if (i == 0) 8574 fail("Parse succeeded with no reallocation"); 8575 else if (i == max_realloc_count) 8576 fail("Parse failed with max reallocation count"); 8577 } 8578 END_TEST 8579 8580 /* Same test for external entity parsers */ 8581 static int XMLCALL 8582 external_entity_reallocator(XML_Parser parser, const XML_Char *context, 8583 const XML_Char *base, const XML_Char *systemId, 8584 const XML_Char *publicId) { 8585 const char *text = get_buffer_test_text; 8586 XML_Parser ext_parser; 8587 void *buffer; 8588 enum XML_Status status; 8589 8590 UNUSED_P(base); 8591 UNUSED_P(systemId); 8592 UNUSED_P(publicId); 8593 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8594 if (ext_parser == NULL) 8595 fail("Could not create external entity parser"); 8596 8597 reallocation_count = (intptr_t)XML_GetUserData(parser); 8598 buffer = XML_GetBuffer(ext_parser, 1536); 8599 if (buffer == NULL) 8600 fail("Buffer allocation failed"); 8601 assert(buffer != NULL); 8602 memcpy(buffer, text, strlen(text)); 8603 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE); 8604 reallocation_count = -1; 8605 XML_ParserFree(ext_parser); 8606 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR; 8607 } 8608 8609 START_TEST(test_alloc_ext_entity_realloc_buffer) { 8610 const char *text = "<!DOCTYPE doc [\n" 8611 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8612 "]>\n" 8613 "<doc>&en;</doc>"; 8614 int i; 8615 const int max_realloc_count = 10; 8616 8617 for (i = 0; i < max_realloc_count; i++) { 8618 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator); 8619 XML_SetUserData(g_parser, (void *)(intptr_t)i); 8620 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8621 == XML_STATUS_OK) 8622 break; 8623 /* See comment in test_alloc_parse_xdecl() */ 8624 alloc_teardown(); 8625 alloc_setup(); 8626 } 8627 if (i == 0) 8628 fail("Succeeded with no reallocations"); 8629 if (i == max_realloc_count) 8630 fail("Failed with max reallocations"); 8631 } 8632 END_TEST 8633 8634 /* Test elements with many attributes are handled correctly */ 8635 START_TEST(test_alloc_realloc_many_attributes) { 8636 const char *text = "<!DOCTYPE doc [\n" 8637 "<!ATTLIST doc za CDATA 'default'>\n" 8638 "<!ATTLIST doc zb CDATA 'def2'>\n" 8639 "<!ATTLIST doc zc CDATA 'def3'>\n" 8640 "]>\n" 8641 "<doc a='1'" 8642 " b='2'" 8643 " c='3'" 8644 " d='4'" 8645 " e='5'" 8646 " f='6'" 8647 " g='7'" 8648 " h='8'" 8649 " i='9'" 8650 " j='10'" 8651 " k='11'" 8652 " l='12'" 8653 " m='13'" 8654 " n='14'" 8655 " p='15'" 8656 " q='16'" 8657 " r='17'" 8658 " s='18'>" 8659 "</doc>"; 8660 int i; 8661 const int max_realloc_count = 10; 8662 8663 for (i = 0; i < max_realloc_count; i++) { 8664 reallocation_count = i; 8665 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8666 != XML_STATUS_ERROR) 8667 break; 8668 /* See comment in test_alloc_parse_xdecl() */ 8669 alloc_teardown(); 8670 alloc_setup(); 8671 } 8672 if (i == 0) 8673 fail("Parse succeeded despite no reallocations"); 8674 if (i == max_realloc_count) 8675 fail("Parse failed at max reallocations"); 8676 } 8677 END_TEST 8678 8679 /* Test handling of a public entity with failing allocator */ 8680 START_TEST(test_alloc_public_entity_value) { 8681 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8682 "<doc></doc>\n"; 8683 char dtd_text[] 8684 = "<!ELEMENT doc EMPTY>\n" 8685 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n" 8686 "<!ENTITY % " 8687 /* Each line is 64 characters */ 8688 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8702 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8703 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8704 " '%e1;'>\n" 8705 "%e1;\n"; 8706 int i; 8707 const int max_alloc_count = 50; 8708 8709 for (i = 0; i < max_alloc_count; i++) { 8710 allocation_count = i; 8711 dummy_handler_flags = 0; 8712 XML_SetUserData(g_parser, dtd_text); 8713 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8714 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8715 /* Provoke a particular code path */ 8716 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8717 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8718 != XML_STATUS_ERROR) 8719 break; 8720 /* See comment in test_alloc_parse_xdecl() */ 8721 alloc_teardown(); 8722 alloc_setup(); 8723 } 8724 if (i == 0) 8725 fail("Parsing worked despite failing allocation"); 8726 if (i == max_alloc_count) 8727 fail("Parsing failed at max allocation count"); 8728 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG) 8729 fail("Entity declaration handler not called"); 8730 } 8731 END_TEST 8732 8733 START_TEST(test_alloc_realloc_subst_public_entity_value) { 8734 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8735 "<doc></doc>\n"; 8736 char dtd_text[] 8737 = "<!ELEMENT doc EMPTY>\n" 8738 "<!ENTITY % " 8739 /* Each line is 64 characters */ 8740 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8741 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8742 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8743 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8744 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8745 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8746 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8747 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8748 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8749 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8750 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8751 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8752 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8753 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8754 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8755 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8756 " PUBLIC 'foo' 'bar.ent'>\n" 8757 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8758 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8759 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8760 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8761 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8762 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8763 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8764 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8765 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8766 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8767 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8768 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8769 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8770 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8771 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8772 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;"; 8773 int i; 8774 const int max_realloc_count = 10; 8775 8776 for (i = 0; i < max_realloc_count; i++) { 8777 reallocation_count = i; 8778 XML_SetUserData(g_parser, dtd_text); 8779 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8780 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8781 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8782 != XML_STATUS_ERROR) 8783 break; 8784 /* See comment in test_alloc_parse_xdecl() */ 8785 alloc_teardown(); 8786 alloc_setup(); 8787 } 8788 if (i == 0) 8789 fail("Parsing worked despite failing reallocation"); 8790 if (i == max_realloc_count) 8791 fail("Parsing failed at max reallocation count"); 8792 } 8793 END_TEST 8794 8795 START_TEST(test_alloc_parse_public_doctype) { 8796 const char *text 8797 = "<?xml version='1.0' encoding='utf-8'?>\n" 8798 "<!DOCTYPE doc PUBLIC '" 8799 /* 64 characters per line */ 8800 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 8801 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8802 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8803 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8804 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8805 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8806 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8807 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8808 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8809 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8810 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8811 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8812 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8813 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8814 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8815 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8816 "' 'test'>\n" 8817 "<doc></doc>"; 8818 int i; 8819 const int max_alloc_count = 25; 8820 8821 for (i = 0; i < max_alloc_count; i++) { 8822 allocation_count = i; 8823 dummy_handler_flags = 0; 8824 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8825 dummy_end_doctype_decl_handler); 8826 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8827 != XML_STATUS_ERROR) 8828 break; 8829 /* See comment in test_alloc_parse_xdecl() */ 8830 alloc_teardown(); 8831 alloc_setup(); 8832 } 8833 if (i == 0) 8834 fail("Parse succeeded despite failing allocator"); 8835 if (i == max_alloc_count) 8836 fail("Parse failed at maximum allocation count"); 8837 if (dummy_handler_flags 8838 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG 8839 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG)) 8840 fail("Doctype handler functions not called"); 8841 } 8842 END_TEST 8843 8844 START_TEST(test_alloc_parse_public_doctype_long_name) { 8845 const char *text 8846 = "<?xml version='1.0' encoding='utf-8'?>\n" 8847 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '" 8848 /* 64 characters per line */ 8849 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8850 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8851 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8852 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8853 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8854 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8855 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8856 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8857 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8858 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8859 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8860 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8861 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8862 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8863 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8864 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8865 "'>\n" 8866 "<doc></doc>"; 8867 int i; 8868 const int max_alloc_count = 25; 8869 8870 for (i = 0; i < max_alloc_count; i++) { 8871 allocation_count = i; 8872 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8873 dummy_end_doctype_decl_handler); 8874 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8875 != XML_STATUS_ERROR) 8876 break; 8877 /* See comment in test_alloc_parse_xdecl() */ 8878 alloc_teardown(); 8879 alloc_setup(); 8880 } 8881 if (i == 0) 8882 fail("Parse succeeded despite failing allocator"); 8883 if (i == max_alloc_count) 8884 fail("Parse failed at maximum allocation count"); 8885 } 8886 END_TEST 8887 8888 static int XMLCALL 8889 external_entity_alloc(XML_Parser parser, const XML_Char *context, 8890 const XML_Char *base, const XML_Char *systemId, 8891 const XML_Char *publicId) { 8892 const char *text = (const char *)XML_GetUserData(parser); 8893 XML_Parser ext_parser; 8894 int parse_res; 8895 8896 UNUSED_P(base); 8897 UNUSED_P(systemId); 8898 UNUSED_P(publicId); 8899 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8900 if (ext_parser == NULL) 8901 return XML_STATUS_ERROR; 8902 parse_res 8903 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8904 XML_ParserFree(ext_parser); 8905 return parse_res; 8906 } 8907 8908 /* Test foreign DTD handling */ 8909 START_TEST(test_alloc_set_foreign_dtd) { 8910 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 8911 "<doc>&entity;</doc>"; 8912 char text2[] = "<!ELEMENT doc (#PCDATA)*>"; 8913 int i; 8914 const int max_alloc_count = 25; 8915 8916 for (i = 0; i < max_alloc_count; i++) { 8917 allocation_count = i; 8918 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8919 XML_SetUserData(g_parser, &text2); 8920 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8921 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 8922 fail("Could not set foreign DTD"); 8923 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE) 8924 != XML_STATUS_ERROR) 8925 break; 8926 /* See comment in test_alloc_parse_xdecl() */ 8927 alloc_teardown(); 8928 alloc_setup(); 8929 } 8930 if (i == 0) 8931 fail("Parse succeeded despite failing allocator"); 8932 if (i == max_alloc_count) 8933 fail("Parse failed at maximum allocation count"); 8934 } 8935 END_TEST 8936 8937 /* Test based on ibm/valid/P32/ibm32v04.xml */ 8938 START_TEST(test_alloc_attribute_enum_value) { 8939 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8940 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8941 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 8942 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n" 8943 "<!ELEMENT a EMPTY>\n" 8944 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>"; 8945 int i; 8946 const int max_alloc_count = 30; 8947 8948 for (i = 0; i < max_alloc_count; i++) { 8949 allocation_count = i; 8950 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8951 XML_SetUserData(g_parser, dtd_text); 8952 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8953 /* An attribute list handler provokes a different code path */ 8954 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8955 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8956 != XML_STATUS_ERROR) 8957 break; 8958 /* See comment in test_alloc_parse_xdecl() */ 8959 alloc_teardown(); 8960 alloc_setup(); 8961 } 8962 if (i == 0) 8963 fail("Parse succeeded despite failing allocator"); 8964 if (i == max_alloc_count) 8965 fail("Parse failed at maximum allocation count"); 8966 } 8967 END_TEST 8968 8969 /* Test attribute enums sufficient to overflow the string pool */ 8970 START_TEST(test_alloc_realloc_attribute_enum_value) { 8971 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8972 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8973 "<animal>This is a yellow tiger</animal>"; 8974 /* We wish to define a collection of attribute enums that will 8975 * cause the string pool storing them to have to expand. This 8976 * means more than 1024 bytes, including the parentheses and 8977 * separator bars. 8978 */ 8979 char dtd_text[] 8980 = "<!ELEMENT animal (#PCDATA)*>\n" 8981 "<!ATTLIST animal thing " 8982 "(default" 8983 /* Each line is 64 characters */ 8984 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8985 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8986 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8987 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8988 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8989 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8990 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8991 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8992 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8993 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8994 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8995 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8996 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8997 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8998 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8999 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)" 9000 " 'default'>"; 9001 int i; 9002 const int max_realloc_count = 10; 9003 9004 for (i = 0; i < max_realloc_count; i++) { 9005 reallocation_count = i; 9006 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9007 XML_SetUserData(g_parser, dtd_text); 9008 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9009 /* An attribute list handler provokes a different code path */ 9010 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9011 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9012 != XML_STATUS_ERROR) 9013 break; 9014 /* See comment in test_alloc_parse_xdecl() */ 9015 alloc_teardown(); 9016 alloc_setup(); 9017 } 9018 if (i == 0) 9019 fail("Parse succeeded despite failing reallocator"); 9020 if (i == max_realloc_count) 9021 fail("Parse failed at maximum reallocation count"); 9022 } 9023 END_TEST 9024 9025 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */ 9026 START_TEST(test_alloc_realloc_implied_attribute) { 9027 /* Forcing this particular code path is a balancing act. The 9028 * addition of the closing parenthesis and terminal NUL must be 9029 * what pushes the string of enums over the 1024-byte limit, 9030 * otherwise a different code path will pick up the realloc. 9031 */ 9032 const char *text 9033 = "<!DOCTYPE doc [\n" 9034 "<!ELEMENT doc EMPTY>\n" 9035 "<!ATTLIST doc a " 9036 /* Each line is 64 characters */ 9037 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9038 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9039 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9040 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9041 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9042 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9043 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9044 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9045 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9046 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9047 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9048 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9049 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9050 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9051 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9052 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 9053 " #IMPLIED>\n" 9054 "]><doc/>"; 9055 int i; 9056 const int max_realloc_count = 10; 9057 9058 for (i = 0; i < max_realloc_count; i++) { 9059 reallocation_count = i; 9060 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9061 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9062 != XML_STATUS_ERROR) 9063 break; 9064 /* See comment in test_alloc_parse_xdecl() */ 9065 alloc_teardown(); 9066 alloc_setup(); 9067 } 9068 if (i == 0) 9069 fail("Parse succeeded despite failing reallocator"); 9070 if (i == max_realloc_count) 9071 fail("Parse failed at maximum reallocation count"); 9072 } 9073 END_TEST 9074 9075 /* Test attribute enums in a defaulted attribute forcing pool growth */ 9076 START_TEST(test_alloc_realloc_default_attribute) { 9077 /* Forcing this particular code path is a balancing act. The 9078 * addition of the closing parenthesis and terminal NUL must be 9079 * what pushes the string of enums over the 1024-byte limit, 9080 * otherwise a different code path will pick up the realloc. 9081 */ 9082 const char *text 9083 = "<!DOCTYPE doc [\n" 9084 "<!ELEMENT doc EMPTY>\n" 9085 "<!ATTLIST doc a " 9086 /* Each line is 64 characters */ 9087 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9088 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9089 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9090 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9091 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9092 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9093 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9094 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9095 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9096 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9097 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9098 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9099 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9100 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9101 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9102 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 9103 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'" 9104 ">\n]><doc/>"; 9105 int i; 9106 const int max_realloc_count = 10; 9107 9108 for (i = 0; i < max_realloc_count; i++) { 9109 reallocation_count = i; 9110 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9111 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9112 != XML_STATUS_ERROR) 9113 break; 9114 /* See comment in test_alloc_parse_xdecl() */ 9115 alloc_teardown(); 9116 alloc_setup(); 9117 } 9118 if (i == 0) 9119 fail("Parse succeeded despite failing reallocator"); 9120 if (i == max_realloc_count) 9121 fail("Parse failed at maximum reallocation count"); 9122 } 9123 END_TEST 9124 9125 /* Test long notation name with dodgy allocator */ 9126 START_TEST(test_alloc_notation) { 9127 const char *text 9128 = "<!DOCTYPE doc [\n" 9129 "<!NOTATION " 9130 /* Each line is 64 characters */ 9131 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9132 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9133 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9134 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9135 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9136 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9137 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9138 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9139 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9140 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9141 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9142 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9143 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9144 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9145 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9146 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9147 " SYSTEM 'http://example.org/n'>\n" 9148 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA " 9149 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9150 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9151 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9152 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9153 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9154 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9155 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9156 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9157 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9158 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9159 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9160 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9161 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9162 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9163 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9164 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9165 ">\n" 9166 "<!ELEMENT doc EMPTY>\n" 9167 "]>\n<doc/>"; 9168 int i; 9169 const int max_alloc_count = 20; 9170 9171 for (i = 0; i < max_alloc_count; i++) { 9172 allocation_count = i; 9173 dummy_handler_flags = 0; 9174 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9175 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 9176 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9177 != XML_STATUS_ERROR) 9178 break; 9179 /* See comment in test_alloc_parse_xdecl() */ 9180 alloc_teardown(); 9181 alloc_setup(); 9182 } 9183 if (i == 0) 9184 fail("Parse succeeded despite allocation failures"); 9185 if (i == max_alloc_count) 9186 fail("Parse failed at maximum allocation count"); 9187 if (dummy_handler_flags 9188 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG)) 9189 fail("Entity declaration handler not called"); 9190 } 9191 END_TEST 9192 9193 /* Test public notation with dodgy allocator */ 9194 START_TEST(test_alloc_public_notation) { 9195 const char *text 9196 = "<!DOCTYPE doc [\n" 9197 "<!NOTATION note PUBLIC '" 9198 /* 64 characters per line */ 9199 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9200 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9201 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9202 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9203 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9204 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9205 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9206 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9207 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9208 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9209 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9210 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9211 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9212 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9213 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9214 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9215 "' 'foo'>\n" 9216 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9217 "<!ELEMENT doc EMPTY>\n" 9218 "]>\n<doc/>"; 9219 int i; 9220 const int max_alloc_count = 20; 9221 9222 for (i = 0; i < max_alloc_count; i++) { 9223 allocation_count = i; 9224 dummy_handler_flags = 0; 9225 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9226 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9227 != XML_STATUS_ERROR) 9228 break; 9229 /* See comment in test_alloc_parse_xdecl() */ 9230 alloc_teardown(); 9231 alloc_setup(); 9232 } 9233 if (i == 0) 9234 fail("Parse succeeded despite allocation failures"); 9235 if (i == max_alloc_count) 9236 fail("Parse failed at maximum allocation count"); 9237 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9238 fail("Notation handler not called"); 9239 } 9240 END_TEST 9241 9242 /* Test public notation with dodgy allocator */ 9243 START_TEST(test_alloc_system_notation) { 9244 const char *text 9245 = "<!DOCTYPE doc [\n" 9246 "<!NOTATION note SYSTEM '" 9247 /* 64 characters per line */ 9248 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9249 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9250 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9251 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9252 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9253 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9254 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9255 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9256 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9257 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9258 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9259 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9260 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9261 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9262 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9263 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9264 "'>\n" 9265 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9266 "<!ELEMENT doc EMPTY>\n" 9267 "]>\n<doc/>"; 9268 int i; 9269 const int max_alloc_count = 20; 9270 9271 for (i = 0; i < max_alloc_count; i++) { 9272 allocation_count = i; 9273 dummy_handler_flags = 0; 9274 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9275 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9276 != XML_STATUS_ERROR) 9277 break; 9278 /* See comment in test_alloc_parse_xdecl() */ 9279 alloc_teardown(); 9280 alloc_setup(); 9281 } 9282 if (i == 0) 9283 fail("Parse succeeded despite allocation failures"); 9284 if (i == max_alloc_count) 9285 fail("Parse failed at maximum allocation count"); 9286 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9287 fail("Notation handler not called"); 9288 } 9289 END_TEST 9290 9291 START_TEST(test_alloc_nested_groups) { 9292 const char *text 9293 = "<!DOCTYPE doc [\n" 9294 "<!ELEMENT doc " 9295 /* Sixteen elements per line */ 9296 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9297 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9298 "))))))))))))))))))))))))))))))))>\n" 9299 "<!ELEMENT e EMPTY>" 9300 "]>\n" 9301 "<doc><e/></doc>"; 9302 CharData storage; 9303 int i; 9304 const int max_alloc_count = 20; 9305 9306 for (i = 0; i < max_alloc_count; i++) { 9307 allocation_count = i; 9308 CharData_Init(&storage); 9309 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9310 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9311 XML_SetUserData(g_parser, &storage); 9312 dummy_handler_flags = 0; 9313 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9314 != XML_STATUS_ERROR) 9315 break; 9316 /* See comment in test_alloc_parse_xdecl() */ 9317 alloc_teardown(); 9318 alloc_setup(); 9319 } 9320 9321 if (i == 0) 9322 fail("Parse succeeded despite failing reallocator"); 9323 if (i == max_alloc_count) 9324 fail("Parse failed at maximum reallocation count"); 9325 CharData_CheckXMLChars(&storage, XCS("doce")); 9326 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9327 fail("Element handler not fired"); 9328 } 9329 END_TEST 9330 9331 START_TEST(test_alloc_realloc_nested_groups) { 9332 const char *text 9333 = "<!DOCTYPE doc [\n" 9334 "<!ELEMENT doc " 9335 /* Sixteen elements per line */ 9336 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9337 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9338 "))))))))))))))))))))))))))))))))>\n" 9339 "<!ELEMENT e EMPTY>" 9340 "]>\n" 9341 "<doc><e/></doc>"; 9342 CharData storage; 9343 int i; 9344 const int max_realloc_count = 10; 9345 9346 for (i = 0; i < max_realloc_count; i++) { 9347 reallocation_count = i; 9348 CharData_Init(&storage); 9349 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9350 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9351 XML_SetUserData(g_parser, &storage); 9352 dummy_handler_flags = 0; 9353 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9354 != XML_STATUS_ERROR) 9355 break; 9356 /* See comment in test_alloc_parse_xdecl() */ 9357 alloc_teardown(); 9358 alloc_setup(); 9359 } 9360 9361 if (i == 0) 9362 fail("Parse succeeded despite failing reallocator"); 9363 if (i == max_realloc_count) 9364 fail("Parse failed at maximum reallocation count"); 9365 CharData_CheckXMLChars(&storage, XCS("doce")); 9366 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9367 fail("Element handler not fired"); 9368 } 9369 END_TEST 9370 9371 START_TEST(test_alloc_large_group) { 9372 const char *text = "<!DOCTYPE doc [\n" 9373 "<!ELEMENT doc (" 9374 "a1|a2|a3|a4|a5|a6|a7|a8|" 9375 "b1|b2|b3|b4|b5|b6|b7|b8|" 9376 "c1|c2|c3|c4|c5|c6|c7|c8|" 9377 "d1|d2|d3|d4|d5|d6|d7|d8|" 9378 "e1" 9379 ")+>\n" 9380 "]>\n" 9381 "<doc>\n" 9382 "<a1/>\n" 9383 "</doc>\n"; 9384 int i; 9385 const int max_alloc_count = 50; 9386 9387 for (i = 0; i < max_alloc_count; i++) { 9388 allocation_count = i; 9389 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9390 dummy_handler_flags = 0; 9391 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9392 != XML_STATUS_ERROR) 9393 break; 9394 /* See comment in test_alloc_parse_xdecl() */ 9395 alloc_teardown(); 9396 alloc_setup(); 9397 } 9398 if (i == 0) 9399 fail("Parse succeeded despite failing allocator"); 9400 if (i == max_alloc_count) 9401 fail("Parse failed at maximum allocation count"); 9402 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9403 fail("Element handler flag not raised"); 9404 } 9405 END_TEST 9406 9407 START_TEST(test_alloc_realloc_group_choice) { 9408 const char *text = "<!DOCTYPE doc [\n" 9409 "<!ELEMENT doc (" 9410 "a1|a2|a3|a4|a5|a6|a7|a8|" 9411 "b1|b2|b3|b4|b5|b6|b7|b8|" 9412 "c1|c2|c3|c4|c5|c6|c7|c8|" 9413 "d1|d2|d3|d4|d5|d6|d7|d8|" 9414 "e1" 9415 ")+>\n" 9416 "]>\n" 9417 "<doc>\n" 9418 "<a1/>\n" 9419 "<b2 attr='foo'>This is a foo</b2>\n" 9420 "<c3></c3>\n" 9421 "</doc>\n"; 9422 int i; 9423 const int max_realloc_count = 10; 9424 9425 for (i = 0; i < max_realloc_count; i++) { 9426 reallocation_count = i; 9427 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9428 dummy_handler_flags = 0; 9429 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9430 != XML_STATUS_ERROR) 9431 break; 9432 /* See comment in test_alloc_parse_xdecl() */ 9433 alloc_teardown(); 9434 alloc_setup(); 9435 } 9436 if (i == 0) 9437 fail("Parse succeeded despite failing reallocator"); 9438 if (i == max_realloc_count) 9439 fail("Parse failed at maximum reallocation count"); 9440 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9441 fail("Element handler flag not raised"); 9442 } 9443 END_TEST 9444 9445 START_TEST(test_alloc_pi_in_epilog) { 9446 const char *text = "<doc></doc>\n" 9447 "<?pi in epilog?>"; 9448 int i; 9449 const int max_alloc_count = 15; 9450 9451 for (i = 0; i < max_alloc_count; i++) { 9452 allocation_count = i; 9453 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 9454 dummy_handler_flags = 0; 9455 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9456 != XML_STATUS_ERROR) 9457 break; 9458 /* See comment in test_alloc_parse_xdecl() */ 9459 alloc_teardown(); 9460 alloc_setup(); 9461 } 9462 if (i == 0) 9463 fail("Parse completed despite failing allocator"); 9464 if (i == max_alloc_count) 9465 fail("Parse failed at maximum allocation count"); 9466 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG) 9467 fail("Processing instruction handler not invoked"); 9468 } 9469 END_TEST 9470 9471 START_TEST(test_alloc_comment_in_epilog) { 9472 const char *text = "<doc></doc>\n" 9473 "<!-- comment in epilog -->"; 9474 int i; 9475 const int max_alloc_count = 15; 9476 9477 for (i = 0; i < max_alloc_count; i++) { 9478 allocation_count = i; 9479 XML_SetCommentHandler(g_parser, dummy_comment_handler); 9480 dummy_handler_flags = 0; 9481 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9482 != XML_STATUS_ERROR) 9483 break; 9484 /* See comment in test_alloc_parse_xdecl() */ 9485 alloc_teardown(); 9486 alloc_setup(); 9487 } 9488 if (i == 0) 9489 fail("Parse completed despite failing allocator"); 9490 if (i == max_alloc_count) 9491 fail("Parse failed at maximum allocation count"); 9492 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG) 9493 fail("Processing instruction handler not invoked"); 9494 } 9495 END_TEST 9496 9497 START_TEST(test_alloc_realloc_long_attribute_value) { 9498 const char *text 9499 = "<!DOCTYPE doc [<!ENTITY foo '" 9500 /* Each line is 64 characters */ 9501 "This entity will be substituted as an attribute value, and is " 9502 "calculated to be exactly long enough that the terminating NUL " 9503 "that the library adds internally will trigger the string pool to" 9504 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9505 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9506 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9507 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9508 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9509 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9510 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9511 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9512 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9513 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9514 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9515 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9516 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9517 "'>]>\n" 9518 "<doc a='&foo;'></doc>"; 9519 int i; 9520 const int max_realloc_count = 10; 9521 9522 for (i = 0; i < max_realloc_count; i++) { 9523 reallocation_count = i; 9524 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9525 != XML_STATUS_ERROR) 9526 break; 9527 /* See comment in test_alloc_parse_xdecl() */ 9528 alloc_teardown(); 9529 alloc_setup(); 9530 } 9531 if (i == 0) 9532 fail("Parse succeeded despite failing reallocator"); 9533 if (i == max_realloc_count) 9534 fail("Parse failed at maximum reallocation count"); 9535 } 9536 END_TEST 9537 9538 START_TEST(test_alloc_attribute_whitespace) { 9539 const char *text = "<doc a=' '></doc>"; 9540 int i; 9541 const int max_alloc_count = 15; 9542 9543 for (i = 0; i < max_alloc_count; i++) { 9544 allocation_count = i; 9545 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9546 != XML_STATUS_ERROR) 9547 break; 9548 /* See comment in test_alloc_parse_xdecl() */ 9549 alloc_teardown(); 9550 alloc_setup(); 9551 } 9552 if (i == 0) 9553 fail("Parse succeeded despite failing allocator"); 9554 if (i == max_alloc_count) 9555 fail("Parse failed at maximum allocation count"); 9556 } 9557 END_TEST 9558 9559 START_TEST(test_alloc_attribute_predefined_entity) { 9560 const char *text = "<doc a='&'></doc>"; 9561 int i; 9562 const int max_alloc_count = 15; 9563 9564 for (i = 0; i < max_alloc_count; i++) { 9565 allocation_count = i; 9566 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9567 != XML_STATUS_ERROR) 9568 break; 9569 /* See comment in test_alloc_parse_xdecl() */ 9570 alloc_teardown(); 9571 alloc_setup(); 9572 } 9573 if (i == 0) 9574 fail("Parse succeeded despite failing allocator"); 9575 if (i == max_alloc_count) 9576 fail("Parse failed at maximum allocation count"); 9577 } 9578 END_TEST 9579 9580 /* Test that a character reference at the end of a suitably long 9581 * default value for an attribute can trigger pool growth, and recovers 9582 * if the allocator fails on it. 9583 */ 9584 START_TEST(test_alloc_long_attr_default_with_char_ref) { 9585 const char *text 9586 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '" 9587 /* 64 characters per line */ 9588 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9589 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9590 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9591 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9592 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9593 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9594 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9595 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9596 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9597 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9598 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9599 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9600 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9601 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9602 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9603 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI" 9604 "1'>]>\n" 9605 "<doc/>"; 9606 int i; 9607 const int max_alloc_count = 20; 9608 9609 for (i = 0; i < max_alloc_count; i++) { 9610 allocation_count = i; 9611 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9612 != XML_STATUS_ERROR) 9613 break; 9614 /* See comment in test_alloc_parse_xdecl() */ 9615 alloc_teardown(); 9616 alloc_setup(); 9617 } 9618 if (i == 0) 9619 fail("Parse succeeded despite failing allocator"); 9620 if (i == max_alloc_count) 9621 fail("Parse failed at maximum allocation count"); 9622 } 9623 END_TEST 9624 9625 /* Test that a long character reference substitution triggers a pool 9626 * expansion correctly for an attribute value. 9627 */ 9628 START_TEST(test_alloc_long_attr_value) { 9629 const char *text 9630 = "<!DOCTYPE test [<!ENTITY foo '\n" 9631 /* 64 characters per line */ 9632 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9633 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9634 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9635 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9636 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9637 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9638 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9639 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9640 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9641 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9642 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9643 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9644 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9645 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9646 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9647 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9648 "'>]>\n" 9649 "<test a='&foo;'/>"; 9650 int i; 9651 const int max_alloc_count = 25; 9652 9653 for (i = 0; i < max_alloc_count; i++) { 9654 allocation_count = i; 9655 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9656 != XML_STATUS_ERROR) 9657 break; 9658 /* See comment in test_alloc_parse_xdecl() */ 9659 alloc_teardown(); 9660 alloc_setup(); 9661 } 9662 if (i == 0) 9663 fail("Parse succeeded despite failing allocator"); 9664 if (i == max_alloc_count) 9665 fail("Parse failed at maximum allocation count"); 9666 } 9667 END_TEST 9668 9669 /* Test that an error in a nested parameter entity substitution is 9670 * handled correctly. It seems unlikely that the code path being 9671 * exercised can be reached purely by carefully crafted XML, but an 9672 * allocation error in the right place will definitely do it. 9673 */ 9674 START_TEST(test_alloc_nested_entities) { 9675 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 9676 "<doc />"; 9677 ExtFaults test_data 9678 = {"<!ENTITY % pe1 '" 9679 /* 64 characters per line */ 9680 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9681 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9682 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9683 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9684 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9685 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9686 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9687 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9688 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9689 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9690 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9691 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9692 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9693 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9694 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9695 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9696 "'>\n" 9697 "<!ENTITY % pe2 '%pe1;'>\n" 9698 "%pe2;", 9699 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY}; 9700 9701 /* Causes an allocation error in a nested storeEntityValue() */ 9702 allocation_count = 12; 9703 XML_SetUserData(g_parser, &test_data); 9704 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9705 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 9706 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 9707 "Entity allocation failure not noted"); 9708 } 9709 END_TEST 9710 9711 START_TEST(test_alloc_realloc_param_entity_newline) { 9712 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9713 "<doc/>"; 9714 char dtd_text[] 9715 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9716 /* 64 characters per line */ 9717 "This default value is carefully crafted so that the carriage " 9718 "return right at the end of the entity string causes an internal " 9719 "string pool to have to grow. This allows us to test the alloc " 9720 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9721 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9722 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9723 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9724 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9725 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9726 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9727 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9728 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9729 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9730 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9731 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9732 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE" 9733 "\">\n'>" 9734 "%pe;\n"; 9735 int i; 9736 const int max_realloc_count = 5; 9737 9738 for (i = 0; i < max_realloc_count; i++) { 9739 reallocation_count = i; 9740 XML_SetUserData(g_parser, dtd_text); 9741 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9742 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9743 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9744 != XML_STATUS_ERROR) 9745 break; 9746 /* See comment in test_alloc_parse_xdecl() */ 9747 alloc_teardown(); 9748 alloc_setup(); 9749 } 9750 if (i == 0) 9751 fail("Parse succeeded despite failing reallocator"); 9752 if (i == max_realloc_count) 9753 fail("Parse failed at maximum reallocation count"); 9754 } 9755 END_TEST 9756 9757 START_TEST(test_alloc_realloc_ce_extends_pe) { 9758 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9759 "<doc/>"; 9760 char dtd_text[] 9761 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9762 /* 64 characters per line */ 9763 "This default value is carefully crafted so that the character " 9764 "entity at the end causes an internal string pool to have to " 9765 "grow. This allows us to test the allocation failure path from " 9766 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9767 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9768 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9769 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9770 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9771 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9772 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9773 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9774 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9775 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9776 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9777 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9778 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ" 9779 "\">\n'>" 9780 "%pe;\n"; 9781 int i; 9782 const int max_realloc_count = 5; 9783 9784 for (i = 0; i < max_realloc_count; i++) { 9785 reallocation_count = i; 9786 XML_SetUserData(g_parser, dtd_text); 9787 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9788 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9789 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9790 != XML_STATUS_ERROR) 9791 break; 9792 /* See comment in test_alloc_parse_xdecl() */ 9793 alloc_teardown(); 9794 alloc_setup(); 9795 } 9796 if (i == 0) 9797 fail("Parse succeeded despite failing reallocator"); 9798 if (i == max_realloc_count) 9799 fail("Parse failed at maximum reallocation count"); 9800 } 9801 END_TEST 9802 9803 START_TEST(test_alloc_realloc_attributes) { 9804 const char *text = "<!DOCTYPE doc [\n" 9805 " <!ATTLIST doc\n" 9806 " a1 (a|b|c) 'a'\n" 9807 " a2 (foo|bar) #IMPLIED\n" 9808 " a3 NMTOKEN #IMPLIED\n" 9809 " a4 NMTOKENS #IMPLIED\n" 9810 " a5 ID #IMPLIED\n" 9811 " a6 IDREF #IMPLIED\n" 9812 " a7 IDREFS #IMPLIED\n" 9813 " a8 ENTITY #IMPLIED\n" 9814 " a9 ENTITIES #IMPLIED\n" 9815 " a10 CDATA #IMPLIED\n" 9816 " >]>\n" 9817 "<doc>wombat</doc>\n"; 9818 int i; 9819 const int max_realloc_count = 5; 9820 9821 for (i = 0; i < max_realloc_count; i++) { 9822 reallocation_count = i; 9823 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9824 != XML_STATUS_ERROR) 9825 break; 9826 /* See comment in test_alloc_parse_xdecl() */ 9827 alloc_teardown(); 9828 alloc_setup(); 9829 } 9830 9831 if (i == 0) 9832 fail("Parse succeeded despite failing reallocator"); 9833 if (i == max_realloc_count) 9834 fail("Parse failed at maximum reallocation count"); 9835 } 9836 END_TEST 9837 9838 START_TEST(test_alloc_long_doc_name) { 9839 const char *text = 9840 /* 64 characters per line */ 9841 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr" 9842 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9843 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9844 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9845 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9846 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9847 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9848 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9849 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9850 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9851 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9852 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9853 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9854 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9855 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9856 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9857 " a='1'/>"; 9858 int i; 9859 const int max_alloc_count = 20; 9860 9861 for (i = 0; i < max_alloc_count; i++) { 9862 allocation_count = i; 9863 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9864 != XML_STATUS_ERROR) 9865 break; 9866 /* See comment in test_alloc_parse_xdecl() */ 9867 alloc_teardown(); 9868 alloc_setup(); 9869 } 9870 if (i == 0) 9871 fail("Parsing worked despite failing reallocations"); 9872 else if (i == max_alloc_count) 9873 fail("Parsing failed even at max reallocation count"); 9874 } 9875 END_TEST 9876 9877 START_TEST(test_alloc_long_base) { 9878 const char *text = "<!DOCTYPE doc [\n" 9879 " <!ENTITY e SYSTEM 'foo'>\n" 9880 "]>\n" 9881 "<doc>&e;</doc>"; 9882 char entity_text[] = "Hello world"; 9883 const XML_Char *base = 9884 /* 64 characters per line */ 9885 /* clang-format off */ 9886 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t") 9887 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9888 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9889 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9890 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9891 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9892 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9893 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9894 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9895 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9896 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9897 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9898 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9899 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9900 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9901 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"); 9902 /* clang-format on */ 9903 int i; 9904 const int max_alloc_count = 25; 9905 9906 for (i = 0; i < max_alloc_count; i++) { 9907 allocation_count = i; 9908 XML_SetUserData(g_parser, entity_text); 9909 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9910 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9911 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) { 9912 XML_ParserReset(g_parser, NULL); 9913 continue; 9914 } 9915 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9916 != XML_STATUS_ERROR) 9917 break; 9918 /* See comment in test_alloc_parse_xdecl() */ 9919 alloc_teardown(); 9920 alloc_setup(); 9921 } 9922 if (i == 0) 9923 fail("Parsing worked despite failing allocations"); 9924 else if (i == max_alloc_count) 9925 fail("Parsing failed even at max allocation count"); 9926 } 9927 END_TEST 9928 9929 START_TEST(test_alloc_long_public_id) { 9930 const char *text 9931 = "<!DOCTYPE doc [\n" 9932 " <!ENTITY e PUBLIC '" 9933 /* 64 characters per line */ 9934 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec" 9935 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9936 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9937 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9938 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9939 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9940 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9941 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9942 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9943 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9944 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9945 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9946 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9947 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9948 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9949 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9950 "' 'bar'>\n" 9951 "]>\n" 9952 "<doc>&e;</doc>"; 9953 char entity_text[] = "Hello world"; 9954 int i; 9955 const int max_alloc_count = 40; 9956 9957 for (i = 0; i < max_alloc_count; i++) { 9958 allocation_count = i; 9959 XML_SetUserData(g_parser, entity_text); 9960 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9961 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9962 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9963 != XML_STATUS_ERROR) 9964 break; 9965 /* See comment in test_alloc_parse_xdecl() */ 9966 alloc_teardown(); 9967 alloc_setup(); 9968 } 9969 if (i == 0) 9970 fail("Parsing worked despite failing allocations"); 9971 else if (i == max_alloc_count) 9972 fail("Parsing failed even at max allocation count"); 9973 } 9974 END_TEST 9975 9976 START_TEST(test_alloc_long_entity_value) { 9977 const char *text 9978 = "<!DOCTYPE doc [\n" 9979 " <!ENTITY e1 '" 9980 /* 64 characters per line */ 9981 "Long entity value that should provoke a string pool to grow whil" 9982 "e setting up to parse the external entity below. xyz0123456789AB" 9983 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9984 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9985 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9986 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9987 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9988 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9989 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9990 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9991 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9992 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9993 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9994 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9995 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9996 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9997 "'>\n" 9998 " <!ENTITY e2 SYSTEM 'bar'>\n" 9999 "]>\n" 10000 "<doc>&e2;</doc>"; 10001 char entity_text[] = "Hello world"; 10002 int i; 10003 const int max_alloc_count = 40; 10004 10005 for (i = 0; i < max_alloc_count; i++) { 10006 allocation_count = i; 10007 XML_SetUserData(g_parser, entity_text); 10008 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10009 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 10010 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10011 != XML_STATUS_ERROR) 10012 break; 10013 /* See comment in test_alloc_parse_xdecl() */ 10014 alloc_teardown(); 10015 alloc_setup(); 10016 } 10017 if (i == 0) 10018 fail("Parsing worked despite failing allocations"); 10019 else if (i == max_alloc_count) 10020 fail("Parsing failed even at max allocation count"); 10021 } 10022 END_TEST 10023 10024 START_TEST(test_alloc_long_notation) { 10025 const char *text 10026 = "<!DOCTYPE doc [\n" 10027 " <!NOTATION note SYSTEM '" 10028 /* 64 characters per line */ 10029 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 10030 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10031 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10032 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10033 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10034 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10035 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10036 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10037 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10038 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10039 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10040 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10041 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10042 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10043 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10044 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10045 "'>\n" 10046 " <!ENTITY e1 SYSTEM 'foo' NDATA " 10047 /* 64 characters per line */ 10048 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 10049 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10050 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10051 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10052 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10053 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10054 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10055 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10056 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10057 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10058 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10059 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10060 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10061 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10062 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10063 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10064 ">\n" 10065 " <!ENTITY e2 SYSTEM 'bar'>\n" 10066 "]>\n" 10067 "<doc>&e2;</doc>"; 10068 ExtOption options[] 10069 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}}; 10070 int i; 10071 const int max_alloc_count = 40; 10072 10073 for (i = 0; i < max_alloc_count; i++) { 10074 allocation_count = i; 10075 XML_SetUserData(g_parser, options); 10076 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10077 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10078 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10079 != XML_STATUS_ERROR) 10080 break; 10081 10082 /* See comment in test_alloc_parse_xdecl() */ 10083 alloc_teardown(); 10084 alloc_setup(); 10085 } 10086 if (i == 0) 10087 fail("Parsing worked despite failing allocations"); 10088 else if (i == max_alloc_count) 10089 fail("Parsing failed even at max allocation count"); 10090 } 10091 END_TEST 10092 10093 static void 10094 nsalloc_setup(void) { 10095 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 10096 XML_Char ns_sep[2] = {' ', '\0'}; 10097 10098 /* Ensure the parser creation will go through */ 10099 allocation_count = ALLOC_ALWAYS_SUCCEED; 10100 reallocation_count = REALLOC_ALWAYS_SUCCEED; 10101 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep); 10102 if (g_parser == NULL) 10103 fail("Parser not created"); 10104 } 10105 10106 static void 10107 nsalloc_teardown(void) { 10108 basic_teardown(); 10109 } 10110 10111 /* Test the effects of allocation failure in simple namespace parsing. 10112 * Based on test_ns_default_with_empty_uri() 10113 */ 10114 START_TEST(test_nsalloc_xmlns) { 10115 const char *text = "<doc xmlns='http://example.org/'>\n" 10116 " <e xmlns=''/>\n" 10117 "</doc>"; 10118 unsigned int i; 10119 const unsigned int max_alloc_count = 30; 10120 10121 for (i = 0; i < max_alloc_count; i++) { 10122 allocation_count = i; 10123 /* Exercise more code paths with a default handler */ 10124 XML_SetDefaultHandler(g_parser, dummy_default_handler); 10125 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10126 != XML_STATUS_ERROR) 10127 break; 10128 /* Resetting the parser is insufficient, because some memory 10129 * allocations are cached within the parser. Instead we use 10130 * the teardown and setup routines to ensure that we have the 10131 * right sort of parser back in our hands. 10132 */ 10133 nsalloc_teardown(); 10134 nsalloc_setup(); 10135 } 10136 if (i == 0) 10137 fail("Parsing worked despite failing allocations"); 10138 else if (i == max_alloc_count) 10139 fail("Parsing failed even at maximum allocation count"); 10140 } 10141 END_TEST 10142 10143 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */ 10144 START_TEST(test_nsalloc_parse_buffer) { 10145 const char *text = "<doc>Hello</doc>"; 10146 void *buffer; 10147 10148 /* Try a parse before the start of the world */ 10149 /* (Exercises new code path) */ 10150 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10151 fail("Pre-init XML_ParseBuffer not faulted"); 10152 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER) 10153 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10154 10155 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */); 10156 if (buffer == NULL) 10157 fail("Could not acquire parse buffer"); 10158 10159 allocation_count = 0; 10160 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10161 fail("Pre-init XML_ParseBuffer not faulted"); 10162 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY) 10163 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10164 10165 /* Now with actual memory allocation */ 10166 allocation_count = ALLOC_ALWAYS_SUCCEED; 10167 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK) 10168 xml_failure(g_parser); 10169 10170 /* Check that resuming an unsuspended parser is faulted */ 10171 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 10172 fail("Resuming unsuspended parser not faulted"); 10173 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED) 10174 xml_failure(g_parser); 10175 10176 /* Get the parser into suspended state */ 10177 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 10178 resumable = XML_TRUE; 10179 buffer = XML_GetBuffer(g_parser, (int)strlen(text)); 10180 if (buffer == NULL) 10181 fail("Could not acquire parse buffer"); 10182 assert(buffer != NULL); 10183 memcpy(buffer, text, strlen(text)); 10184 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10185 != XML_STATUS_SUSPENDED) 10186 xml_failure(g_parser); 10187 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 10188 xml_failure(g_parser); 10189 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10190 != XML_STATUS_ERROR) 10191 fail("Suspended XML_ParseBuffer not faulted"); 10192 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 10193 xml_failure(g_parser); 10194 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10195 fail("Suspended XML_GetBuffer not faulted"); 10196 10197 /* Get it going again and complete the world */ 10198 XML_SetCharacterDataHandler(g_parser, NULL); 10199 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 10200 xml_failure(g_parser); 10201 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10202 != XML_STATUS_ERROR) 10203 fail("Post-finishing XML_ParseBuffer not faulted"); 10204 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED) 10205 xml_failure(g_parser); 10206 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10207 fail("Post-finishing XML_GetBuffer not faulted"); 10208 } 10209 END_TEST 10210 10211 /* Check handling of long prefix names (pool growth) */ 10212 START_TEST(test_nsalloc_long_prefix) { 10213 const char *text 10214 = "<" 10215 /* 64 characters per line */ 10216 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10217 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10218 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10219 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10232 ":foo xmlns:" 10233 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10234 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10235 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10236 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10237 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10238 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10239 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10240 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10241 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10242 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10243 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10244 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10245 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10246 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10247 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10248 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10249 "='http://example.org/'>" 10250 "</" 10251 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10252 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10253 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10254 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10255 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10256 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10257 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10258 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10259 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10260 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10261 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10262 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10263 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10264 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10265 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10266 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10267 ":foo>"; 10268 int i; 10269 const int max_alloc_count = 40; 10270 10271 for (i = 0; i < max_alloc_count; i++) { 10272 allocation_count = i; 10273 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10274 != XML_STATUS_ERROR) 10275 break; 10276 /* See comment in test_nsalloc_xmlns() */ 10277 nsalloc_teardown(); 10278 nsalloc_setup(); 10279 } 10280 if (i == 0) 10281 fail("Parsing worked despite failing allocations"); 10282 else if (i == max_alloc_count) 10283 fail("Parsing failed even at max allocation count"); 10284 } 10285 END_TEST 10286 10287 /* Check handling of long uri names (pool growth) */ 10288 START_TEST(test_nsalloc_long_uri) { 10289 const char *text 10290 = "<foo:e xmlns:foo='http://example.org/" 10291 /* 64 characters per line */ 10292 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10293 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10294 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10295 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10296 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10297 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10298 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10299 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10300 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10301 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10302 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10303 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10304 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10305 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10306 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10307 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10308 "' bar:a='12'\n" 10309 "xmlns:bar='http://example.org/" 10310 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10311 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10312 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10313 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10314 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10315 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10316 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10317 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10318 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10319 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10320 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10321 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10322 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10323 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10324 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10325 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10326 "'>" 10327 "</foo:e>"; 10328 int i; 10329 const int max_alloc_count = 40; 10330 10331 for (i = 0; i < max_alloc_count; i++) { 10332 allocation_count = i; 10333 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10334 != XML_STATUS_ERROR) 10335 break; 10336 /* See comment in test_nsalloc_xmlns() */ 10337 nsalloc_teardown(); 10338 nsalloc_setup(); 10339 } 10340 if (i == 0) 10341 fail("Parsing worked despite failing allocations"); 10342 else if (i == max_alloc_count) 10343 fail("Parsing failed even at max allocation count"); 10344 } 10345 END_TEST 10346 10347 /* Test handling of long attribute names with prefixes */ 10348 START_TEST(test_nsalloc_long_attr) { 10349 const char *text 10350 = "<foo:e xmlns:foo='http://example.org/' bar:" 10351 /* 64 characters per line */ 10352 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10354 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10355 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10356 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10357 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10358 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10359 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10360 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10361 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10362 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10363 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10364 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10365 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10366 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10367 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10368 "='12'\n" 10369 "xmlns:bar='http://example.org/'>" 10370 "</foo:e>"; 10371 int i; 10372 const int max_alloc_count = 40; 10373 10374 for (i = 0; i < max_alloc_count; i++) { 10375 allocation_count = i; 10376 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10377 != XML_STATUS_ERROR) 10378 break; 10379 /* See comment in test_nsalloc_xmlns() */ 10380 nsalloc_teardown(); 10381 nsalloc_setup(); 10382 } 10383 if (i == 0) 10384 fail("Parsing worked despite failing allocations"); 10385 else if (i == max_alloc_count) 10386 fail("Parsing failed even at max allocation count"); 10387 } 10388 END_TEST 10389 10390 /* Test handling of an attribute name with a long namespace prefix */ 10391 START_TEST(test_nsalloc_long_attr_prefix) { 10392 const char *text 10393 = "<foo:e xmlns:foo='http://example.org/' " 10394 /* 64 characters per line */ 10395 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10396 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10397 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10398 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10399 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10400 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10401 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10402 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10403 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10404 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10405 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10406 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10407 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10408 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10409 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10410 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10411 ":a='12'\n" 10412 "xmlns:" 10413 /* 64 characters per line */ 10414 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10415 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10416 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10417 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10418 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10419 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10420 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10421 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10422 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10423 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10424 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10425 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10426 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10427 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10428 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10429 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10430 "='http://example.org/'>" 10431 "</foo:e>"; 10432 const XML_Char *elemstr[] = { 10433 /* clang-format off */ 10434 XCS("http://example.org/ e foo"), 10435 XCS("http://example.org/ a ") 10436 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10437 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10438 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10439 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10440 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10441 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10442 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10443 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10444 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10445 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10446 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10447 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10448 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10449 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10450 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10451 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10452 /* clang-format on */ 10453 }; 10454 int i; 10455 const int max_alloc_count = 40; 10456 10457 for (i = 0; i < max_alloc_count; i++) { 10458 allocation_count = i; 10459 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10460 XML_SetUserData(g_parser, (void *)elemstr); 10461 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10462 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10463 != XML_STATUS_ERROR) 10464 break; 10465 /* See comment in test_nsalloc_xmlns() */ 10466 nsalloc_teardown(); 10467 nsalloc_setup(); 10468 } 10469 if (i == 0) 10470 fail("Parsing worked despite failing allocations"); 10471 else if (i == max_alloc_count) 10472 fail("Parsing failed even at max allocation count"); 10473 } 10474 END_TEST 10475 10476 /* Test attribute handling in the face of a dodgy reallocator */ 10477 START_TEST(test_nsalloc_realloc_attributes) { 10478 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 10479 " xmlns:bar='http://example.org/'>" 10480 "</foo:e>"; 10481 int i; 10482 const int max_realloc_count = 10; 10483 10484 for (i = 0; i < max_realloc_count; i++) { 10485 reallocation_count = i; 10486 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10487 != XML_STATUS_ERROR) 10488 break; 10489 /* See comment in test_nsalloc_xmlns() */ 10490 nsalloc_teardown(); 10491 nsalloc_setup(); 10492 } 10493 if (i == 0) 10494 fail("Parsing worked despite failing reallocations"); 10495 else if (i == max_realloc_count) 10496 fail("Parsing failed at max reallocation count"); 10497 } 10498 END_TEST 10499 10500 /* Test long element names with namespaces under a failing allocator */ 10501 START_TEST(test_nsalloc_long_element) { 10502 const char *text 10503 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 10504 " xmlns:foo='http://example.org/' bar:a='12'\n" 10505 " xmlns:bar='http://example.org/'>" 10506 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 10507 const XML_Char *elemstr[] 10508 = {XCS("http://example.org/") 10509 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 10510 XCS("http://example.org/ a bar")}; 10511 int i; 10512 const int max_alloc_count = 30; 10513 10514 for (i = 0; i < max_alloc_count; i++) { 10515 allocation_count = i; 10516 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10517 XML_SetUserData(g_parser, (void *)elemstr); 10518 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10519 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10520 != XML_STATUS_ERROR) 10521 break; 10522 /* See comment in test_nsalloc_xmlns() */ 10523 nsalloc_teardown(); 10524 nsalloc_setup(); 10525 } 10526 if (i == 0) 10527 fail("Parsing worked despite failing reallocations"); 10528 else if (i == max_alloc_count) 10529 fail("Parsing failed at max reallocation count"); 10530 } 10531 END_TEST 10532 10533 /* Test the effects of reallocation failure when reassigning a 10534 * binding. 10535 * 10536 * XML_ParserReset does not free the BINDING structures used by a 10537 * parser, but instead adds them to an internal free list to be reused 10538 * as necessary. Likewise the URI buffers allocated for the binding 10539 * aren't freed, but kept attached to their existing binding. If the 10540 * new binding has a longer URI, it will need reallocation. This test 10541 * provokes that reallocation, and tests the control path if it fails. 10542 */ 10543 START_TEST(test_nsalloc_realloc_binding_uri) { 10544 const char *first = "<doc xmlns='http://example.org/'>\n" 10545 " <e xmlns='' />\n" 10546 "</doc>"; 10547 const char *second 10548 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n" 10549 " <e xmlns='' />\n" 10550 "</doc>"; 10551 unsigned i; 10552 const unsigned max_realloc_count = 10; 10553 10554 /* First, do a full parse that will leave bindings around */ 10555 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE) 10556 == XML_STATUS_ERROR) 10557 xml_failure(g_parser); 10558 10559 /* Now repeat with a longer URI and a duff reallocator */ 10560 for (i = 0; i < max_realloc_count; i++) { 10561 XML_ParserReset(g_parser, NULL); 10562 reallocation_count = i; 10563 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE) 10564 != XML_STATUS_ERROR) 10565 break; 10566 } 10567 if (i == 0) 10568 fail("Parsing worked despite failing reallocation"); 10569 else if (i == max_realloc_count) 10570 fail("Parsing failed at max reallocation count"); 10571 } 10572 END_TEST 10573 10574 /* Check handling of long prefix names (pool growth) */ 10575 START_TEST(test_nsalloc_realloc_long_prefix) { 10576 const char *text 10577 = "<" 10578 /* 64 characters per line */ 10579 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10580 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10581 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10582 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 ":foo xmlns:" 10596 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10597 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10598 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10599 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 "='http://example.org/'>" 10613 "</" 10614 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10615 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10616 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10617 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 ":foo>"; 10631 int i; 10632 const int max_realloc_count = 12; 10633 10634 for (i = 0; i < max_realloc_count; i++) { 10635 reallocation_count = i; 10636 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10637 != XML_STATUS_ERROR) 10638 break; 10639 /* See comment in test_nsalloc_xmlns() */ 10640 nsalloc_teardown(); 10641 nsalloc_setup(); 10642 } 10643 if (i == 0) 10644 fail("Parsing worked despite failing reallocations"); 10645 else if (i == max_realloc_count) 10646 fail("Parsing failed even at max reallocation count"); 10647 } 10648 END_TEST 10649 10650 /* Check handling of even long prefix names (different code path) */ 10651 START_TEST(test_nsalloc_realloc_longer_prefix) { 10652 const char *text 10653 = "<" 10654 /* 64 characters per line */ 10655 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10656 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10657 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 "Q:foo xmlns:" 10672 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10673 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10674 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 "Q='http://example.org/'>" 10689 "</" 10690 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10691 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10692 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10693 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 "Q:foo>"; 10707 int i; 10708 const int max_realloc_count = 12; 10709 10710 for (i = 0; i < max_realloc_count; i++) { 10711 reallocation_count = i; 10712 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10713 != XML_STATUS_ERROR) 10714 break; 10715 /* See comment in test_nsalloc_xmlns() */ 10716 nsalloc_teardown(); 10717 nsalloc_setup(); 10718 } 10719 if (i == 0) 10720 fail("Parsing worked despite failing reallocations"); 10721 else if (i == max_realloc_count) 10722 fail("Parsing failed even at max reallocation count"); 10723 } 10724 END_TEST 10725 10726 START_TEST(test_nsalloc_long_namespace) { 10727 const char *text1 10728 = "<" 10729 /* 64 characters per line */ 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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10746 ":e xmlns:" 10747 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10748 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10749 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10750 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10751 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10752 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10753 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10754 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10755 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10756 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10757 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10758 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10759 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10760 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10761 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10762 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10763 "='http://example.org/'>\n"; 10764 const char *text2 10765 = "<" 10766 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10767 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10768 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10769 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10770 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10771 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10772 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10773 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10774 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10777 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10778 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10782 ":f " 10783 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10784 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10785 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10786 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10787 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10788 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10789 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10790 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10791 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10792 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10793 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10794 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10795 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10796 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10797 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10798 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10799 ":attr='foo'/>\n" 10800 "</" 10801 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10802 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10803 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10804 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10805 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10806 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10807 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10808 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10809 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10810 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10811 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10812 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10813 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10814 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10815 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10816 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10817 ":e>"; 10818 int i; 10819 const int max_alloc_count = 40; 10820 10821 for (i = 0; i < max_alloc_count; i++) { 10822 allocation_count = i; 10823 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 10824 != XML_STATUS_ERROR 10825 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 10826 XML_TRUE) 10827 != XML_STATUS_ERROR) 10828 break; 10829 /* See comment in test_nsalloc_xmlns() */ 10830 nsalloc_teardown(); 10831 nsalloc_setup(); 10832 } 10833 if (i == 0) 10834 fail("Parsing worked despite failing allocations"); 10835 else if (i == max_alloc_count) 10836 fail("Parsing failed even at max allocation count"); 10837 } 10838 END_TEST 10839 10840 /* Using a slightly shorter namespace name provokes allocations in 10841 * slightly different places in the code. 10842 */ 10843 START_TEST(test_nsalloc_less_long_namespace) { 10844 const char *text 10845 = "<" 10846 /* 64 characters per line */ 10847 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10848 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10849 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10850 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10851 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10852 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10853 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10854 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10855 ":e xmlns:" 10856 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10857 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10858 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10859 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10860 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10861 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10862 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10863 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10864 "='http://example.org/'>\n" 10865 "<" 10866 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10867 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10868 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10869 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10870 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10871 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10872 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10873 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10874 ":f " 10875 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10876 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10877 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10878 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10879 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10880 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10881 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10882 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10883 ":att='foo'/>\n" 10884 "</" 10885 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10886 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10887 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10888 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10889 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10890 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10891 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10892 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10893 ":e>"; 10894 int i; 10895 const int max_alloc_count = 40; 10896 10897 for (i = 0; i < max_alloc_count; i++) { 10898 allocation_count = i; 10899 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10900 != XML_STATUS_ERROR) 10901 break; 10902 /* See comment in test_nsalloc_xmlns() */ 10903 nsalloc_teardown(); 10904 nsalloc_setup(); 10905 } 10906 if (i == 0) 10907 fail("Parsing worked despite failing allocations"); 10908 else if (i == max_alloc_count) 10909 fail("Parsing failed even at max allocation count"); 10910 } 10911 END_TEST 10912 10913 START_TEST(test_nsalloc_long_context) { 10914 const char *text 10915 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10916 " <!ATTLIST doc baz ID #REQUIRED>\n" 10917 " <!ENTITY en SYSTEM 'bar'>\n" 10918 "]>\n" 10919 "<doc xmlns='http://example.org/" 10920 /* 64 characters per line */ 10921 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10922 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10923 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10924 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10925 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10926 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10927 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 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/ABCDEFGHIJKL" 10937 "' baz='2'>\n" 10938 "&en;" 10939 "</doc>"; 10940 ExtOption options[] = { 10941 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10942 int i; 10943 const int max_alloc_count = 70; 10944 10945 for (i = 0; i < max_alloc_count; i++) { 10946 allocation_count = i; 10947 XML_SetUserData(g_parser, options); 10948 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10949 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10950 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10951 != XML_STATUS_ERROR) 10952 break; 10953 10954 /* See comment in test_nsalloc_xmlns() */ 10955 nsalloc_teardown(); 10956 nsalloc_setup(); 10957 } 10958 if (i == 0) 10959 fail("Parsing worked despite failing allocations"); 10960 else if (i == max_alloc_count) 10961 fail("Parsing failed even at max allocation count"); 10962 } 10963 END_TEST 10964 10965 /* This function is void; it will throw a fail() on error, so if it 10966 * returns normally it must have succeeded. 10967 */ 10968 static void 10969 context_realloc_test(const char *text) { 10970 ExtOption options[] = { 10971 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10972 int i; 10973 const int max_realloc_count = 6; 10974 10975 for (i = 0; i < max_realloc_count; i++) { 10976 reallocation_count = i; 10977 XML_SetUserData(g_parser, options); 10978 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10979 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10980 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10981 != XML_STATUS_ERROR) 10982 break; 10983 /* See comment in test_nsalloc_xmlns() */ 10984 nsalloc_teardown(); 10985 nsalloc_setup(); 10986 } 10987 if (i == 0) 10988 fail("Parsing worked despite failing reallocations"); 10989 else if (i == max_realloc_count) 10990 fail("Parsing failed even at max reallocation count"); 10991 } 10992 10993 START_TEST(test_nsalloc_realloc_long_context) { 10994 const char *text 10995 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10996 " <!ENTITY en SYSTEM 'bar'>\n" 10997 "]>\n" 10998 "<doc xmlns='http://example.org/" 10999 /* 64 characters per line */ 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/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11006 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11007 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11008 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11009 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11010 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11011 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11012 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11013 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11014 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11015 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 11016 "'>\n" 11017 "&en;" 11018 "</doc>"; 11019 11020 context_realloc_test(text); 11021 } 11022 END_TEST 11023 11024 START_TEST(test_nsalloc_realloc_long_context_2) { 11025 const char *text 11026 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11027 " <!ENTITY en SYSTEM 'bar'>\n" 11028 "]>\n" 11029 "<doc xmlns='http://example.org/" 11030 /* 64 characters per line */ 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/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11037 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11038 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11039 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11040 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11041 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11042 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11043 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11044 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11045 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11046 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK" 11047 "'>\n" 11048 "&en;" 11049 "</doc>"; 11050 11051 context_realloc_test(text); 11052 } 11053 END_TEST 11054 11055 START_TEST(test_nsalloc_realloc_long_context_3) { 11056 const char *text 11057 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11058 " <!ENTITY en SYSTEM 'bar'>\n" 11059 "]>\n" 11060 "<doc xmlns='http://example.org/" 11061 /* 64 characters per line */ 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 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11068 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11069 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11070 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11071 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11072 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11073 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11074 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11075 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11076 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11077 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH" 11078 "'>\n" 11079 "&en;" 11080 "</doc>"; 11081 11082 context_realloc_test(text); 11083 } 11084 END_TEST 11085 11086 START_TEST(test_nsalloc_realloc_long_context_4) { 11087 const char *text 11088 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11089 " <!ENTITY en SYSTEM 'bar'>\n" 11090 "]>\n" 11091 "<doc xmlns='http://example.org/" 11092 /* 64 characters per line */ 11093 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11094 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11095 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11096 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11097 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11098 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11099 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11100 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11101 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11102 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11103 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11104 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11105 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11106 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11107 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11108 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO" 11109 "'>\n" 11110 "&en;" 11111 "</doc>"; 11112 11113 context_realloc_test(text); 11114 } 11115 END_TEST 11116 11117 START_TEST(test_nsalloc_realloc_long_context_5) { 11118 const char *text 11119 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11120 " <!ENTITY en SYSTEM 'bar'>\n" 11121 "]>\n" 11122 "<doc xmlns='http://example.org/" 11123 /* 64 characters per line */ 11124 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11125 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11126 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11128 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11129 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11130 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11131 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11132 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11133 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11134 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11135 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11136 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11137 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11138 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11139 "ABC" 11140 "'>\n" 11141 "&en;" 11142 "</doc>"; 11143 11144 context_realloc_test(text); 11145 } 11146 END_TEST 11147 11148 START_TEST(test_nsalloc_realloc_long_context_6) { 11149 const char *text 11150 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11151 " <!ENTITY en SYSTEM 'bar'>\n" 11152 "]>\n" 11153 "<doc xmlns='http://example.org/" 11154 /* 64 characters per line */ 11155 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11156 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11157 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11158 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11159 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11160 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11161 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11162 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11163 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11164 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11165 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11166 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11167 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11168 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11169 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 11170 "'>\n" 11171 "&en;" 11172 "</doc>"; 11173 11174 context_realloc_test(text); 11175 } 11176 END_TEST 11177 11178 START_TEST(test_nsalloc_realloc_long_context_7) { 11179 const char *text 11180 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11181 " <!ENTITY en SYSTEM 'bar'>\n" 11182 "]>\n" 11183 "<doc xmlns='http://example.org/" 11184 /* 64 characters per line */ 11185 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11186 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11187 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11188 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11189 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11190 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11191 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11192 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11193 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11194 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11195 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11196 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11197 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11198 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11199 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11200 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM" 11201 "'>\n" 11202 "&en;" 11203 "</doc>"; 11204 11205 context_realloc_test(text); 11206 } 11207 END_TEST 11208 11209 START_TEST(test_nsalloc_realloc_long_ge_name) { 11210 const char *text 11211 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11212 " <!ENTITY " 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 " SYSTEM 'bar'>\n" 11231 "]>\n" 11232 "<doc xmlns='http://example.org/baz'>\n" 11233 "&" 11234 /* 64 characters per line */ 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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11251 ";" 11252 "</doc>"; 11253 ExtOption options[] = { 11254 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}}; 11255 int i; 11256 const int max_realloc_count = 10; 11257 11258 for (i = 0; i < max_realloc_count; i++) { 11259 reallocation_count = i; 11260 XML_SetUserData(g_parser, options); 11261 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11262 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11263 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11264 != XML_STATUS_ERROR) 11265 break; 11266 /* See comment in test_nsalloc_xmlns() */ 11267 nsalloc_teardown(); 11268 nsalloc_setup(); 11269 } 11270 if (i == 0) 11271 fail("Parsing worked despite failing reallocations"); 11272 else if (i == max_realloc_count) 11273 fail("Parsing failed even at max reallocation count"); 11274 } 11275 END_TEST 11276 11277 /* Test that when a namespace is passed through the context mechanism 11278 * to an external entity parser, the parsers handle reallocation 11279 * failures correctly. The prefix is exactly the right length to 11280 * provoke particular uncommon code paths. 11281 */ 11282 START_TEST(test_nsalloc_realloc_long_context_in_dtd) { 11283 const char *text1 11284 = "<!DOCTYPE " 11285 /* 64 characters per line */ 11286 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11287 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11288 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11289 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11290 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11291 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11292 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11293 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11294 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11295 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11296 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11297 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11298 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11299 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11300 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11301 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11302 ":doc [\n" 11303 " <!ENTITY First SYSTEM 'foo/First'>\n" 11304 "]>\n" 11305 "<" 11306 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11307 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11308 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11309 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11310 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11311 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11312 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11313 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11314 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11315 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11316 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11317 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11318 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11319 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11320 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11321 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11322 ":doc xmlns:" 11323 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11324 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11325 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11326 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11327 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11328 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11329 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11330 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11331 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11332 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11333 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11334 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11335 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11336 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11337 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11338 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11339 "='foo/Second'>&First;"; 11340 const char *text2 11341 = "</" 11342 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11343 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11344 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11345 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11346 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11347 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11348 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11349 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11350 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11351 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11352 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11353 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11354 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11355 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11356 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11357 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11358 ":doc>"; 11359 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}}; 11360 int i; 11361 const int max_realloc_count = 20; 11362 11363 for (i = 0; i < max_realloc_count; i++) { 11364 reallocation_count = i; 11365 XML_SetUserData(g_parser, options); 11366 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11367 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11368 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 11369 != XML_STATUS_ERROR 11370 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 11371 XML_TRUE) 11372 != XML_STATUS_ERROR) 11373 break; 11374 /* See comment in test_nsalloc_xmlns() */ 11375 nsalloc_teardown(); 11376 nsalloc_setup(); 11377 } 11378 if (i == 0) 11379 fail("Parsing worked despite failing reallocations"); 11380 else if (i == max_realloc_count) 11381 fail("Parsing failed even at max reallocation count"); 11382 } 11383 END_TEST 11384 11385 START_TEST(test_nsalloc_long_default_in_ext) { 11386 const char *text 11387 = "<!DOCTYPE doc [\n" 11388 " <!ATTLIST e a1 CDATA '" 11389 /* 64 characters per line */ 11390 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11391 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11392 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11393 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11394 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11395 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11396 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11397 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11398 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11399 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11400 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11401 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11402 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11403 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11404 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11405 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11406 "'>\n" 11407 " <!ENTITY x SYSTEM 'foo'>\n" 11408 "]>\n" 11409 "<doc>&x;</doc>"; 11410 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}}; 11411 int i; 11412 const int max_alloc_count = 50; 11413 11414 for (i = 0; i < max_alloc_count; i++) { 11415 allocation_count = i; 11416 XML_SetUserData(g_parser, options); 11417 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11418 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11419 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11420 != XML_STATUS_ERROR) 11421 break; 11422 11423 /* See comment in test_nsalloc_xmlns() */ 11424 nsalloc_teardown(); 11425 nsalloc_setup(); 11426 } 11427 if (i == 0) 11428 fail("Parsing worked despite failing allocations"); 11429 else if (i == max_alloc_count) 11430 fail("Parsing failed even at max allocation count"); 11431 } 11432 END_TEST 11433 11434 START_TEST(test_nsalloc_long_systemid_in_ext) { 11435 const char *text 11436 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11437 " <!ENTITY en SYSTEM '" 11438 /* 64 characters per line */ 11439 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11440 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11441 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11442 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11443 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11444 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11445 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11446 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11447 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11448 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11449 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11450 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11451 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11452 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11453 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11454 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11455 "'>\n" 11456 "]>\n" 11457 "<doc>&en;</doc>"; 11458 ExtOption options[] = { 11459 {XCS("foo"), "<!ELEMENT e EMPTY>"}, 11460 {/* clang-format off */ 11461 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11462 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11463 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11464 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11465 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11466 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11467 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11468 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11469 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11470 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11471 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11472 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11473 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11474 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11475 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11476 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"), 11477 /* clang-format on */ 11478 "<e/>"}, 11479 {NULL, NULL}}; 11480 int i; 11481 const int max_alloc_count = 55; 11482 11483 for (i = 0; i < max_alloc_count; i++) { 11484 allocation_count = i; 11485 XML_SetUserData(g_parser, options); 11486 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11487 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11488 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11489 != XML_STATUS_ERROR) 11490 break; 11491 11492 /* See comment in test_nsalloc_xmlns() */ 11493 nsalloc_teardown(); 11494 nsalloc_setup(); 11495 } 11496 if (i == 0) 11497 fail("Parsing worked despite failing allocations"); 11498 else if (i == max_alloc_count) 11499 fail("Parsing failed even at max allocation count"); 11500 } 11501 END_TEST 11502 11503 /* Test the effects of allocation failure on parsing an element in a 11504 * namespace. Based on test_nsalloc_long_context. 11505 */ 11506 START_TEST(test_nsalloc_prefixed_element) { 11507 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n" 11508 " <!ATTLIST pfx:element baz ID #REQUIRED>\n" 11509 " <!ENTITY en SYSTEM 'bar'>\n" 11510 "]>\n" 11511 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n" 11512 "&en;" 11513 "</pfx:element>"; 11514 ExtOption options[] = { 11515 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 11516 int i; 11517 const int max_alloc_count = 70; 11518 11519 for (i = 0; i < max_alloc_count; i++) { 11520 allocation_count = i; 11521 XML_SetUserData(g_parser, options); 11522 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11523 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11524 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11525 != XML_STATUS_ERROR) 11526 break; 11527 11528 /* See comment in test_nsalloc_xmlns() */ 11529 nsalloc_teardown(); 11530 nsalloc_setup(); 11531 } 11532 if (i == 0) 11533 fail("Success despite failing allocator"); 11534 else if (i == max_alloc_count) 11535 fail("Failed even at full allocation count"); 11536 } 11537 END_TEST 11538 11539 #if defined(XML_DTD) 11540 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int); 11541 11542 struct AccountingTestCase { 11543 const char *primaryText; 11544 const char *firstExternalText; /* often NULL */ 11545 const char *secondExternalText; /* often NULL */ 11546 const unsigned long long expectedCountBytesIndirectExtra; 11547 XML_Bool singleBytesWanted; 11548 }; 11549 11550 static int 11551 accounting_external_entity_ref_handler(XML_Parser parser, 11552 const XML_Char *context, 11553 const XML_Char *base, 11554 const XML_Char *systemId, 11555 const XML_Char *publicId) { 11556 UNUSED_P(context); 11557 UNUSED_P(base); 11558 UNUSED_P(publicId); 11559 11560 const struct AccountingTestCase *const testCase 11561 = (const struct AccountingTestCase *)XML_GetUserData(parser); 11562 11563 const char *externalText = NULL; 11564 if (xcstrcmp(systemId, XCS("first.ent")) == 0) { 11565 externalText = testCase->firstExternalText; 11566 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) { 11567 externalText = testCase->secondExternalText; 11568 } else { 11569 assert(! "systemId is neither \"first.ent\" nor \"second.ent\""); 11570 } 11571 assert(externalText); 11572 11573 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 11574 assert(entParser); 11575 11576 const XmlParseFunction xmlParseFunction 11577 = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11578 11579 const enum XML_Status status = xmlParseFunction( 11580 entParser, externalText, (int)strlen(externalText), XML_TRUE); 11581 11582 XML_ParserFree(entParser); 11583 return status; 11584 } 11585 11586 START_TEST(test_accounting_precision) { 11587 const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */ 11588 struct AccountingTestCase cases[] = { 11589 {"<e/>", NULL, NULL, 0, 0}, 11590 {"<e></e>", NULL, NULL, 0, 0}, 11591 11592 /* Attributes */ 11593 {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later}, 11594 {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0}, 11595 {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0, 11596 filled_later}, 11597 {"<e k=\"&'><"\" />", NULL, NULL, 11598 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11599 {"<e1 xmlns='https://example.org/'>\n" 11600 " <e2 xmlns=''/>\n" 11601 "</e1>", 11602 NULL, NULL, 0, filled_later}, 11603 11604 /* Text */ 11605 {"<e>text</e>", NULL, NULL, 0, filled_later}, 11606 {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later}, 11607 {"<e>&'><"</e>", NULL, NULL, 11608 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11609 {"<e>A)</e>", NULL, NULL, 0, filled_later}, 11610 11611 /* Prolog */ 11612 {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later}, 11613 11614 /* Whitespace */ 11615 {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later}, 11616 {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later}, 11617 {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later}, 11618 11619 /* Comments */ 11620 {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later}, 11621 11622 /* Processing instructions */ 11623 {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>", 11624 NULL, NULL, 0, filled_later}, 11625 {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>", 11626 "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>", 11627 0, filled_later}, 11628 11629 /* CDATA */ 11630 {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later}, 11631 /* The following is the essence of this OSS-Fuzz finding: 11632 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302 11633 https://oss-fuzz.com/testcase-detail/4860575394955264 11634 */ 11635 {"<!DOCTYPE r [\n" 11636 "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n" 11637 "]>\n" 11638 "<r>&e;</r>\n", 11639 NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"), 11640 filled_later}, 11641 11642 /* Conditional sections */ 11643 {"<!DOCTYPE r [\n" 11644 "<!ENTITY % draft 'INCLUDE'>\n" 11645 "<!ENTITY % final 'IGNORE'>\n" 11646 "<!ENTITY % import SYSTEM \"first.ent\">\n" 11647 "%import;\n" 11648 "]>\n" 11649 "<r/>\n", 11650 "<![%draft;[<!--1-->]]>\n" 11651 "<![%final;[<!--22-->]]>", 11652 NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")), 11653 filled_later}, 11654 11655 /* General entities */ 11656 {"<!DOCTYPE root [\n" 11657 "<!ENTITY nine \"123456789\">\n" 11658 "]>\n" 11659 "<root>&nine;</root>", 11660 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11661 {"<!DOCTYPE root [\n" 11662 "<!ENTITY nine \"123456789\">\n" 11663 "]>\n" 11664 "<root k1=\"&nine;\"/>", 11665 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11666 {"<!DOCTYPE root [\n" 11667 "<!ENTITY nine \"123456789\">\n" 11668 "<!ENTITY nine2 \"&nine;&nine;\">\n" 11669 "]>\n" 11670 "<root>&nine2;&nine2;&nine2;</root>", 11671 NULL, NULL, 11672 sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */ 11673 * (strlen("&nine;") + strlen("123456789")), 11674 filled_later}, 11675 {"<!DOCTYPE r [\n" 11676 " <!ENTITY five SYSTEM 'first.ent'>\n" 11677 "]>\n" 11678 "<r>&five;</r>", 11679 "12345", NULL, 0, filled_later}, 11680 11681 /* Parameter entities */ 11682 {"<!DOCTYPE r [\n" 11683 "<!ENTITY % comment \"<!---->\">\n" 11684 "%comment;\n" 11685 "]>\n" 11686 "<r/>", 11687 NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later}, 11688 {"<!DOCTYPE r [\n" 11689 "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n" 11690 "%ninedef;\n" 11691 "]>\n" 11692 "<r>&nine;</r>", 11693 NULL, NULL, 11694 sizeof(XML_Char) 11695 * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")), 11696 filled_later}, 11697 {"<!DOCTYPE r [\n" 11698 "<!ENTITY % comment \"<!--1-->\">\n" 11699 "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n" 11700 "%comment2;\n" 11701 "]>\n" 11702 "<r/>\n", 11703 NULL, NULL, 11704 sizeof(XML_Char) 11705 * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")), 11706 filled_later}, 11707 {"<!DOCTYPE r [\n" 11708 " <!ENTITY % five \"12345\">\n" 11709 " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n" 11710 " %five2def;\n" 11711 "]>\n" 11712 "<r>&five2;</r>", 11713 NULL, NULL, /* from "%five2def;": */ 11714 sizeof(XML_Char) 11715 * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">") 11716 + 2 /* calls to "%five;" */ * strlen("12345") 11717 + /* from "&five2;": */ strlen("[12345][12345]]]]")), 11718 filled_later}, 11719 {"<!DOCTYPE r SYSTEM \"first.ent\">\n" 11720 "<r/>", 11721 "<!ENTITY % comment '<!--1-->'>\n" 11722 "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n" 11723 "%comment2;", 11724 NULL, 11725 sizeof(XML_Char) 11726 * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->") 11727 + 2 /* calls to "%comment;" */ * strlen("<!---->")), 11728 filled_later}, 11729 {"<!DOCTYPE r SYSTEM 'first.ent'>\n" 11730 "<r/>", 11731 "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n" 11732 "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n" 11733 "%e2;\n", 11734 "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"), 11735 filled_later}, 11736 { 11737 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11738 "<r/>", 11739 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11740 "<!ENTITY % e2 '%e1;'>", 11741 "<?xml version='1.0' encoding='utf-8'?>\n" 11742 "hello\n" 11743 "xml" /* without trailing newline! */, 11744 0, 11745 filled_later, 11746 }, 11747 { 11748 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11749 "<r/>", 11750 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11751 "<!ENTITY % e2 '%e1;'>", 11752 "<?xml version='1.0' encoding='utf-8'?>\n" 11753 "hello\n" 11754 "xml\n" /* with trailing newline! */, 11755 0, 11756 filled_later, 11757 }, 11758 {"<!DOCTYPE doc SYSTEM 'first.ent'>\n" 11759 "<doc></doc>\n", 11760 "<!ELEMENT doc EMPTY>\n" 11761 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11762 "<!ENTITY % e2 '%e1;'>\n" 11763 "%e1;\n", 11764 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */, 11765 strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later}, 11766 {"<!DOCTYPE r [\n" 11767 " <!ENTITY five SYSTEM 'first.ent'>\n" 11768 "]>\n" 11769 "<r>&five;</r>", 11770 "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later}, 11771 }; 11772 11773 const size_t countCases = sizeof(cases) / sizeof(cases[0]); 11774 size_t u = 0; 11775 for (; u < countCases; u++) { 11776 size_t v = 0; 11777 for (; v < 2; v++) { 11778 const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE; 11779 const unsigned long long expectedCountBytesDirect 11780 = strlen(cases[u].primaryText); 11781 const unsigned long long expectedCountBytesIndirect 11782 = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText) 11783 : 0) 11784 + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText) 11785 : 0) 11786 + cases[u].expectedCountBytesIndirectExtra; 11787 11788 XML_Parser parser = XML_ParserCreate(NULL); 11789 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11790 if (cases[u].firstExternalText) { 11791 XML_SetExternalEntityRefHandler(parser, 11792 accounting_external_entity_ref_handler); 11793 XML_SetUserData(parser, (void *)&cases[u]); 11794 cases[u].singleBytesWanted = singleBytesWanted; 11795 } 11796 11797 const XmlParseFunction xmlParseFunction 11798 = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11799 11800 enum XML_Status status 11801 = xmlParseFunction(parser, cases[u].primaryText, 11802 (int)strlen(cases[u].primaryText), XML_TRUE); 11803 if (status != XML_STATUS_OK) { 11804 _xml_failure(parser, __FILE__, __LINE__); 11805 } 11806 11807 const unsigned long long actualCountBytesDirect 11808 = testingAccountingGetCountBytesDirect(parser); 11809 const unsigned long long actualCountBytesIndirect 11810 = testingAccountingGetCountBytesIndirect(parser); 11811 11812 XML_ParserFree(parser); 11813 11814 if (actualCountBytesDirect != expectedCountBytesDirect) { 11815 fprintf( 11816 stderr, 11817 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11818 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11819 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11820 expectedCountBytesDirect, actualCountBytesDirect); 11821 fail("Count of direct bytes is off"); 11822 } 11823 11824 if (actualCountBytesIndirect != expectedCountBytesIndirect) { 11825 fprintf( 11826 stderr, 11827 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11828 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11829 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11830 expectedCountBytesIndirect, actualCountBytesIndirect); 11831 fail("Count of indirect bytes is off"); 11832 } 11833 } 11834 } 11835 } 11836 END_TEST 11837 11838 static float 11839 portableNAN(void) { 11840 return strtof("nan", NULL); 11841 } 11842 11843 static float 11844 portableINFINITY(void) { 11845 return strtof("infinity", NULL); 11846 } 11847 11848 START_TEST(test_billion_laughs_attack_protection_api) { 11849 XML_Parser parserWithoutParent = XML_ParserCreate(NULL); 11850 XML_Parser parserWithParent 11851 = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL); 11852 if (parserWithoutParent == NULL) 11853 fail("parserWithoutParent is NULL"); 11854 if (parserWithParent == NULL) 11855 fail("parserWithParent is NULL"); 11856 11857 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases 11858 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f) 11859 == XML_TRUE) 11860 fail("Call with NULL parser is NOT supposed to succeed"); 11861 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent, 11862 123.0f) 11863 == XML_TRUE) 11864 fail("Call with non-root parser is NOT supposed to succeed"); 11865 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11866 parserWithoutParent, portableNAN()) 11867 == XML_TRUE) 11868 fail("Call with NaN limit is NOT supposed to succeed"); 11869 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11870 parserWithoutParent, -1.0f) 11871 == XML_TRUE) 11872 fail("Call with negative limit is NOT supposed to succeed"); 11873 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11874 parserWithoutParent, 0.9f) 11875 == XML_TRUE) 11876 fail("Call with positive limit <1.0 is NOT supposed to succeed"); 11877 11878 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases 11879 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11880 parserWithoutParent, 1.0f) 11881 == XML_FALSE) 11882 fail("Call with positive limit >=1.0 is supposed to succeed"); 11883 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11884 parserWithoutParent, 123456.789f) 11885 == XML_FALSE) 11886 fail("Call with positive limit >=1.0 is supposed to succeed"); 11887 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11888 parserWithoutParent, portableINFINITY()) 11889 == XML_FALSE) 11890 fail("Call with positive limit >=1.0 is supposed to succeed"); 11891 11892 // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases 11893 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123) 11894 == XML_TRUE) 11895 fail("Call with NULL parser is NOT supposed to succeed"); 11896 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent, 11897 123) 11898 == XML_TRUE) 11899 fail("Call with non-root parser is NOT supposed to succeed"); 11900 11901 // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases 11902 if (XML_SetBillionLaughsAttackProtectionActivationThreshold( 11903 parserWithoutParent, 123) 11904 == XML_FALSE) 11905 fail("Call with non-NULL parentless parser is supposed to succeed"); 11906 11907 XML_ParserFree(parserWithParent); 11908 XML_ParserFree(parserWithoutParent); 11909 } 11910 END_TEST 11911 11912 START_TEST(test_helper_unsigned_char_to_printable) { 11913 // Smoke test 11914 unsigned char uc = 0; 11915 for (; uc < (unsigned char)-1; uc++) { 11916 const char *const printable = unsignedCharToPrintable(uc); 11917 if (printable == NULL) 11918 fail("unsignedCharToPrintable returned NULL"); 11919 if (strlen(printable) < (size_t)1) 11920 fail("unsignedCharToPrintable returned empty string"); 11921 } 11922 11923 // Two concrete samples 11924 if (strcmp(unsignedCharToPrintable('A'), "A") != 0) 11925 fail("unsignedCharToPrintable result mistaken"); 11926 if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0) 11927 fail("unsignedCharToPrintable result mistaken"); 11928 } 11929 END_TEST 11930 #endif // defined(XML_DTD) 11931 11932 static Suite * 11933 make_suite(void) { 11934 Suite *s = suite_create("basic"); 11935 TCase *tc_basic = tcase_create("basic tests"); 11936 TCase *tc_namespace = tcase_create("XML namespaces"); 11937 TCase *tc_misc = tcase_create("miscellaneous tests"); 11938 TCase *tc_alloc = tcase_create("allocation tests"); 11939 TCase *tc_nsalloc = tcase_create("namespace allocation tests"); 11940 #if defined(XML_DTD) 11941 TCase *tc_accounting = tcase_create("accounting tests"); 11942 #endif 11943 11944 suite_add_tcase(s, tc_basic); 11945 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown); 11946 tcase_add_test(tc_basic, test_nul_byte); 11947 tcase_add_test(tc_basic, test_u0000_char); 11948 tcase_add_test(tc_basic, test_siphash_self); 11949 tcase_add_test(tc_basic, test_siphash_spec); 11950 tcase_add_test(tc_basic, test_bom_utf8); 11951 tcase_add_test(tc_basic, test_bom_utf16_be); 11952 tcase_add_test(tc_basic, test_bom_utf16_le); 11953 tcase_add_test(tc_basic, test_nobom_utf16_le); 11954 tcase_add_test(tc_basic, test_illegal_utf8); 11955 tcase_add_test(tc_basic, test_utf8_auto_align); 11956 tcase_add_test(tc_basic, test_utf16); 11957 tcase_add_test(tc_basic, test_utf16_le_epilog_newline); 11958 tcase_add_test(tc_basic, test_not_utf16); 11959 tcase_add_test(tc_basic, test_bad_encoding); 11960 tcase_add_test(tc_basic, test_latin1_umlauts); 11961 tcase_add_test(tc_basic, test_long_utf8_character); 11962 tcase_add_test(tc_basic, test_long_latin1_attribute); 11963 tcase_add_test(tc_basic, test_long_ascii_attribute); 11964 /* Regression test for SF bug #491986. */ 11965 tcase_add_test(tc_basic, test_danish_latin1); 11966 /* Regression test for SF bug #514281. */ 11967 tcase_add_test(tc_basic, test_french_charref_hexidecimal); 11968 tcase_add_test(tc_basic, test_french_charref_decimal); 11969 tcase_add_test(tc_basic, test_french_latin1); 11970 tcase_add_test(tc_basic, test_french_utf8); 11971 tcase_add_test(tc_basic, test_utf8_false_rejection); 11972 tcase_add_test(tc_basic, test_line_number_after_parse); 11973 tcase_add_test(tc_basic, test_column_number_after_parse); 11974 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers); 11975 tcase_add_test(tc_basic, test_line_number_after_error); 11976 tcase_add_test(tc_basic, test_column_number_after_error); 11977 tcase_add_test(tc_basic, test_really_long_lines); 11978 tcase_add_test(tc_basic, test_really_long_encoded_lines); 11979 tcase_add_test(tc_basic, test_end_element_events); 11980 tcase_add_test(tc_basic, test_attr_whitespace_normalization); 11981 tcase_add_test(tc_basic, test_xmldecl_misplaced); 11982 tcase_add_test(tc_basic, test_xmldecl_invalid); 11983 tcase_add_test(tc_basic, test_xmldecl_missing_attr); 11984 tcase_add_test(tc_basic, test_xmldecl_missing_value); 11985 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity); 11986 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity); 11987 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset); 11988 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset); 11989 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone); 11990 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset); 11991 tcase_add_test(tc_basic, test_not_standalone_handler_reject); 11992 tcase_add_test(tc_basic, test_not_standalone_handler_accept); 11993 tcase_add_test(tc_basic, 11994 test_wfc_undeclared_entity_with_external_subset_standalone); 11995 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone); 11996 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs); 11997 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding); 11998 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler); 11999 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom); 12000 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding); 12001 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2); 12002 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse); 12003 tcase_add_test__ifdef_xml_dtd(tc_basic, 12004 test_ext_entity_invalid_suspended_parse); 12005 tcase_add_test(tc_basic, test_dtd_default_handling); 12006 tcase_add_test(tc_basic, test_dtd_attr_handling); 12007 tcase_add_test(tc_basic, test_empty_ns_without_namespaces); 12008 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces); 12009 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls); 12010 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls); 12011 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls); 12012 tcase_add_test(tc_basic, test_good_cdata_ascii); 12013 tcase_add_test(tc_basic, test_good_cdata_utf16); 12014 tcase_add_test(tc_basic, test_good_cdata_utf16_le); 12015 tcase_add_test(tc_basic, test_long_cdata_utf16); 12016 tcase_add_test(tc_basic, test_multichar_cdata_utf16); 12017 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair); 12018 tcase_add_test(tc_basic, test_bad_cdata); 12019 tcase_add_test(tc_basic, test_bad_cdata_utf16); 12020 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls); 12021 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls); 12022 tcase_add_test(tc_basic, test_memory_allocation); 12023 tcase_add_test(tc_basic, test_default_current); 12024 tcase_add_test(tc_basic, test_dtd_elements); 12025 tcase_add_test(tc_basic, test_dtd_elements_nesting); 12026 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd); 12027 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone); 12028 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd); 12029 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype); 12030 tcase_add_test__ifdef_xml_dtd(tc_basic, 12031 test_foreign_dtd_without_external_subset); 12032 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd); 12033 tcase_add_test(tc_basic, test_set_base); 12034 tcase_add_test(tc_basic, test_attributes); 12035 tcase_add_test(tc_basic, test_reset_in_entity); 12036 tcase_add_test(tc_basic, test_resume_invalid_parse); 12037 tcase_add_test(tc_basic, test_resume_resuspended); 12038 tcase_add_test(tc_basic, test_cdata_default); 12039 tcase_add_test(tc_basic, test_subordinate_reset); 12040 tcase_add_test(tc_basic, test_subordinate_suspend); 12041 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend); 12042 tcase_add_test(tc_basic, test_subordinate_xdecl_abort); 12043 tcase_add_test(tc_basic, test_explicit_encoding); 12044 tcase_add_test(tc_basic, test_trailing_cr); 12045 tcase_add_test(tc_basic, test_ext_entity_trailing_cr); 12046 tcase_add_test(tc_basic, test_trailing_rsqb); 12047 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb); 12048 tcase_add_test(tc_basic, test_ext_entity_good_cdata); 12049 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters); 12050 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter); 12051 tcase_add_test(tc_basic, test_empty_parse); 12052 tcase_add_test(tc_basic, test_get_buffer_1); 12053 tcase_add_test(tc_basic, test_get_buffer_2); 12054 #if defined(XML_CONTEXT_BYTES) 12055 tcase_add_test(tc_basic, test_get_buffer_3_overflow); 12056 #endif 12057 tcase_add_test(tc_basic, test_byte_info_at_end); 12058 tcase_add_test(tc_basic, test_byte_info_at_error); 12059 tcase_add_test(tc_basic, test_byte_info_at_cdata); 12060 tcase_add_test(tc_basic, test_predefined_entities); 12061 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd); 12062 tcase_add_test(tc_basic, test_not_predefined_entities); 12063 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section); 12064 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16); 12065 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be); 12066 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section); 12067 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values); 12068 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone); 12069 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort); 12070 tcase_add_test(tc_basic, test_bad_public_doctype); 12071 tcase_add_test(tc_basic, test_attribute_enum_value); 12072 tcase_add_test(tc_basic, test_predefined_entity_redefinition); 12073 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing); 12074 tcase_add_test(tc_basic, test_public_notation_no_sysid); 12075 tcase_add_test(tc_basic, test_nested_groups); 12076 tcase_add_test(tc_basic, test_group_choice); 12077 tcase_add_test(tc_basic, test_standalone_parameter_entity); 12078 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity); 12079 tcase_add_test__ifdef_xml_dtd(tc_basic, 12080 test_recursive_external_parameter_entity); 12081 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd); 12082 tcase_add_test(tc_basic, test_suspend_xdecl); 12083 tcase_add_test(tc_basic, test_abort_epilog); 12084 tcase_add_test(tc_basic, test_abort_epilog_2); 12085 tcase_add_test(tc_basic, test_suspend_epilog); 12086 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag); 12087 tcase_add_test(tc_basic, test_unfinished_epilog); 12088 tcase_add_test(tc_basic, test_partial_char_in_epilog); 12089 tcase_add_test(tc_basic, test_hash_collision); 12090 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity); 12091 tcase_add_test__ifdef_xml_dtd(tc_basic, 12092 test_suspend_resume_internal_entity_issue_629); 12093 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error); 12094 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity); 12095 tcase_add_test(tc_basic, test_restart_on_error); 12096 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value); 12097 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value); 12098 tcase_add_test(tc_basic, test_trailing_cr_in_att_value); 12099 tcase_add_test(tc_basic, test_standalone_internal_entity); 12100 tcase_add_test(tc_basic, test_skipped_external_entity); 12101 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity); 12102 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity); 12103 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr); 12104 tcase_add_test(tc_basic, test_invalid_character_entity); 12105 tcase_add_test(tc_basic, test_invalid_character_entity_2); 12106 tcase_add_test(tc_basic, test_invalid_character_entity_3); 12107 tcase_add_test(tc_basic, test_invalid_character_entity_4); 12108 tcase_add_test(tc_basic, test_pi_handled_in_default); 12109 tcase_add_test(tc_basic, test_comment_handled_in_default); 12110 tcase_add_test(tc_basic, test_pi_yml); 12111 tcase_add_test(tc_basic, test_pi_xnl); 12112 tcase_add_test(tc_basic, test_pi_xmm); 12113 tcase_add_test(tc_basic, test_utf16_pi); 12114 tcase_add_test(tc_basic, test_utf16_be_pi); 12115 tcase_add_test(tc_basic, test_utf16_be_comment); 12116 tcase_add_test(tc_basic, test_utf16_le_comment); 12117 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn); 12118 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn); 12119 tcase_add_test(tc_basic, test_unknown_encoding_success); 12120 tcase_add_test(tc_basic, test_unknown_encoding_bad_name); 12121 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2); 12122 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1); 12123 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2); 12124 tcase_add_test(tc_basic, test_invalid_unknown_encoding); 12125 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok); 12126 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail); 12127 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length); 12128 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit); 12129 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate); 12130 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high); 12131 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value); 12132 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom); 12133 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom); 12134 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2); 12135 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2); 12136 tcase_add_test(tc_basic, test_ext_entity_utf16_be); 12137 tcase_add_test(tc_basic, test_ext_entity_utf16_le); 12138 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown); 12139 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom); 12140 tcase_add_test(tc_basic, test_utf8_in_cdata_section); 12141 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2); 12142 tcase_add_test(tc_basic, test_utf8_in_start_tags); 12143 tcase_add_test(tc_basic, test_trailing_spaces_in_elements); 12144 tcase_add_test(tc_basic, test_utf16_attribute); 12145 tcase_add_test(tc_basic, test_utf16_second_attr); 12146 tcase_add_test(tc_basic, test_attr_after_solidus); 12147 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe); 12148 tcase_add_test(tc_basic, test_bad_attr_desc_keyword); 12149 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16); 12150 tcase_add_test(tc_basic, test_bad_doctype); 12151 tcase_add_test(tc_basic, test_bad_doctype_utf8); 12152 tcase_add_test(tc_basic, test_bad_doctype_utf16); 12153 tcase_add_test(tc_basic, test_bad_doctype_plus); 12154 tcase_add_test(tc_basic, test_bad_doctype_star); 12155 tcase_add_test(tc_basic, test_bad_doctype_query); 12156 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore); 12157 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr); 12158 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr); 12159 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be); 12160 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le); 12161 tcase_add_test(tc_basic, test_short_doctype); 12162 tcase_add_test(tc_basic, test_short_doctype_2); 12163 tcase_add_test(tc_basic, test_short_doctype_3); 12164 tcase_add_test(tc_basic, test_long_doctype); 12165 tcase_add_test(tc_basic, test_bad_entity); 12166 tcase_add_test(tc_basic, test_bad_entity_2); 12167 tcase_add_test(tc_basic, test_bad_entity_3); 12168 tcase_add_test(tc_basic, test_bad_entity_4); 12169 tcase_add_test(tc_basic, test_bad_notation); 12170 tcase_add_test(tc_basic, test_default_doctype_handler); 12171 tcase_add_test(tc_basic, test_empty_element_abort); 12172 12173 suite_add_tcase(s, tc_namespace); 12174 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown); 12175 tcase_add_test(tc_namespace, test_return_ns_triplet); 12176 tcase_add_test(tc_namespace, test_ns_tagname_overwrite); 12177 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet); 12178 tcase_add_test(tc_namespace, test_start_ns_clears_start_element); 12179 tcase_add_test__ifdef_xml_dtd(tc_namespace, 12180 test_default_ns_from_ext_subset_and_ext_ge); 12181 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1); 12182 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2); 12183 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3); 12184 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4); 12185 tcase_add_test(tc_namespace, test_ns_unbound_prefix); 12186 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri); 12187 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes); 12188 tcase_add_test(tc_namespace, test_ns_duplicate_hashes); 12189 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute); 12190 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element); 12191 tcase_add_test(tc_namespace, test_ns_parser_reset); 12192 tcase_add_test(tc_namespace, test_ns_long_element); 12193 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts); 12194 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer); 12195 tcase_add_test(tc_namespace, test_ns_reserved_attributes); 12196 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2); 12197 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix); 12198 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success); 12199 tcase_add_test(tc_namespace, test_ns_double_colon); 12200 tcase_add_test(tc_namespace, test_ns_double_colon_element); 12201 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname); 12202 tcase_add_test(tc_namespace, test_ns_bad_element_leafname); 12203 tcase_add_test(tc_namespace, test_ns_utf16_leafname); 12204 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname); 12205 tcase_add_test(tc_namespace, test_ns_utf16_doctype); 12206 tcase_add_test(tc_namespace, test_ns_invalid_doctype); 12207 tcase_add_test(tc_namespace, test_ns_double_colon_doctype); 12208 tcase_add_test(tc_namespace, test_ns_separator_in_uri); 12209 12210 suite_add_tcase(s, tc_misc); 12211 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); 12212 tcase_add_test(tc_misc, test_misc_alloc_create_parser); 12213 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding); 12214 tcase_add_test(tc_misc, test_misc_null_parser); 12215 tcase_add_test(tc_misc, test_misc_error_string); 12216 tcase_add_test(tc_misc, test_misc_version); 12217 tcase_add_test(tc_misc, test_misc_features); 12218 tcase_add_test(tc_misc, test_misc_attribute_leak); 12219 tcase_add_test(tc_misc, test_misc_utf16le); 12220 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1); 12221 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2); 12222 tcase_add_test__ifdef_xml_dtd( 12223 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317); 12224 12225 suite_add_tcase(s, tc_alloc); 12226 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); 12227 tcase_add_test(tc_alloc, test_alloc_parse_xdecl); 12228 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2); 12229 tcase_add_test(tc_alloc, test_alloc_parse_pi); 12230 tcase_add_test(tc_alloc, test_alloc_parse_pi_2); 12231 tcase_add_test(tc_alloc, test_alloc_parse_pi_3); 12232 tcase_add_test(tc_alloc, test_alloc_parse_comment); 12233 tcase_add_test(tc_alloc, test_alloc_parse_comment_2); 12234 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser); 12235 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser); 12236 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts); 12237 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity); 12238 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding); 12239 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity); 12240 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling); 12241 tcase_add_test(tc_alloc, test_alloc_explicit_encoding); 12242 tcase_add_test(tc_alloc, test_alloc_set_base); 12243 tcase_add_test(tc_alloc, test_alloc_realloc_buffer); 12244 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer); 12245 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes); 12246 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value); 12247 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12248 test_alloc_realloc_subst_public_entity_value); 12249 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype); 12250 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name); 12251 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd); 12252 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value); 12253 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12254 test_alloc_realloc_attribute_enum_value); 12255 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute); 12256 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute); 12257 tcase_add_test(tc_alloc, test_alloc_notation); 12258 tcase_add_test(tc_alloc, test_alloc_public_notation); 12259 tcase_add_test(tc_alloc, test_alloc_system_notation); 12260 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups); 12261 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups); 12262 tcase_add_test(tc_alloc, test_alloc_large_group); 12263 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice); 12264 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog); 12265 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog); 12266 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12267 test_alloc_realloc_long_attribute_value); 12268 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace); 12269 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity); 12270 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref); 12271 tcase_add_test(tc_alloc, test_alloc_long_attr_value); 12272 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities); 12273 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12274 test_alloc_realloc_param_entity_newline); 12275 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe); 12276 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes); 12277 tcase_add_test(tc_alloc, test_alloc_long_doc_name); 12278 tcase_add_test(tc_alloc, test_alloc_long_base); 12279 tcase_add_test(tc_alloc, test_alloc_long_public_id); 12280 tcase_add_test(tc_alloc, test_alloc_long_entity_value); 12281 tcase_add_test(tc_alloc, test_alloc_long_notation); 12282 12283 suite_add_tcase(s, tc_nsalloc); 12284 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown); 12285 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns); 12286 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer); 12287 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix); 12288 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri); 12289 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr); 12290 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix); 12291 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes); 12292 tcase_add_test(tc_nsalloc, test_nsalloc_long_element); 12293 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri); 12294 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix); 12295 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix); 12296 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace); 12297 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace); 12298 tcase_add_test(tc_nsalloc, test_nsalloc_long_context); 12299 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context); 12300 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2); 12301 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3); 12302 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4); 12303 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5); 12304 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6); 12305 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7); 12306 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name); 12307 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd); 12308 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext); 12309 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext); 12310 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element); 12311 12312 #if defined(XML_DTD) 12313 suite_add_tcase(s, tc_accounting); 12314 tcase_add_test(tc_accounting, test_accounting_precision); 12315 tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); 12316 tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); 12317 #endif 12318 12319 return s; 12320 } 12321 12322 int 12323 main(int argc, char *argv[]) { 12324 int i, nf; 12325 int verbosity = CK_NORMAL; 12326 Suite *s = make_suite(); 12327 SRunner *sr = srunner_create(s); 12328 12329 /* run the tests for internal helper functions */ 12330 testhelper_is_whitespace_normalized(); 12331 12332 for (i = 1; i < argc; ++i) { 12333 char *opt = argv[i]; 12334 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0) 12335 verbosity = CK_VERBOSE; 12336 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0) 12337 verbosity = CK_SILENT; 12338 else { 12339 fprintf(stderr, "runtests: unknown option '%s'\n", opt); 12340 return 2; 12341 } 12342 } 12343 if (verbosity != CK_SILENT) 12344 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion()); 12345 srunner_run_all(sr, verbosity); 12346 nf = srunner_ntests_failed(sr); 12347 srunner_free(sr); 12348 12349 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 12350 } 12351