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-2022 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 static void XMLCALL 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 /* Regression test for GH issue #612: unfinished m_declAttributeType 6738 * allocation in ->m_tempPool can corrupt following allocation. 6739 */ 6740 static int XMLCALL 6741 external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context, 6742 const XML_Char *base, 6743 const XML_Char *systemId, 6744 const XML_Char *publicId) { 6745 const char *text = "<!ELEMENT barf ANY>\n" 6746 "<!ATTLIST barf my_attr (blah|%blah;a|foo) #REQUIRED>\n" 6747 "<!--COMMENT-->\n"; 6748 XML_Parser ext_parser; 6749 6750 UNUSED_P(base); 6751 UNUSED_P(publicId); 6752 if (systemId == NULL) 6753 return XML_STATUS_OK; 6754 6755 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 6756 if (ext_parser == NULL) 6757 fail("Could not create external entity parser"); 6758 6759 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 6760 == XML_STATUS_ERROR) 6761 xml_failure(ext_parser); 6762 6763 XML_ParserFree(ext_parser); 6764 return XML_STATUS_OK; 6765 } 6766 6767 START_TEST(test_pool_integrity_with_unfinished_attr) { 6768 const char *text = "<?xml version='1.0' encoding='UTF-8'?>\n" 6769 "<!DOCTYPE foo [\n" 6770 "<!ELEMENT foo ANY>\n" 6771 "<!ENTITY % entp SYSTEM \"external.dtd\">\n" 6772 "%entp;\n" 6773 "]>\n" 6774 "<a></a>\n"; 6775 const XML_Char *expected = XCS("COMMENT"); 6776 CharData storage; 6777 6778 CharData_Init(&storage); 6779 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6780 XML_SetExternalEntityRefHandler(g_parser, external_entity_unfinished_attlist); 6781 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 6782 XML_SetCommentHandler(g_parser, accumulate_comment); 6783 XML_SetUserData(g_parser, &storage); 6784 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6785 == XML_STATUS_ERROR) 6786 xml_failure(g_parser); 6787 CharData_CheckXMLChars(&storage, expected); 6788 } 6789 END_TEST 6790 6791 typedef struct { 6792 XML_Parser parser; 6793 CharData *storage; 6794 } ParserPlusStorage; 6795 6796 static void XMLCALL 6797 accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) { 6798 ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData; 6799 accumulate_comment(parserPlusStorage->storage, data); 6800 XML_StopParser(parserPlusStorage->parser, XML_TRUE); 6801 } 6802 6803 START_TEST(test_nested_entity_suspend) { 6804 const char *const text = "<!DOCTYPE a [\n" 6805 " <!ENTITY e1 '<!--e1-->'>\n" 6806 " <!ENTITY e2 '<!--e2 head-->&e1;<!--e2 tail-->'>\n" 6807 " <!ENTITY e3 '<!--e3 head-->&e2;<!--e3 tail-->'>\n" 6808 "]>\n" 6809 "<a><!--start-->&e3;<!--end--></a>"; 6810 const XML_Char *const expected = XCS("start") XCS("e3 head") XCS("e2 head") 6811 XCS("e1") XCS("e2 tail") XCS("e3 tail") XCS("end"); 6812 CharData storage; 6813 XML_Parser parser = XML_ParserCreate(NULL); 6814 ParserPlusStorage parserPlusStorage = {parser, &storage}; 6815 6816 CharData_Init(&storage); 6817 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6818 XML_SetCommentHandler(parser, accumulate_and_suspend_comment_handler); 6819 XML_SetUserData(parser, &parserPlusStorage); 6820 6821 enum XML_Status status = XML_Parse(parser, text, (int)strlen(text), XML_TRUE); 6822 while (status == XML_STATUS_SUSPENDED) { 6823 status = XML_ResumeParser(parser); 6824 } 6825 if (status != XML_STATUS_OK) 6826 xml_failure(parser); 6827 6828 CharData_CheckXMLChars(&storage, expected); 6829 XML_ParserFree(parser); 6830 } 6831 END_TEST 6832 6833 /* 6834 * Namespaces tests. 6835 */ 6836 6837 static void 6838 namespace_setup(void) { 6839 g_parser = XML_ParserCreateNS(NULL, XCS(' ')); 6840 if (g_parser == NULL) 6841 fail("Parser not created."); 6842 } 6843 6844 static void 6845 namespace_teardown(void) { 6846 basic_teardown(); 6847 } 6848 6849 /* Check that an element name and attribute name match the expected values. 6850 The expected values are passed as an array reference of string pointers 6851 provided as the userData argument; the first is the expected 6852 element name, and the second is the expected attribute name. 6853 */ 6854 static int triplet_start_flag = XML_FALSE; 6855 static int triplet_end_flag = XML_FALSE; 6856 6857 static void XMLCALL 6858 triplet_start_checker(void *userData, const XML_Char *name, 6859 const XML_Char **atts) { 6860 XML_Char **elemstr = (XML_Char **)userData; 6861 char buffer[1024]; 6862 if (xcstrcmp(elemstr[0], name) != 0) { 6863 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name); 6864 fail(buffer); 6865 } 6866 if (xcstrcmp(elemstr[1], atts[0]) != 0) { 6867 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]); 6868 fail(buffer); 6869 } 6870 triplet_start_flag = XML_TRUE; 6871 } 6872 6873 /* Check that the element name passed to the end-element handler matches 6874 the expected value. The expected value is passed as the first element 6875 in an array of strings passed as the userData argument. 6876 */ 6877 static void XMLCALL 6878 triplet_end_checker(void *userData, const XML_Char *name) { 6879 XML_Char **elemstr = (XML_Char **)userData; 6880 if (xcstrcmp(elemstr[0], name) != 0) { 6881 char buffer[1024]; 6882 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name); 6883 fail(buffer); 6884 } 6885 triplet_end_flag = XML_TRUE; 6886 } 6887 6888 START_TEST(test_return_ns_triplet) { 6889 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 6890 " xmlns:bar='http://example.org/'>"; 6891 const char *epilog = "</foo:e>"; 6892 const XML_Char *elemstr[] 6893 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")}; 6894 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6895 XML_SetUserData(g_parser, (void *)elemstr); 6896 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 6897 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler, 6898 dummy_end_namespace_decl_handler); 6899 triplet_start_flag = XML_FALSE; 6900 triplet_end_flag = XML_FALSE; 6901 dummy_handler_flags = 0; 6902 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 6903 == XML_STATUS_ERROR) 6904 xml_failure(g_parser); 6905 if (! triplet_start_flag) 6906 fail("triplet_start_checker not invoked"); 6907 /* Check that unsetting "return triplets" fails while still parsing */ 6908 XML_SetReturnNSTriplet(g_parser, XML_FALSE); 6909 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 6910 == XML_STATUS_ERROR) 6911 xml_failure(g_parser); 6912 if (! triplet_end_flag) 6913 fail("triplet_end_checker not invoked"); 6914 if (dummy_handler_flags 6915 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG)) 6916 fail("Namespace handlers not called"); 6917 } 6918 END_TEST 6919 6920 static void XMLCALL 6921 overwrite_start_checker(void *userData, const XML_Char *name, 6922 const XML_Char **atts) { 6923 CharData *storage = (CharData *)userData; 6924 CharData_AppendXMLChars(storage, XCS("start "), 6); 6925 CharData_AppendXMLChars(storage, name, -1); 6926 while (*atts != NULL) { 6927 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11); 6928 CharData_AppendXMLChars(storage, *atts, -1); 6929 atts += 2; 6930 } 6931 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6932 } 6933 6934 static void XMLCALL 6935 overwrite_end_checker(void *userData, const XML_Char *name) { 6936 CharData *storage = (CharData *)userData; 6937 CharData_AppendXMLChars(storage, XCS("end "), 4); 6938 CharData_AppendXMLChars(storage, name, -1); 6939 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6940 } 6941 6942 static void 6943 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) { 6944 CharData storage; 6945 CharData_Init(&storage); 6946 XML_SetUserData(g_parser, &storage); 6947 XML_SetElementHandler(g_parser, overwrite_start_checker, 6948 overwrite_end_checker); 6949 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6950 == XML_STATUS_ERROR) 6951 xml_failure(g_parser); 6952 CharData_CheckXMLChars(&storage, result); 6953 } 6954 6955 /* Regression test for SF bug #566334. */ 6956 START_TEST(test_ns_tagname_overwrite) { 6957 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6958 " <n:f n:attr='foo'/>\n" 6959 " <n:g n:attr2='bar'/>\n" 6960 "</n:e>"; 6961 const XML_Char *result = XCS("start http://example.org/ e\n") 6962 XCS("start http://example.org/ f\n") 6963 XCS("attribute http://example.org/ attr\n") 6964 XCS("end http://example.org/ f\n") 6965 XCS("start http://example.org/ g\n") 6966 XCS("attribute http://example.org/ attr2\n") 6967 XCS("end http://example.org/ g\n") 6968 XCS("end http://example.org/ e\n"); 6969 run_ns_tagname_overwrite_test(text, result); 6970 } 6971 END_TEST 6972 6973 /* Regression test for SF bug #566334. */ 6974 START_TEST(test_ns_tagname_overwrite_triplet) { 6975 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6976 " <n:f n:attr='foo'/>\n" 6977 " <n:g n:attr2='bar'/>\n" 6978 "</n:e>"; 6979 const XML_Char *result = XCS("start http://example.org/ e n\n") 6980 XCS("start http://example.org/ f n\n") 6981 XCS("attribute http://example.org/ attr n\n") 6982 XCS("end http://example.org/ f n\n") 6983 XCS("start http://example.org/ g n\n") 6984 XCS("attribute http://example.org/ attr2 n\n") 6985 XCS("end http://example.org/ g n\n") 6986 XCS("end http://example.org/ e n\n"); 6987 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6988 run_ns_tagname_overwrite_test(text, result); 6989 } 6990 END_TEST 6991 6992 /* Regression test for SF bug #620343. */ 6993 static void XMLCALL 6994 start_element_fail(void *userData, const XML_Char *name, 6995 const XML_Char **atts) { 6996 UNUSED_P(userData); 6997 UNUSED_P(name); 6998 UNUSED_P(atts); 6999 7000 /* We should never get here. */ 7001 fail("should never reach start_element_fail()"); 7002 } 7003 7004 static void XMLCALL 7005 start_ns_clearing_start_element(void *userData, const XML_Char *prefix, 7006 const XML_Char *uri) { 7007 UNUSED_P(prefix); 7008 UNUSED_P(uri); 7009 XML_SetStartElementHandler((XML_Parser)userData, NULL); 7010 } 7011 7012 START_TEST(test_start_ns_clears_start_element) { 7013 /* This needs to use separate start/end tags; using the empty tag 7014 syntax doesn't cause the problematic path through Expat to be 7015 taken. 7016 */ 7017 const char *text = "<e xmlns='http://example.org/'></e>"; 7018 7019 XML_SetStartElementHandler(g_parser, start_element_fail); 7020 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element); 7021 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 7022 XML_UseParserAsHandlerArg(g_parser); 7023 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7024 == XML_STATUS_ERROR) 7025 xml_failure(g_parser); 7026 } 7027 END_TEST 7028 7029 /* Regression test for SF bug #616863. */ 7030 static int XMLCALL 7031 external_entity_handler(XML_Parser parser, const XML_Char *context, 7032 const XML_Char *base, const XML_Char *systemId, 7033 const XML_Char *publicId) { 7034 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser); 7035 const char *text; 7036 XML_Parser p2; 7037 7038 UNUSED_P(base); 7039 UNUSED_P(systemId); 7040 UNUSED_P(publicId); 7041 if (callno == 1) 7042 text = ("<!ELEMENT doc (e+)>\n" 7043 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 7044 "<!ELEMENT e EMPTY>\n"); 7045 else 7046 text = ("<?xml version='1.0' encoding='us-ascii'?>" 7047 "<e/>"); 7048 7049 XML_SetUserData(parser, (void *)callno); 7050 p2 = XML_ExternalEntityParserCreate(parser, context, NULL); 7051 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE) 7052 == XML_STATUS_ERROR) { 7053 xml_failure(p2); 7054 return XML_STATUS_ERROR; 7055 } 7056 XML_ParserFree(p2); 7057 return XML_STATUS_OK; 7058 } 7059 7060 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) { 7061 const char *text = "<?xml version='1.0'?>\n" 7062 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 7063 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 7064 "]>\n" 7065 "<doc xmlns='http://example.org/ns1'>\n" 7066 "&en;\n" 7067 "</doc>"; 7068 7069 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7070 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler); 7071 /* We actually need to set this handler to tickle this bug. */ 7072 XML_SetStartElementHandler(g_parser, dummy_start_element); 7073 XML_SetUserData(g_parser, NULL); 7074 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7075 == XML_STATUS_ERROR) 7076 xml_failure(g_parser); 7077 } 7078 END_TEST 7079 7080 /* Regression test #1 for SF bug #673791. */ 7081 START_TEST(test_ns_prefix_with_empty_uri_1) { 7082 const char *text = "<doc xmlns:prefix='http://example.org/'>\n" 7083 " <e xmlns:prefix=''/>\n" 7084 "</doc>"; 7085 7086 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 7087 "Did not report re-setting namespace" 7088 " URI with prefix to ''."); 7089 } 7090 END_TEST 7091 7092 /* Regression test #2 for SF bug #673791. */ 7093 START_TEST(test_ns_prefix_with_empty_uri_2) { 7094 const char *text = "<?xml version='1.0'?>\n" 7095 "<docelem xmlns:pre=''/>"; 7096 7097 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 7098 "Did not report setting namespace URI with prefix to ''."); 7099 } 7100 END_TEST 7101 7102 /* Regression test #3 for SF bug #673791. */ 7103 START_TEST(test_ns_prefix_with_empty_uri_3) { 7104 const char *text = "<!DOCTYPE doc [\n" 7105 " <!ELEMENT doc EMPTY>\n" 7106 " <!ATTLIST doc\n" 7107 " xmlns:prefix CDATA ''>\n" 7108 "]>\n" 7109 "<doc/>"; 7110 7111 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 7112 "Didn't report attr default setting NS w/ prefix to ''."); 7113 } 7114 END_TEST 7115 7116 /* Regression test #4 for SF bug #673791. */ 7117 START_TEST(test_ns_prefix_with_empty_uri_4) { 7118 const char *text = "<!DOCTYPE doc [\n" 7119 " <!ELEMENT prefix:doc EMPTY>\n" 7120 " <!ATTLIST prefix:doc\n" 7121 " xmlns:prefix CDATA 'http://example.org/'>\n" 7122 "]>\n" 7123 "<prefix:doc/>"; 7124 /* Packaged info expected by the end element handler; 7125 the weird structuring lets us re-use the triplet_end_checker() 7126 function also used for another test. */ 7127 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")}; 7128 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 7129 XML_SetUserData(g_parser, (void *)elemstr); 7130 XML_SetEndElementHandler(g_parser, triplet_end_checker); 7131 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7132 == XML_STATUS_ERROR) 7133 xml_failure(g_parser); 7134 } 7135 END_TEST 7136 7137 /* Test with non-xmlns prefix */ 7138 START_TEST(test_ns_unbound_prefix) { 7139 const char *text = "<!DOCTYPE doc [\n" 7140 " <!ELEMENT prefix:doc EMPTY>\n" 7141 " <!ATTLIST prefix:doc\n" 7142 " notxmlns:prefix CDATA 'http://example.org/'>\n" 7143 "]>\n" 7144 "<prefix:doc/>"; 7145 7146 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7147 != XML_STATUS_ERROR) 7148 fail("Unbound prefix incorrectly passed"); 7149 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX) 7150 xml_failure(g_parser); 7151 } 7152 END_TEST 7153 7154 START_TEST(test_ns_default_with_empty_uri) { 7155 const char *text = "<doc xmlns='http://example.org/'>\n" 7156 " <e xmlns=''/>\n" 7157 "</doc>"; 7158 /* Add some handlers to exercise extra code paths */ 7159 XML_SetStartNamespaceDeclHandler(g_parser, 7160 dummy_start_namespace_decl_handler); 7161 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 7162 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7163 == XML_STATUS_ERROR) 7164 xml_failure(g_parser); 7165 } 7166 END_TEST 7167 7168 /* Regression test for SF bug #692964: two prefixes for one namespace. */ 7169 START_TEST(test_ns_duplicate_attrs_diff_prefixes) { 7170 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7171 " xmlns:b='http://example.org/a'\n" 7172 " a:a='v' b:a='v' />"; 7173 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE, 7174 "did not report multiple attributes with same URI+name"); 7175 } 7176 END_TEST 7177 7178 START_TEST(test_ns_duplicate_hashes) { 7179 /* The hash of an attribute is calculated as the hash of its URI 7180 * concatenated with a space followed by its name (after the 7181 * colon). We wish to generate attributes with the same hash 7182 * value modulo the attribute table size so that we can check that 7183 * the attribute hash table works correctly. The attribute hash 7184 * table size will be the smallest power of two greater than the 7185 * number of attributes, but at least eight. There is 7186 * unfortunately no programmatic way of getting the hash or the 7187 * table size at user level, but the test code coverage percentage 7188 * will drop if the hashes cease to point to the same row. 7189 * 7190 * The cunning plan is to have few enough attributes to have a 7191 * reliable table size of 8, and have the single letter attribute 7192 * names be 8 characters apart, producing a hash which will be the 7193 * same modulo 8. 7194 */ 7195 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7196 " a:a='v' a:i='w' />"; 7197 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7198 == XML_STATUS_ERROR) 7199 xml_failure(g_parser); 7200 } 7201 END_TEST 7202 7203 /* Regression test for SF bug #695401: unbound prefix. */ 7204 START_TEST(test_ns_unbound_prefix_on_attribute) { 7205 const char *text = "<doc a:attr=''/>"; 7206 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7207 "did not report unbound prefix on attribute"); 7208 } 7209 END_TEST 7210 7211 /* Regression test for SF bug #695401: unbound prefix. */ 7212 START_TEST(test_ns_unbound_prefix_on_element) { 7213 const char *text = "<a:doc/>"; 7214 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7215 "did not report unbound prefix on element"); 7216 } 7217 END_TEST 7218 7219 /* Test that the parsing status is correctly reset by XML_ParserReset(). 7220 * We usE test_return_ns_triplet() for our example parse to improve 7221 * coverage of tidying up code executed. 7222 */ 7223 START_TEST(test_ns_parser_reset) { 7224 XML_ParsingStatus status; 7225 7226 XML_GetParsingStatus(g_parser, &status); 7227 if (status.parsing != XML_INITIALIZED) 7228 fail("parsing status doesn't start INITIALIZED"); 7229 test_return_ns_triplet(); 7230 XML_GetParsingStatus(g_parser, &status); 7231 if (status.parsing != XML_FINISHED) 7232 fail("parsing status doesn't end FINISHED"); 7233 XML_ParserReset(g_parser, NULL); 7234 XML_GetParsingStatus(g_parser, &status); 7235 if (status.parsing != XML_INITIALIZED) 7236 fail("parsing status doesn't reset to INITIALIZED"); 7237 } 7238 END_TEST 7239 7240 /* Test that long element names with namespaces are handled correctly */ 7241 START_TEST(test_ns_long_element) { 7242 const char *text 7243 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 7244 " xmlns:foo='http://example.org/' bar:a='12'\n" 7245 " xmlns:bar='http://example.org/'>" 7246 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 7247 const XML_Char *elemstr[] 7248 = {XCS("http://example.org/") 7249 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 7250 XCS("http://example.org/ a bar")}; 7251 7252 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 7253 XML_SetUserData(g_parser, (void *)elemstr); 7254 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 7255 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7256 == XML_STATUS_ERROR) 7257 xml_failure(g_parser); 7258 } 7259 END_TEST 7260 7261 /* Test mixed population of prefixed and unprefixed attributes */ 7262 START_TEST(test_ns_mixed_prefix_atts) { 7263 const char *text = "<e a='12' bar:b='13'\n" 7264 " xmlns:bar='http://example.org/'>" 7265 "</e>"; 7266 7267 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7268 == XML_STATUS_ERROR) 7269 xml_failure(g_parser); 7270 } 7271 END_TEST 7272 7273 /* Test having a long namespaced element name inside a short one. 7274 * This exercises some internal buffer reallocation that is shared 7275 * across elements with the same namespace URI. 7276 */ 7277 START_TEST(test_ns_extend_uri_buffer) { 7278 const char *text = "<foo:e xmlns:foo='http://example.org/'>" 7279 " <foo:thisisalongenoughnametotriggerallocationaction" 7280 " foo:a='12' />" 7281 "</foo:e>"; 7282 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7283 == XML_STATUS_ERROR) 7284 xml_failure(g_parser); 7285 } 7286 END_TEST 7287 7288 /* Test that xmlns is correctly rejected as an attribute in the xmlns 7289 * namespace, but not in other namespaces 7290 */ 7291 START_TEST(test_ns_reserved_attributes) { 7292 const char *text1 7293 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />"; 7294 const char *text2 7295 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />"; 7296 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS, 7297 "xmlns not rejected as an attribute"); 7298 XML_ParserReset(g_parser, NULL); 7299 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7300 == XML_STATUS_ERROR) 7301 xml_failure(g_parser); 7302 } 7303 END_TEST 7304 7305 /* Test more reserved attributes */ 7306 START_TEST(test_ns_reserved_attributes_2) { 7307 const char *text1 = "<foo:e xmlns:foo='http://example.org/'" 7308 " xmlns:xml='http://example.org/' />"; 7309 const char *text2 7310 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />"; 7311 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />"; 7312 7313 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML, 7314 "xml not rejected as an attribute"); 7315 XML_ParserReset(g_parser, NULL); 7316 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI, 7317 "Use of w3.org URL not faulted"); 7318 XML_ParserReset(g_parser, NULL); 7319 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI, 7320 "Use of w3.org xmlns URL not faulted"); 7321 } 7322 END_TEST 7323 7324 /* Test string pool handling of namespace names of 2048 characters */ 7325 /* Exercises a particular string pool growth path */ 7326 START_TEST(test_ns_extremely_long_prefix) { 7327 /* C99 compilers are only required to support 4095-character 7328 * strings, so the following needs to be split in two to be safe 7329 * for all compilers. 7330 */ 7331 const char *text1 7332 = "<doc " 7333 /* 64 character on each line */ 7334 /* ...gives a total length of 2048 */ 7335 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7336 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7337 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7338 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7339 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7340 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7341 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7342 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7343 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7344 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7345 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7346 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7347 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7348 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7349 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7350 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7351 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7352 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7353 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7354 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7355 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7356 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7357 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7358 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7359 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7360 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7361 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7362 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7363 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7364 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7365 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7366 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7367 ":a='12'"; 7368 const char *text2 7369 = " xmlns:" 7370 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7371 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7372 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7373 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7374 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7375 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7376 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7377 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7378 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7379 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7380 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7381 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7382 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7383 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7384 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7385 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7386 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7387 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7388 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7389 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7390 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7391 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7392 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7393 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7394 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7395 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7396 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7397 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7398 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7399 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7400 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7401 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7402 "='foo'\n>" 7403 "</doc>"; 7404 7405 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 7406 == XML_STATUS_ERROR) 7407 xml_failure(g_parser); 7408 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7409 == XML_STATUS_ERROR) 7410 xml_failure(g_parser); 7411 } 7412 END_TEST 7413 7414 /* Test unknown encoding handlers in namespace setup */ 7415 START_TEST(test_ns_unknown_encoding_success) { 7416 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 7417 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>"; 7418 7419 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7420 run_character_check(text, XCS("Hi")); 7421 } 7422 END_TEST 7423 7424 /* Test that too many colons are rejected */ 7425 START_TEST(test_ns_double_colon) { 7426 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />"; 7427 const enum XML_Status status 7428 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7429 #ifdef XML_NS 7430 if ((status == XML_STATUS_OK) 7431 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7432 fail("Double colon in attribute name not faulted" 7433 " (despite active namespace support)"); 7434 } 7435 #else 7436 if (status != XML_STATUS_OK) { 7437 fail("Double colon in attribute name faulted" 7438 " (despite inactive namespace support"); 7439 } 7440 #endif 7441 } 7442 END_TEST 7443 7444 START_TEST(test_ns_double_colon_element) { 7445 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />"; 7446 const enum XML_Status status 7447 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7448 #ifdef XML_NS 7449 if ((status == XML_STATUS_OK) 7450 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7451 fail("Double colon in element name not faulted" 7452 " (despite active namespace support)"); 7453 } 7454 #else 7455 if (status != XML_STATUS_OK) { 7456 fail("Double colon in element name faulted" 7457 " (despite inactive namespace support"); 7458 } 7459 #endif 7460 } 7461 END_TEST 7462 7463 /* Test that non-name characters after a colon are rejected */ 7464 START_TEST(test_ns_bad_attr_leafname) { 7465 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />"; 7466 7467 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7468 "Invalid character in leafname not faulted"); 7469 } 7470 END_TEST 7471 7472 START_TEST(test_ns_bad_element_leafname) { 7473 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />"; 7474 7475 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7476 "Invalid character in element leafname not faulted"); 7477 } 7478 END_TEST 7479 7480 /* Test high-byte-set UTF-16 characters are valid in a leafname */ 7481 START_TEST(test_ns_utf16_leafname) { 7482 const char text[] = 7483 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' /> 7484 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7485 */ 7486 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0" 7487 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0"; 7488 const XML_Char *expected = XCS("a"); 7489 CharData storage; 7490 7491 CharData_Init(&storage); 7492 XML_SetStartElementHandler(g_parser, accumulate_attribute); 7493 XML_SetUserData(g_parser, &storage); 7494 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7495 == XML_STATUS_ERROR) 7496 xml_failure(g_parser); 7497 CharData_CheckXMLChars(&storage, expected); 7498 } 7499 END_TEST 7500 7501 START_TEST(test_ns_utf16_element_leafname) { 7502 const char text[] = 7503 /* <n:{KHO KHWAI} xmlns:n='URI'/> 7504 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7505 */ 7506 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>"; 7507 #ifdef XML_UNICODE 7508 const XML_Char *expected = XCS("URI \x0e04"); 7509 #else 7510 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7511 #endif 7512 CharData storage; 7513 7514 CharData_Init(&storage); 7515 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7516 XML_SetUserData(g_parser, &storage); 7517 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7518 == XML_STATUS_ERROR) 7519 xml_failure(g_parser); 7520 CharData_CheckXMLChars(&storage, expected); 7521 } 7522 END_TEST 7523 7524 START_TEST(test_ns_utf16_doctype) { 7525 const char text[] = 7526 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n 7527 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7528 */ 7529 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 " 7530 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 " 7531 "\0]\0>\0\n" 7532 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */ 7533 "\0<\0f\0o\0o\0:\x0e\x04\0 " 7534 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>" 7535 "\0&\0b\0a\0r\0;" 7536 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>"; 7537 #ifdef XML_UNICODE 7538 const XML_Char *expected = XCS("URI \x0e04"); 7539 #else 7540 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7541 #endif 7542 CharData storage; 7543 7544 CharData_Init(&storage); 7545 XML_SetUserData(g_parser, &storage); 7546 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7547 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7548 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7549 == XML_STATUS_ERROR) 7550 xml_failure(g_parser); 7551 CharData_CheckXMLChars(&storage, expected); 7552 } 7553 END_TEST 7554 7555 START_TEST(test_ns_invalid_doctype) { 7556 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n" 7557 "<foo:!bad>&bar;</foo:!bad>"; 7558 7559 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7560 "Invalid character in document local name not faulted"); 7561 } 7562 END_TEST 7563 7564 START_TEST(test_ns_double_colon_doctype) { 7565 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n" 7566 "<foo:a:doc>&bar;</foo:a:doc>"; 7567 7568 expect_failure(text, XML_ERROR_SYNTAX, 7569 "Double colon in document name not faulted"); 7570 } 7571 END_TEST 7572 7573 START_TEST(test_ns_separator_in_uri) { 7574 struct test_case { 7575 enum XML_Status expectedStatus; 7576 const char *doc; 7577 XML_Char namesep; 7578 }; 7579 struct test_case cases[] = { 7580 {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')}, 7581 {XML_STATUS_ERROR, "<doc xmlns='one
two' />", XCS('\n')}, 7582 {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')}, 7583 }; 7584 7585 size_t i = 0; 7586 size_t failCount = 0; 7587 for (; i < sizeof(cases) / sizeof(cases[0]); i++) { 7588 XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep); 7589 XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); 7590 if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), 7591 /*isFinal*/ XML_TRUE) 7592 != cases[i].expectedStatus) { 7593 failCount++; 7594 } 7595 XML_ParserFree(parser); 7596 } 7597 7598 if (failCount) { 7599 fail("Namespace separator handling is broken"); 7600 } 7601 } 7602 END_TEST 7603 7604 /* Control variable; the number of times duff_allocator() will successfully 7605 * allocate */ 7606 #define ALLOC_ALWAYS_SUCCEED (-1) 7607 #define REALLOC_ALWAYS_SUCCEED (-1) 7608 7609 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED; 7610 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED; 7611 7612 /* Crocked allocator for allocation failure tests */ 7613 static void * 7614 duff_allocator(size_t size) { 7615 if (allocation_count == 0) 7616 return NULL; 7617 if (allocation_count != ALLOC_ALWAYS_SUCCEED) 7618 allocation_count--; 7619 return malloc(size); 7620 } 7621 7622 /* Crocked reallocator for allocation failure tests */ 7623 static void * 7624 duff_reallocator(void *ptr, size_t size) { 7625 if (reallocation_count == 0) 7626 return NULL; 7627 if (reallocation_count != REALLOC_ALWAYS_SUCCEED) 7628 reallocation_count--; 7629 return realloc(ptr, size); 7630 } 7631 7632 /* Test that a failure to allocate the parser structure fails gracefully */ 7633 START_TEST(test_misc_alloc_create_parser) { 7634 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7635 unsigned int i; 7636 const unsigned int max_alloc_count = 10; 7637 7638 /* Something this simple shouldn't need more than 10 allocations */ 7639 for (i = 0; i < max_alloc_count; i++) { 7640 allocation_count = i; 7641 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7642 if (g_parser != NULL) 7643 break; 7644 } 7645 if (i == 0) 7646 fail("Parser unexpectedly ignored failing allocator"); 7647 else if (i == max_alloc_count) 7648 fail("Parser not created with max allocation count"); 7649 } 7650 END_TEST 7651 7652 /* Test memory allocation failures for a parser with an encoding */ 7653 START_TEST(test_misc_alloc_create_parser_with_encoding) { 7654 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7655 unsigned int i; 7656 const unsigned int max_alloc_count = 10; 7657 7658 /* Try several levels of allocation */ 7659 for (i = 0; i < max_alloc_count; i++) { 7660 allocation_count = i; 7661 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL); 7662 if (g_parser != NULL) 7663 break; 7664 } 7665 if (i == 0) 7666 fail("Parser ignored failing allocator"); 7667 else if (i == max_alloc_count) 7668 fail("Parser not created with max allocation count"); 7669 } 7670 END_TEST 7671 7672 /* Test that freeing a NULL parser doesn't cause an explosion. 7673 * (Not actually tested anywhere else) 7674 */ 7675 START_TEST(test_misc_null_parser) { 7676 XML_ParserFree(NULL); 7677 } 7678 END_TEST 7679 7680 /* Test that XML_ErrorString rejects out-of-range codes */ 7681 START_TEST(test_misc_error_string) { 7682 if (XML_ErrorString((enum XML_Error) - 1) != NULL) 7683 fail("Negative error code not rejected"); 7684 if (XML_ErrorString((enum XML_Error)100) != NULL) 7685 fail("Large error code not rejected"); 7686 } 7687 END_TEST 7688 7689 /* Test the version information is consistent */ 7690 7691 /* Since we are working in XML_LChars (potentially 16-bits), we 7692 * can't use the standard C library functions for character 7693 * manipulation and have to roll our own. 7694 */ 7695 static int 7696 parse_version(const XML_LChar *version_text, 7697 XML_Expat_Version *version_struct) { 7698 if (! version_text) 7699 return XML_FALSE; 7700 7701 while (*version_text != 0x00) { 7702 if (*version_text >= ASCII_0 && *version_text <= ASCII_9) 7703 break; 7704 version_text++; 7705 } 7706 if (*version_text == 0x00) 7707 return XML_FALSE; 7708 7709 /* version_struct->major = strtoul(version_text, 10, &version_text) */ 7710 version_struct->major = 0; 7711 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7712 version_struct->major 7713 = 10 * version_struct->major + (*version_text++ - ASCII_0); 7714 } 7715 if (*version_text++ != ASCII_PERIOD) 7716 return XML_FALSE; 7717 7718 /* Now for the minor version number */ 7719 version_struct->minor = 0; 7720 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7721 version_struct->minor 7722 = 10 * version_struct->minor + (*version_text++ - ASCII_0); 7723 } 7724 if (*version_text++ != ASCII_PERIOD) 7725 return XML_FALSE; 7726 7727 /* Finally the micro version number */ 7728 version_struct->micro = 0; 7729 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7730 version_struct->micro 7731 = 10 * version_struct->micro + (*version_text++ - ASCII_0); 7732 } 7733 if (*version_text != 0x00) 7734 return XML_FALSE; 7735 return XML_TRUE; 7736 } 7737 7738 static int 7739 versions_equal(const XML_Expat_Version *first, 7740 const XML_Expat_Version *second) { 7741 return (first->major == second->major && first->minor == second->minor 7742 && first->micro == second->micro); 7743 } 7744 7745 START_TEST(test_misc_version) { 7746 XML_Expat_Version read_version = XML_ExpatVersionInfo(); 7747 /* Silence compiler warning with the following assignment */ 7748 XML_Expat_Version parsed_version = {0, 0, 0}; 7749 const XML_LChar *version_text = XML_ExpatVersion(); 7750 7751 if (version_text == NULL) 7752 fail("Could not obtain version text"); 7753 assert(version_text != NULL); 7754 if (! parse_version(version_text, &parsed_version)) 7755 fail("Unable to parse version text"); 7756 if (! versions_equal(&read_version, &parsed_version)) 7757 fail("Version mismatch"); 7758 7759 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) 7760 if (xcstrcmp(version_text, XCS("expat_2.5.0"))) /* needs bump on releases */ 7761 fail("XML_*_VERSION in expat.h out of sync?\n"); 7762 #else 7763 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T 7764 * then XML_LChar is defined as char, for some reason. 7765 */ 7766 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */ 7767 fail("XML_*_VERSION in expat.h out of sync?\n"); 7768 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */ 7769 } 7770 END_TEST 7771 7772 /* Test feature information */ 7773 START_TEST(test_misc_features) { 7774 const XML_Feature *features = XML_GetFeatureList(); 7775 7776 /* Prevent problems with double-freeing parsers */ 7777 g_parser = NULL; 7778 if (features == NULL) { 7779 fail("Failed to get feature information"); 7780 } else { 7781 /* Loop through the features checking what we can */ 7782 while (features->feature != XML_FEATURE_END) { 7783 switch (features->feature) { 7784 case XML_FEATURE_SIZEOF_XML_CHAR: 7785 if (features->value != sizeof(XML_Char)) 7786 fail("Incorrect size of XML_Char"); 7787 break; 7788 case XML_FEATURE_SIZEOF_XML_LCHAR: 7789 if (features->value != sizeof(XML_LChar)) 7790 fail("Incorrect size of XML_LChar"); 7791 break; 7792 default: 7793 break; 7794 } 7795 features++; 7796 } 7797 } 7798 } 7799 END_TEST 7800 7801 /* Regression test for GitHub Issue #17: memory leak parsing attribute 7802 * values with mixed bound and unbound namespaces. 7803 */ 7804 START_TEST(test_misc_attribute_leak) { 7805 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>"; 7806 XML_Memory_Handling_Suite memsuite 7807 = {tracking_malloc, tracking_realloc, tracking_free}; 7808 7809 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n")); 7810 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found"); 7811 XML_ParserFree(g_parser); 7812 /* Prevent the teardown trying to double free */ 7813 g_parser = NULL; 7814 7815 if (! tracking_report()) 7816 fail("Memory leak found"); 7817 } 7818 END_TEST 7819 7820 /* Test parser created for UTF-16LE is successful */ 7821 START_TEST(test_misc_utf16le) { 7822 const char text[] = 7823 /* <?xml version='1.0'?><q>Hi</q> */ 7824 "<\0?\0x\0m\0l\0 \0" 7825 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0" 7826 "<\0q\0>\0H\0i\0<\0/\0q\0>\0"; 7827 const XML_Char *expected = XCS("Hi"); 7828 CharData storage; 7829 7830 g_parser = XML_ParserCreate(XCS("UTF-16LE")); 7831 if (g_parser == NULL) 7832 fail("Parser not created"); 7833 7834 CharData_Init(&storage); 7835 XML_SetUserData(g_parser, &storage); 7836 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 7837 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7838 == XML_STATUS_ERROR) 7839 xml_failure(g_parser); 7840 CharData_CheckXMLChars(&storage, expected); 7841 } 7842 END_TEST 7843 7844 typedef struct { 7845 XML_Parser parser; 7846 int deep; 7847 } DataIssue240; 7848 7849 static void 7850 start_element_issue_240(void *userData, const XML_Char *name, 7851 const XML_Char **atts) { 7852 DataIssue240 *mydata = (DataIssue240 *)userData; 7853 UNUSED_P(name); 7854 UNUSED_P(atts); 7855 mydata->deep++; 7856 } 7857 7858 static void 7859 end_element_issue_240(void *userData, const XML_Char *name) { 7860 DataIssue240 *mydata = (DataIssue240 *)userData; 7861 7862 UNUSED_P(name); 7863 mydata->deep--; 7864 if (mydata->deep == 0) { 7865 XML_StopParser(mydata->parser, 0); 7866 } 7867 } 7868 7869 START_TEST(test_misc_stop_during_end_handler_issue_240_1) { 7870 XML_Parser parser; 7871 DataIssue240 *mydata; 7872 enum XML_Status result; 7873 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>"; 7874 7875 parser = XML_ParserCreate(NULL); 7876 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7877 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7878 mydata->parser = parser; 7879 mydata->deep = 0; 7880 XML_SetUserData(parser, mydata); 7881 7882 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1); 7883 XML_ParserFree(parser); 7884 free(mydata); 7885 if (result != XML_STATUS_ERROR) 7886 fail("Stopping the parser did not work as expected"); 7887 } 7888 END_TEST 7889 7890 START_TEST(test_misc_stop_during_end_handler_issue_240_2) { 7891 XML_Parser parser; 7892 DataIssue240 *mydata; 7893 enum XML_Status result; 7894 const char *const doc2 = "<doc><elem/></doc>"; 7895 7896 parser = XML_ParserCreate(NULL); 7897 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7898 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7899 mydata->parser = parser; 7900 mydata->deep = 0; 7901 XML_SetUserData(parser, mydata); 7902 7903 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1); 7904 XML_ParserFree(parser); 7905 free(mydata); 7906 if (result != XML_STATUS_ERROR) 7907 fail("Stopping the parser did not work as expected"); 7908 } 7909 END_TEST 7910 7911 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { 7912 const char *const inputOne = "<!DOCTYPE d [\n" 7913 "<!ENTITY % e ']><d/>'>\n" 7914 "\n" 7915 "%e;"; 7916 const char *const inputTwo = "<!DOCTYPE d [\n" 7917 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n" 7918 "\n" 7919 "%e2;"; 7920 const char *const inputThree = "<!DOCTYPE d [\n" 7921 "<!ENTITY % e ']><d'>\n" 7922 "\n" 7923 "%e;"; 7924 const char *const inputIssue317 = "<!DOCTYPE doc [\n" 7925 "<!ENTITY % foo ']>\n" 7926 "<doc>Hell<oc (#PCDATA)*>'>\n" 7927 "%foo;\n" 7928 "]>\n" 7929 "<doc>Hello, world</dVc>"; 7930 7931 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317}; 7932 size_t inputIndex = 0; 7933 7934 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) { 7935 XML_Parser parser; 7936 enum XML_Status parseResult; 7937 int setParamEntityResult; 7938 XML_Size lineNumber; 7939 XML_Size columnNumber; 7940 const char *const input = inputs[inputIndex]; 7941 7942 parser = XML_ParserCreate(NULL); 7943 setParamEntityResult 7944 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7945 if (setParamEntityResult != 1) 7946 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS."); 7947 7948 parseResult = XML_Parse(parser, input, (int)strlen(input), 0); 7949 if (parseResult != XML_STATUS_ERROR) { 7950 parseResult = XML_Parse(parser, "", 0, 1); 7951 if (parseResult != XML_STATUS_ERROR) { 7952 fail("Parsing was expected to fail but succeeded."); 7953 } 7954 } 7955 7956 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) 7957 fail("Error code does not match XML_ERROR_INVALID_TOKEN"); 7958 7959 lineNumber = XML_GetCurrentLineNumber(parser); 7960 if (lineNumber != 4) 7961 fail("XML_GetCurrentLineNumber does not work as expected."); 7962 7963 columnNumber = XML_GetCurrentColumnNumber(parser); 7964 if (columnNumber != 0) 7965 fail("XML_GetCurrentColumnNumber does not work as expected."); 7966 7967 XML_ParserFree(parser); 7968 } 7969 } 7970 END_TEST 7971 7972 START_TEST(test_misc_tag_mismatch_reset_leak) { 7973 #ifdef XML_NS 7974 const char *const text = "<open xmlns='https://namespace1.test'></close>"; 7975 XML_Parser parser = XML_ParserCreateNS(NULL, XCS('\n')); 7976 7977 if (XML_Parse(parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) 7978 fail("Call to parse was expected to fail"); 7979 if (XML_GetErrorCode(parser) != XML_ERROR_TAG_MISMATCH) 7980 fail("Call to parse was expected to fail from a closing tag mismatch"); 7981 7982 XML_ParserReset(parser, NULL); 7983 7984 if (XML_Parse(parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) 7985 fail("Call to parse was expected to fail"); 7986 if (XML_GetErrorCode(parser) != XML_ERROR_TAG_MISMATCH) 7987 fail("Call to parse was expected to fail from a closing tag mismatch"); 7988 7989 XML_ParserFree(parser); 7990 #endif 7991 } 7992 END_TEST 7993 7994 static void 7995 alloc_setup(void) { 7996 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 7997 7998 /* Ensure the parser creation will go through */ 7999 allocation_count = ALLOC_ALWAYS_SUCCEED; 8000 reallocation_count = REALLOC_ALWAYS_SUCCEED; 8001 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 8002 if (g_parser == NULL) 8003 fail("Parser not created"); 8004 } 8005 8006 static void 8007 alloc_teardown(void) { 8008 basic_teardown(); 8009 } 8010 8011 /* Test the effects of allocation failures on xml declaration processing */ 8012 START_TEST(test_alloc_parse_xdecl) { 8013 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8014 "<doc>Hello, world</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_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 8021 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8022 != XML_STATUS_ERROR) 8023 break; 8024 /* Resetting the parser is insufficient, because some memory 8025 * allocations are cached within the parser. Instead we use 8026 * the teardown and setup routines to ensure that we have the 8027 * right sort of parser back in our hands. 8028 */ 8029 alloc_teardown(); 8030 alloc_setup(); 8031 } 8032 if (i == 0) 8033 fail("Parse succeeded despite failing allocator"); 8034 if (i == max_alloc_count) 8035 fail("Parse failed with max allocations"); 8036 } 8037 END_TEST 8038 8039 /* As above, but with an encoding big enough to cause storing the 8040 * version information to expand the string pool being used. 8041 */ 8042 static int XMLCALL 8043 long_encoding_handler(void *userData, const XML_Char *encoding, 8044 XML_Encoding *info) { 8045 int i; 8046 8047 UNUSED_P(userData); 8048 UNUSED_P(encoding); 8049 for (i = 0; i < 256; i++) 8050 info->map[i] = i; 8051 info->data = NULL; 8052 info->convert = NULL; 8053 info->release = NULL; 8054 return XML_STATUS_OK; 8055 } 8056 8057 START_TEST(test_alloc_parse_xdecl_2) { 8058 const char *text 8059 = "<?xml version='1.0' encoding='" 8060 /* Each line is 64 characters */ 8061 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456" 8062 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8063 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8064 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8065 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8066 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8067 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8068 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8069 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8070 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8071 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8072 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8073 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8074 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8075 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8076 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN" 8077 "'?>" 8078 "<doc>Hello, world</doc>"; 8079 int i; 8080 const int max_alloc_count = 20; 8081 8082 for (i = 0; i < max_alloc_count; i++) { 8083 allocation_count = i; 8084 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 8085 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL); 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 /* Test the effects of allocation failures on a straightforward parse */ 8101 START_TEST(test_alloc_parse_pi) { 8102 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8103 "<?pi unknown?>\n" 8104 "<doc>" 8105 "Hello, world" 8106 "</doc>"; 8107 int i; 8108 const int max_alloc_count = 15; 8109 8110 for (i = 0; i < max_alloc_count; i++) { 8111 allocation_count = i; 8112 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8113 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8114 != XML_STATUS_ERROR) 8115 break; 8116 /* See comment in test_alloc_parse_xdecl() */ 8117 alloc_teardown(); 8118 alloc_setup(); 8119 } 8120 if (i == 0) 8121 fail("Parse succeeded despite failing allocator"); 8122 if (i == max_alloc_count) 8123 fail("Parse failed with max allocations"); 8124 } 8125 END_TEST 8126 8127 START_TEST(test_alloc_parse_pi_2) { 8128 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8129 "<doc>" 8130 "Hello, world" 8131 "<?pi unknown?>\n" 8132 "</doc>"; 8133 int i; 8134 const int max_alloc_count = 15; 8135 8136 for (i = 0; i < max_alloc_count; i++) { 8137 allocation_count = i; 8138 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8139 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8140 != XML_STATUS_ERROR) 8141 break; 8142 /* See comment in test_alloc_parse_xdecl() */ 8143 alloc_teardown(); 8144 alloc_setup(); 8145 } 8146 if (i == 0) 8147 fail("Parse succeeded despite failing allocator"); 8148 if (i == max_alloc_count) 8149 fail("Parse failed with max allocations"); 8150 } 8151 END_TEST 8152 8153 START_TEST(test_alloc_parse_pi_3) { 8154 const char *text 8155 = "<?" 8156 /* 64 characters per line */ 8157 "This processing instruction should be long enough to ensure that" 8158 "it triggers the growth of an internal string pool when the " 8159 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP" 8160 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8161 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8162 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8163 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8164 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8165 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8166 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8167 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8168 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8169 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8170 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8171 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8172 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8173 "Q?><doc/>"; 8174 int i; 8175 const int max_alloc_count = 20; 8176 8177 for (i = 0; i < max_alloc_count; i++) { 8178 allocation_count = i; 8179 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8180 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8181 != XML_STATUS_ERROR) 8182 break; 8183 /* See comment in test_alloc_parse_xdecl() */ 8184 alloc_teardown(); 8185 alloc_setup(); 8186 } 8187 if (i == 0) 8188 fail("Parse succeeded despite failing allocator"); 8189 if (i == max_alloc_count) 8190 fail("Parse failed with max allocations"); 8191 } 8192 END_TEST 8193 8194 START_TEST(test_alloc_parse_comment) { 8195 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8196 "<!-- Test parsing this comment -->" 8197 "<doc>Hi</doc>"; 8198 int i; 8199 const int max_alloc_count = 15; 8200 8201 for (i = 0; i < max_alloc_count; i++) { 8202 allocation_count = i; 8203 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8204 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8205 != XML_STATUS_ERROR) 8206 break; 8207 /* See comment in test_alloc_parse_xdecl() */ 8208 alloc_teardown(); 8209 alloc_setup(); 8210 } 8211 if (i == 0) 8212 fail("Parse succeeded despite failing allocator"); 8213 if (i == max_alloc_count) 8214 fail("Parse failed with max allocations"); 8215 } 8216 END_TEST 8217 8218 START_TEST(test_alloc_parse_comment_2) { 8219 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8220 "<doc>" 8221 "Hello, world" 8222 "<!-- Parse this comment too -->" 8223 "</doc>"; 8224 int i; 8225 const int max_alloc_count = 15; 8226 8227 for (i = 0; i < max_alloc_count; i++) { 8228 allocation_count = i; 8229 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8230 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8231 != XML_STATUS_ERROR) 8232 break; 8233 /* See comment in test_alloc_parse_xdecl() */ 8234 alloc_teardown(); 8235 alloc_setup(); 8236 } 8237 if (i == 0) 8238 fail("Parse succeeded despite failing allocator"); 8239 if (i == max_alloc_count) 8240 fail("Parse failed with max allocations"); 8241 } 8242 END_TEST 8243 8244 static int XMLCALL 8245 external_entity_duff_loader(XML_Parser parser, const XML_Char *context, 8246 const XML_Char *base, const XML_Char *systemId, 8247 const XML_Char *publicId) { 8248 XML_Parser new_parser; 8249 unsigned int i; 8250 const unsigned int max_alloc_count = 10; 8251 8252 UNUSED_P(base); 8253 UNUSED_P(systemId); 8254 UNUSED_P(publicId); 8255 /* Try a few different allocation levels */ 8256 for (i = 0; i < max_alloc_count; i++) { 8257 allocation_count = i; 8258 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8259 if (new_parser != NULL) { 8260 XML_ParserFree(new_parser); 8261 break; 8262 } 8263 } 8264 if (i == 0) 8265 fail("External parser creation ignored failing allocator"); 8266 else if (i == max_alloc_count) 8267 fail("Extern parser not created with max allocation count"); 8268 8269 /* Make sure other random allocation doesn't now fail */ 8270 allocation_count = ALLOC_ALWAYS_SUCCEED; 8271 8272 /* Make sure the failure code path is executed too */ 8273 return XML_STATUS_ERROR; 8274 } 8275 8276 /* Test that external parser creation running out of memory is 8277 * correctly reported. Based on the external entity test cases. 8278 */ 8279 START_TEST(test_alloc_create_external_parser) { 8280 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8281 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8282 "<doc>&entity;</doc>"; 8283 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8284 8285 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8286 XML_SetUserData(g_parser, foo_text); 8287 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader); 8288 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8289 != XML_STATUS_ERROR) { 8290 fail("External parser allocator returned success incorrectly"); 8291 } 8292 } 8293 END_TEST 8294 8295 /* More external parser memory allocation testing */ 8296 START_TEST(test_alloc_run_external_parser) { 8297 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8298 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8299 "<doc>&entity;</doc>"; 8300 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8301 unsigned int i; 8302 const unsigned int max_alloc_count = 15; 8303 8304 for (i = 0; i < max_alloc_count; i++) { 8305 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8306 XML_SetUserData(g_parser, foo_text); 8307 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 8308 allocation_count = i; 8309 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8310 != XML_STATUS_ERROR) 8311 break; 8312 /* See comment in test_alloc_parse_xdecl() */ 8313 alloc_teardown(); 8314 alloc_setup(); 8315 } 8316 if (i == 0) 8317 fail("Parsing ignored failing allocator"); 8318 else if (i == max_alloc_count) 8319 fail("Parsing failed with allocation count 10"); 8320 } 8321 END_TEST 8322 8323 static int XMLCALL 8324 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context, 8325 const XML_Char *base, const XML_Char *systemId, 8326 const XML_Char *publicId) { 8327 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8328 const char *text; 8329 XML_Parser new_parser; 8330 int i; 8331 const int max_alloc_count = 20; 8332 8333 UNUSED_P(base); 8334 UNUSED_P(systemId); 8335 UNUSED_P(publicId); 8336 if (callno == 0) { 8337 /* First time through, check how many calls to malloc occur */ 8338 text = ("<!ELEMENT doc (e+)>\n" 8339 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8340 "<!ELEMENT e EMPTY>\n"); 8341 allocation_count = 10000; 8342 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8343 if (new_parser == NULL) { 8344 fail("Unable to allocate first external parser"); 8345 return XML_STATUS_ERROR; 8346 } 8347 /* Stash the number of calls in the user data */ 8348 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count)); 8349 } else { 8350 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8351 "<e/>"); 8352 /* Try at varying levels to exercise more code paths */ 8353 for (i = 0; i < max_alloc_count; i++) { 8354 allocation_count = callno + i; 8355 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8356 if (new_parser != NULL) 8357 break; 8358 } 8359 if (i == 0) { 8360 fail("Second external parser unexpectedly created"); 8361 XML_ParserFree(new_parser); 8362 return XML_STATUS_ERROR; 8363 } else if (i == max_alloc_count) { 8364 fail("Second external parser not created"); 8365 return XML_STATUS_ERROR; 8366 } 8367 } 8368 8369 allocation_count = ALLOC_ALWAYS_SUCCEED; 8370 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE) 8371 == XML_STATUS_ERROR) { 8372 xml_failure(new_parser); 8373 return XML_STATUS_ERROR; 8374 } 8375 XML_ParserFree(new_parser); 8376 return XML_STATUS_OK; 8377 } 8378 8379 /* Test that running out of memory in dtdCopy is correctly reported. 8380 * Based on test_default_ns_from_ext_subset_and_ext_ge() 8381 */ 8382 START_TEST(test_alloc_dtd_copy_default_atts) { 8383 const char *text = "<?xml version='1.0'?>\n" 8384 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8385 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8386 "]>\n" 8387 "<doc xmlns='http://example.org/ns1'>\n" 8388 "&en;\n" 8389 "</doc>"; 8390 8391 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8392 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler); 8393 XML_SetUserData(g_parser, NULL); 8394 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8395 == XML_STATUS_ERROR) 8396 xml_failure(g_parser); 8397 } 8398 END_TEST 8399 8400 static int XMLCALL 8401 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context, 8402 const XML_Char *base, const XML_Char *systemId, 8403 const XML_Char *publicId) { 8404 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8405 const char *text; 8406 XML_Parser new_parser; 8407 enum XML_Status rv; 8408 8409 UNUSED_P(base); 8410 UNUSED_P(systemId); 8411 UNUSED_P(publicId); 8412 if (callno == 0) { 8413 /* Try different allocation levels for whole exercise */ 8414 text = ("<!ELEMENT doc (e+)>\n" 8415 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8416 "<!ELEMENT e EMPTY>\n"); 8417 XML_SetUserData(parser, (void *)(intptr_t)1); 8418 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8419 if (new_parser == NULL) 8420 return XML_STATUS_ERROR; 8421 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8422 } else { 8423 /* Just run through once */ 8424 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8425 "<e/>"); 8426 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8427 if (new_parser == NULL) 8428 return XML_STATUS_ERROR; 8429 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8430 } 8431 XML_ParserFree(new_parser); 8432 if (rv == XML_STATUS_ERROR) 8433 return XML_STATUS_ERROR; 8434 return XML_STATUS_OK; 8435 } 8436 8437 /* Test more external entity allocation failure paths */ 8438 START_TEST(test_alloc_external_entity) { 8439 const char *text = "<?xml version='1.0'?>\n" 8440 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8441 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8442 "]>\n" 8443 "<doc xmlns='http://example.org/ns1'>\n" 8444 "&en;\n" 8445 "</doc>"; 8446 int i; 8447 const int alloc_test_max_repeats = 50; 8448 8449 for (i = 0; i < alloc_test_max_repeats; i++) { 8450 allocation_count = -1; 8451 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8452 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2); 8453 XML_SetUserData(g_parser, NULL); 8454 allocation_count = i; 8455 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8456 == XML_STATUS_OK) 8457 break; 8458 /* See comment in test_alloc_parse_xdecl() */ 8459 alloc_teardown(); 8460 alloc_setup(); 8461 } 8462 allocation_count = -1; 8463 if (i == 0) 8464 fail("External entity parsed despite duff allocator"); 8465 if (i == alloc_test_max_repeats) 8466 fail("External entity not parsed at max allocation count"); 8467 } 8468 END_TEST 8469 8470 /* Test more allocation failure paths */ 8471 static int XMLCALL 8472 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context, 8473 const XML_Char *base, 8474 const XML_Char *systemId, 8475 const XML_Char *publicId) { 8476 /* As for external_entity_loader() */ 8477 const char *text = "<?xml encoding='iso-8859-3'?>" 8478 "\xC3\xA9"; 8479 XML_Parser ext_parser; 8480 enum XML_Status status; 8481 8482 UNUSED_P(base); 8483 UNUSED_P(systemId); 8484 UNUSED_P(publicId); 8485 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8486 if (ext_parser == NULL) 8487 return XML_STATUS_ERROR; 8488 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) { 8489 XML_ParserFree(ext_parser); 8490 return XML_STATUS_ERROR; 8491 } 8492 status 8493 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8494 XML_ParserFree(ext_parser); 8495 if (status == XML_STATUS_ERROR) 8496 return XML_STATUS_ERROR; 8497 return XML_STATUS_OK; 8498 } 8499 8500 START_TEST(test_alloc_ext_entity_set_encoding) { 8501 const char *text = "<!DOCTYPE doc [\n" 8502 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8503 "]>\n" 8504 "<doc>&en;</doc>"; 8505 int i; 8506 const int max_allocation_count = 30; 8507 8508 for (i = 0; i < max_allocation_count; i++) { 8509 XML_SetExternalEntityRefHandler(g_parser, 8510 external_entity_alloc_set_encoding); 8511 allocation_count = i; 8512 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8513 == XML_STATUS_OK) 8514 break; 8515 allocation_count = -1; 8516 /* See comment in test_alloc_parse_xdecl() */ 8517 alloc_teardown(); 8518 alloc_setup(); 8519 } 8520 if (i == 0) 8521 fail("Encoding check succeeded despite failing allocator"); 8522 if (i == max_allocation_count) 8523 fail("Encoding failed at max allocation count"); 8524 } 8525 END_TEST 8526 8527 static int XMLCALL 8528 unknown_released_encoding_handler(void *data, const XML_Char *encoding, 8529 XML_Encoding *info) { 8530 UNUSED_P(data); 8531 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) { 8532 int i; 8533 8534 for (i = 0; i < 256; i++) 8535 info->map[i] = i; 8536 info->data = NULL; 8537 info->convert = NULL; 8538 info->release = dummy_release; 8539 return XML_STATUS_OK; 8540 } 8541 return XML_STATUS_ERROR; 8542 } 8543 8544 /* Test the effects of allocation failure in internal entities. 8545 * Based on test_unknown_encoding_internal_entity 8546 */ 8547 START_TEST(test_alloc_internal_entity) { 8548 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 8549 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 8550 "<test a='&foo;'/>"; 8551 unsigned int i; 8552 const unsigned int max_alloc_count = 20; 8553 8554 for (i = 0; i < max_alloc_count; i++) { 8555 allocation_count = i; 8556 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, 8557 NULL); 8558 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8559 != XML_STATUS_ERROR) 8560 break; 8561 /* See comment in test_alloc_parse_xdecl() */ 8562 alloc_teardown(); 8563 alloc_setup(); 8564 } 8565 if (i == 0) 8566 fail("Internal entity worked despite failing allocations"); 8567 else if (i == max_alloc_count) 8568 fail("Internal entity failed at max allocation count"); 8569 } 8570 END_TEST 8571 8572 /* Test the robustness against allocation failure of element handling 8573 * Based on test_dtd_default_handling(). 8574 */ 8575 START_TEST(test_alloc_dtd_default_handling) { 8576 const char *text = "<!DOCTYPE doc [\n" 8577 "<!ENTITY e SYSTEM 'http://example.org/e'>\n" 8578 "<!NOTATION n SYSTEM 'http://example.org/n'>\n" 8579 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n" 8580 "<!ELEMENT doc (#PCDATA)>\n" 8581 "<!ATTLIST doc a CDATA #IMPLIED>\n" 8582 "<?pi in dtd?>\n" 8583 "<!--comment in dtd-->\n" 8584 "]>\n" 8585 "<doc><![CDATA[text in doc]]></doc>"; 8586 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>"); 8587 CharData storage; 8588 int i; 8589 const int max_alloc_count = 25; 8590 8591 for (i = 0; i < max_alloc_count; i++) { 8592 allocation_count = i; 8593 dummy_handler_flags = 0; 8594 XML_SetDefaultHandler(g_parser, accumulate_characters); 8595 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 8596 dummy_end_doctype_handler); 8597 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8598 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8599 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 8600 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8601 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8602 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8603 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler, 8604 dummy_end_cdata_handler); 8605 XML_SetUnparsedEntityDeclHandler(g_parser, 8606 dummy_unparsed_entity_decl_handler); 8607 CharData_Init(&storage); 8608 XML_SetUserData(g_parser, &storage); 8609 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 8610 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8611 != XML_STATUS_ERROR) 8612 break; 8613 /* See comment in test_alloc_parse_xdecl() */ 8614 alloc_teardown(); 8615 alloc_setup(); 8616 } 8617 if (i == 0) 8618 fail("Default DTD parsed despite allocation failures"); 8619 if (i == max_alloc_count) 8620 fail("Default DTD not parsed with maximum alloc count"); 8621 CharData_CheckXMLChars(&storage, expected); 8622 if (dummy_handler_flags 8623 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG 8624 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG 8625 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG 8626 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG 8627 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG 8628 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG)) 8629 fail("Not all handlers were called"); 8630 } 8631 END_TEST 8632 8633 /* Test robustness of XML_SetEncoding() with a failing allocator */ 8634 START_TEST(test_alloc_explicit_encoding) { 8635 int i; 8636 const int max_alloc_count = 5; 8637 8638 for (i = 0; i < max_alloc_count; i++) { 8639 allocation_count = i; 8640 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK) 8641 break; 8642 } 8643 if (i == 0) 8644 fail("Encoding set despite failing allocator"); 8645 else if (i == max_alloc_count) 8646 fail("Encoding not set at max allocation count"); 8647 } 8648 END_TEST 8649 8650 /* Test robustness of XML_SetBase against a failing allocator */ 8651 START_TEST(test_alloc_set_base) { 8652 const XML_Char *new_base = XCS("/local/file/name.xml"); 8653 int i; 8654 const int max_alloc_count = 5; 8655 8656 for (i = 0; i < max_alloc_count; i++) { 8657 allocation_count = i; 8658 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK) 8659 break; 8660 } 8661 if (i == 0) 8662 fail("Base set despite failing allocator"); 8663 else if (i == max_alloc_count) 8664 fail("Base not set with max allocation count"); 8665 } 8666 END_TEST 8667 8668 /* Test buffer extension in the face of a duff reallocator */ 8669 START_TEST(test_alloc_realloc_buffer) { 8670 const char *text = get_buffer_test_text; 8671 void *buffer; 8672 int i; 8673 const int max_realloc_count = 10; 8674 8675 /* Get a smallish buffer */ 8676 for (i = 0; i < max_realloc_count; i++) { 8677 reallocation_count = i; 8678 buffer = XML_GetBuffer(g_parser, 1536); 8679 if (buffer == NULL) 8680 fail("1.5K buffer reallocation failed"); 8681 assert(buffer != NULL); 8682 memcpy(buffer, text, strlen(text)); 8683 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 8684 == XML_STATUS_OK) 8685 break; 8686 /* See comment in test_alloc_parse_xdecl() */ 8687 alloc_teardown(); 8688 alloc_setup(); 8689 } 8690 reallocation_count = -1; 8691 if (i == 0) 8692 fail("Parse succeeded with no reallocation"); 8693 else if (i == max_realloc_count) 8694 fail("Parse failed with max reallocation count"); 8695 } 8696 END_TEST 8697 8698 /* Same test for external entity parsers */ 8699 static int XMLCALL 8700 external_entity_reallocator(XML_Parser parser, const XML_Char *context, 8701 const XML_Char *base, const XML_Char *systemId, 8702 const XML_Char *publicId) { 8703 const char *text = get_buffer_test_text; 8704 XML_Parser ext_parser; 8705 void *buffer; 8706 enum XML_Status status; 8707 8708 UNUSED_P(base); 8709 UNUSED_P(systemId); 8710 UNUSED_P(publicId); 8711 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8712 if (ext_parser == NULL) 8713 fail("Could not create external entity parser"); 8714 8715 reallocation_count = (intptr_t)XML_GetUserData(parser); 8716 buffer = XML_GetBuffer(ext_parser, 1536); 8717 if (buffer == NULL) 8718 fail("Buffer allocation failed"); 8719 assert(buffer != NULL); 8720 memcpy(buffer, text, strlen(text)); 8721 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE); 8722 reallocation_count = -1; 8723 XML_ParserFree(ext_parser); 8724 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR; 8725 } 8726 8727 START_TEST(test_alloc_ext_entity_realloc_buffer) { 8728 const char *text = "<!DOCTYPE doc [\n" 8729 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8730 "]>\n" 8731 "<doc>&en;</doc>"; 8732 int i; 8733 const int max_realloc_count = 10; 8734 8735 for (i = 0; i < max_realloc_count; i++) { 8736 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator); 8737 XML_SetUserData(g_parser, (void *)(intptr_t)i); 8738 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8739 == XML_STATUS_OK) 8740 break; 8741 /* See comment in test_alloc_parse_xdecl() */ 8742 alloc_teardown(); 8743 alloc_setup(); 8744 } 8745 if (i == 0) 8746 fail("Succeeded with no reallocations"); 8747 if (i == max_realloc_count) 8748 fail("Failed with max reallocations"); 8749 } 8750 END_TEST 8751 8752 /* Test elements with many attributes are handled correctly */ 8753 START_TEST(test_alloc_realloc_many_attributes) { 8754 const char *text = "<!DOCTYPE doc [\n" 8755 "<!ATTLIST doc za CDATA 'default'>\n" 8756 "<!ATTLIST doc zb CDATA 'def2'>\n" 8757 "<!ATTLIST doc zc CDATA 'def3'>\n" 8758 "]>\n" 8759 "<doc a='1'" 8760 " b='2'" 8761 " c='3'" 8762 " d='4'" 8763 " e='5'" 8764 " f='6'" 8765 " g='7'" 8766 " h='8'" 8767 " i='9'" 8768 " j='10'" 8769 " k='11'" 8770 " l='12'" 8771 " m='13'" 8772 " n='14'" 8773 " p='15'" 8774 " q='16'" 8775 " r='17'" 8776 " s='18'>" 8777 "</doc>"; 8778 int i; 8779 const int max_realloc_count = 10; 8780 8781 for (i = 0; i < max_realloc_count; i++) { 8782 reallocation_count = i; 8783 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8784 != XML_STATUS_ERROR) 8785 break; 8786 /* See comment in test_alloc_parse_xdecl() */ 8787 alloc_teardown(); 8788 alloc_setup(); 8789 } 8790 if (i == 0) 8791 fail("Parse succeeded despite no reallocations"); 8792 if (i == max_realloc_count) 8793 fail("Parse failed at max reallocations"); 8794 } 8795 END_TEST 8796 8797 /* Test handling of a public entity with failing allocator */ 8798 START_TEST(test_alloc_public_entity_value) { 8799 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8800 "<doc></doc>\n"; 8801 char dtd_text[] 8802 = "<!ELEMENT doc EMPTY>\n" 8803 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n" 8804 "<!ENTITY % " 8805 /* Each line is 64 characters */ 8806 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8807 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8808 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8809 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8810 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8811 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8812 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8813 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8814 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8815 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8816 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8817 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8818 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8819 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8820 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8821 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8822 " '%e1;'>\n" 8823 "%e1;\n"; 8824 int i; 8825 const int max_alloc_count = 50; 8826 8827 for (i = 0; i < max_alloc_count; i++) { 8828 allocation_count = i; 8829 dummy_handler_flags = 0; 8830 XML_SetUserData(g_parser, dtd_text); 8831 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8832 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8833 /* Provoke a particular code path */ 8834 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8835 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8836 != XML_STATUS_ERROR) 8837 break; 8838 /* See comment in test_alloc_parse_xdecl() */ 8839 alloc_teardown(); 8840 alloc_setup(); 8841 } 8842 if (i == 0) 8843 fail("Parsing worked despite failing allocation"); 8844 if (i == max_alloc_count) 8845 fail("Parsing failed at max allocation count"); 8846 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG) 8847 fail("Entity declaration handler not called"); 8848 } 8849 END_TEST 8850 8851 START_TEST(test_alloc_realloc_subst_public_entity_value) { 8852 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8853 "<doc></doc>\n"; 8854 char dtd_text[] 8855 = "<!ELEMENT doc EMPTY>\n" 8856 "<!ENTITY % " 8857 /* Each line is 64 characters */ 8858 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8859 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8860 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8861 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8862 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8863 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8864 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8865 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8866 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8867 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8868 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8869 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8870 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8871 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8872 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8873 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8874 " PUBLIC 'foo' 'bar.ent'>\n" 8875 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8876 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8877 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8878 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8879 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8880 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8881 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8882 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8883 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8884 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8885 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8886 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8887 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8888 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8889 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8890 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;"; 8891 int i; 8892 const int max_realloc_count = 10; 8893 8894 for (i = 0; i < max_realloc_count; i++) { 8895 reallocation_count = i; 8896 XML_SetUserData(g_parser, dtd_text); 8897 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8898 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8899 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8900 != XML_STATUS_ERROR) 8901 break; 8902 /* See comment in test_alloc_parse_xdecl() */ 8903 alloc_teardown(); 8904 alloc_setup(); 8905 } 8906 if (i == 0) 8907 fail("Parsing worked despite failing reallocation"); 8908 if (i == max_realloc_count) 8909 fail("Parsing failed at max reallocation count"); 8910 } 8911 END_TEST 8912 8913 START_TEST(test_alloc_parse_public_doctype) { 8914 const char *text 8915 = "<?xml version='1.0' encoding='utf-8'?>\n" 8916 "<!DOCTYPE doc PUBLIC '" 8917 /* 64 characters per line */ 8918 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 8919 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8920 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8921 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8922 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8923 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8924 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8925 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8926 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8927 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8928 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8929 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8930 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8931 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8932 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8933 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8934 "' 'test'>\n" 8935 "<doc></doc>"; 8936 int i; 8937 const int max_alloc_count = 25; 8938 8939 for (i = 0; i < max_alloc_count; i++) { 8940 allocation_count = i; 8941 dummy_handler_flags = 0; 8942 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8943 dummy_end_doctype_decl_handler); 8944 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8945 != XML_STATUS_ERROR) 8946 break; 8947 /* See comment in test_alloc_parse_xdecl() */ 8948 alloc_teardown(); 8949 alloc_setup(); 8950 } 8951 if (i == 0) 8952 fail("Parse succeeded despite failing allocator"); 8953 if (i == max_alloc_count) 8954 fail("Parse failed at maximum allocation count"); 8955 if (dummy_handler_flags 8956 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG 8957 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG)) 8958 fail("Doctype handler functions not called"); 8959 } 8960 END_TEST 8961 8962 START_TEST(test_alloc_parse_public_doctype_long_name) { 8963 const char *text 8964 = "<?xml version='1.0' encoding='utf-8'?>\n" 8965 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '" 8966 /* 64 characters per line */ 8967 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8968 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8969 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8970 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8971 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8972 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8973 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8974 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8975 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8976 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8977 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8978 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8979 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8980 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8981 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8982 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8983 "'>\n" 8984 "<doc></doc>"; 8985 int i; 8986 const int max_alloc_count = 25; 8987 8988 for (i = 0; i < max_alloc_count; i++) { 8989 allocation_count = i; 8990 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8991 dummy_end_doctype_decl_handler); 8992 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8993 != XML_STATUS_ERROR) 8994 break; 8995 /* See comment in test_alloc_parse_xdecl() */ 8996 alloc_teardown(); 8997 alloc_setup(); 8998 } 8999 if (i == 0) 9000 fail("Parse succeeded despite failing allocator"); 9001 if (i == max_alloc_count) 9002 fail("Parse failed at maximum allocation count"); 9003 } 9004 END_TEST 9005 9006 static int XMLCALL 9007 external_entity_alloc(XML_Parser parser, const XML_Char *context, 9008 const XML_Char *base, const XML_Char *systemId, 9009 const XML_Char *publicId) { 9010 const char *text = (const char *)XML_GetUserData(parser); 9011 XML_Parser ext_parser; 9012 int parse_res; 9013 9014 UNUSED_P(base); 9015 UNUSED_P(systemId); 9016 UNUSED_P(publicId); 9017 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 9018 if (ext_parser == NULL) 9019 return XML_STATUS_ERROR; 9020 parse_res 9021 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 9022 XML_ParserFree(ext_parser); 9023 return parse_res; 9024 } 9025 9026 /* Test foreign DTD handling */ 9027 START_TEST(test_alloc_set_foreign_dtd) { 9028 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 9029 "<doc>&entity;</doc>"; 9030 char text2[] = "<!ELEMENT doc (#PCDATA)*>"; 9031 int i; 9032 const int max_alloc_count = 25; 9033 9034 for (i = 0; i < max_alloc_count; i++) { 9035 allocation_count = i; 9036 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9037 XML_SetUserData(g_parser, &text2); 9038 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9039 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 9040 fail("Could not set foreign DTD"); 9041 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE) 9042 != XML_STATUS_ERROR) 9043 break; 9044 /* See comment in test_alloc_parse_xdecl() */ 9045 alloc_teardown(); 9046 alloc_setup(); 9047 } 9048 if (i == 0) 9049 fail("Parse succeeded despite failing allocator"); 9050 if (i == max_alloc_count) 9051 fail("Parse failed at maximum allocation count"); 9052 } 9053 END_TEST 9054 9055 /* Test based on ibm/valid/P32/ibm32v04.xml */ 9056 START_TEST(test_alloc_attribute_enum_value) { 9057 const char *text = "<?xml version='1.0' standalone='no'?>\n" 9058 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 9059 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 9060 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n" 9061 "<!ELEMENT a EMPTY>\n" 9062 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>"; 9063 int i; 9064 const int max_alloc_count = 30; 9065 9066 for (i = 0; i < max_alloc_count; i++) { 9067 allocation_count = i; 9068 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9069 XML_SetUserData(g_parser, dtd_text); 9070 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9071 /* An attribute list handler provokes a different code path */ 9072 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9073 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9074 != XML_STATUS_ERROR) 9075 break; 9076 /* See comment in test_alloc_parse_xdecl() */ 9077 alloc_teardown(); 9078 alloc_setup(); 9079 } 9080 if (i == 0) 9081 fail("Parse succeeded despite failing allocator"); 9082 if (i == max_alloc_count) 9083 fail("Parse failed at maximum allocation count"); 9084 } 9085 END_TEST 9086 9087 /* Test attribute enums sufficient to overflow the string pool */ 9088 START_TEST(test_alloc_realloc_attribute_enum_value) { 9089 const char *text = "<?xml version='1.0' standalone='no'?>\n" 9090 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 9091 "<animal>This is a yellow tiger</animal>"; 9092 /* We wish to define a collection of attribute enums that will 9093 * cause the string pool storing them to have to expand. This 9094 * means more than 1024 bytes, including the parentheses and 9095 * separator bars. 9096 */ 9097 char dtd_text[] 9098 = "<!ELEMENT animal (#PCDATA)*>\n" 9099 "<!ATTLIST animal thing " 9100 "(default" 9101 /* Each line is 64 characters */ 9102 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9103 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9104 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9105 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9106 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9107 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9108 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9109 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9110 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9111 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9112 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9113 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9114 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9115 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9116 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9117 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)" 9118 " 'default'>"; 9119 int i; 9120 const int max_realloc_count = 10; 9121 9122 for (i = 0; i < max_realloc_count; i++) { 9123 reallocation_count = i; 9124 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9125 XML_SetUserData(g_parser, dtd_text); 9126 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9127 /* An attribute list handler provokes a different code path */ 9128 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9129 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9130 != XML_STATUS_ERROR) 9131 break; 9132 /* See comment in test_alloc_parse_xdecl() */ 9133 alloc_teardown(); 9134 alloc_setup(); 9135 } 9136 if (i == 0) 9137 fail("Parse succeeded despite failing reallocator"); 9138 if (i == max_realloc_count) 9139 fail("Parse failed at maximum reallocation count"); 9140 } 9141 END_TEST 9142 9143 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */ 9144 START_TEST(test_alloc_realloc_implied_attribute) { 9145 /* Forcing this particular code path is a balancing act. The 9146 * addition of the closing parenthesis and terminal NUL must be 9147 * what pushes the string of enums over the 1024-byte limit, 9148 * otherwise a different code path will pick up the realloc. 9149 */ 9150 const char *text 9151 = "<!DOCTYPE doc [\n" 9152 "<!ELEMENT doc EMPTY>\n" 9153 "<!ATTLIST doc a " 9154 /* Each line is 64 characters */ 9155 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9156 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9157 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9158 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9159 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9160 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9161 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9162 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9163 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9164 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9165 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9166 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9167 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9168 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9169 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9170 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 9171 " #IMPLIED>\n" 9172 "]><doc/>"; 9173 int i; 9174 const int max_realloc_count = 10; 9175 9176 for (i = 0; i < max_realloc_count; i++) { 9177 reallocation_count = i; 9178 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9179 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9180 != XML_STATUS_ERROR) 9181 break; 9182 /* See comment in test_alloc_parse_xdecl() */ 9183 alloc_teardown(); 9184 alloc_setup(); 9185 } 9186 if (i == 0) 9187 fail("Parse succeeded despite failing reallocator"); 9188 if (i == max_realloc_count) 9189 fail("Parse failed at maximum reallocation count"); 9190 } 9191 END_TEST 9192 9193 /* Test attribute enums in a defaulted attribute forcing pool growth */ 9194 START_TEST(test_alloc_realloc_default_attribute) { 9195 /* Forcing this particular code path is a balancing act. The 9196 * addition of the closing parenthesis and terminal NUL must be 9197 * what pushes the string of enums over the 1024-byte limit, 9198 * otherwise a different code path will pick up the realloc. 9199 */ 9200 const char *text 9201 = "<!DOCTYPE doc [\n" 9202 "<!ELEMENT doc EMPTY>\n" 9203 "<!ATTLIST doc a " 9204 /* Each line is 64 characters */ 9205 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9206 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9207 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9208 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9209 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9210 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9211 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9212 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9213 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9214 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9215 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9216 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9217 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9218 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9219 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9220 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 9221 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'" 9222 ">\n]><doc/>"; 9223 int i; 9224 const int max_realloc_count = 10; 9225 9226 for (i = 0; i < max_realloc_count; i++) { 9227 reallocation_count = i; 9228 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9229 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9230 != XML_STATUS_ERROR) 9231 break; 9232 /* See comment in test_alloc_parse_xdecl() */ 9233 alloc_teardown(); 9234 alloc_setup(); 9235 } 9236 if (i == 0) 9237 fail("Parse succeeded despite failing reallocator"); 9238 if (i == max_realloc_count) 9239 fail("Parse failed at maximum reallocation count"); 9240 } 9241 END_TEST 9242 9243 /* Test long notation name with dodgy allocator */ 9244 START_TEST(test_alloc_notation) { 9245 const char *text 9246 = "<!DOCTYPE doc [\n" 9247 "<!NOTATION " 9248 /* Each line is 64 characters */ 9249 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9250 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9251 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9252 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9253 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9254 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9255 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9256 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9257 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9258 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9259 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9260 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9261 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9262 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9263 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9264 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9265 " SYSTEM 'http://example.org/n'>\n" 9266 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA " 9267 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9268 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9269 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9270 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9271 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9272 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9273 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9274 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9275 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9276 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9277 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9278 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9279 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9280 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9281 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9282 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9283 ">\n" 9284 "<!ELEMENT doc EMPTY>\n" 9285 "]>\n<doc/>"; 9286 int i; 9287 const int max_alloc_count = 20; 9288 9289 for (i = 0; i < max_alloc_count; i++) { 9290 allocation_count = i; 9291 dummy_handler_flags = 0; 9292 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9293 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 9294 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9295 != XML_STATUS_ERROR) 9296 break; 9297 /* See comment in test_alloc_parse_xdecl() */ 9298 alloc_teardown(); 9299 alloc_setup(); 9300 } 9301 if (i == 0) 9302 fail("Parse succeeded despite allocation failures"); 9303 if (i == max_alloc_count) 9304 fail("Parse failed at maximum allocation count"); 9305 if (dummy_handler_flags 9306 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG)) 9307 fail("Entity declaration handler not called"); 9308 } 9309 END_TEST 9310 9311 /* Test public notation with dodgy allocator */ 9312 START_TEST(test_alloc_public_notation) { 9313 const char *text 9314 = "<!DOCTYPE doc [\n" 9315 "<!NOTATION note PUBLIC '" 9316 /* 64 characters per line */ 9317 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9318 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9319 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9320 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9321 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9322 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9323 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9324 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9325 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9326 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9327 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9328 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9329 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9330 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9331 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9332 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9333 "' 'foo'>\n" 9334 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9335 "<!ELEMENT doc EMPTY>\n" 9336 "]>\n<doc/>"; 9337 int i; 9338 const int max_alloc_count = 20; 9339 9340 for (i = 0; i < max_alloc_count; i++) { 9341 allocation_count = i; 9342 dummy_handler_flags = 0; 9343 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9344 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9345 != XML_STATUS_ERROR) 9346 break; 9347 /* See comment in test_alloc_parse_xdecl() */ 9348 alloc_teardown(); 9349 alloc_setup(); 9350 } 9351 if (i == 0) 9352 fail("Parse succeeded despite allocation failures"); 9353 if (i == max_alloc_count) 9354 fail("Parse failed at maximum allocation count"); 9355 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9356 fail("Notation handler not called"); 9357 } 9358 END_TEST 9359 9360 /* Test public notation with dodgy allocator */ 9361 START_TEST(test_alloc_system_notation) { 9362 const char *text 9363 = "<!DOCTYPE doc [\n" 9364 "<!NOTATION note SYSTEM '" 9365 /* 64 characters per line */ 9366 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9367 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9368 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9369 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9370 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9371 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9372 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9373 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9374 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9375 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9376 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9377 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9378 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9379 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9380 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9381 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9382 "'>\n" 9383 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9384 "<!ELEMENT doc EMPTY>\n" 9385 "]>\n<doc/>"; 9386 int i; 9387 const int max_alloc_count = 20; 9388 9389 for (i = 0; i < max_alloc_count; i++) { 9390 allocation_count = i; 9391 dummy_handler_flags = 0; 9392 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9393 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9394 != XML_STATUS_ERROR) 9395 break; 9396 /* See comment in test_alloc_parse_xdecl() */ 9397 alloc_teardown(); 9398 alloc_setup(); 9399 } 9400 if (i == 0) 9401 fail("Parse succeeded despite allocation failures"); 9402 if (i == max_alloc_count) 9403 fail("Parse failed at maximum allocation count"); 9404 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9405 fail("Notation handler not called"); 9406 } 9407 END_TEST 9408 9409 START_TEST(test_alloc_nested_groups) { 9410 const char *text 9411 = "<!DOCTYPE doc [\n" 9412 "<!ELEMENT doc " 9413 /* Sixteen elements per line */ 9414 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9415 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9416 "))))))))))))))))))))))))))))))))>\n" 9417 "<!ELEMENT e EMPTY>" 9418 "]>\n" 9419 "<doc><e/></doc>"; 9420 CharData storage; 9421 int i; 9422 const int max_alloc_count = 20; 9423 9424 for (i = 0; i < max_alloc_count; i++) { 9425 allocation_count = i; 9426 CharData_Init(&storage); 9427 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9428 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9429 XML_SetUserData(g_parser, &storage); 9430 dummy_handler_flags = 0; 9431 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9432 != XML_STATUS_ERROR) 9433 break; 9434 /* See comment in test_alloc_parse_xdecl() */ 9435 alloc_teardown(); 9436 alloc_setup(); 9437 } 9438 9439 if (i == 0) 9440 fail("Parse succeeded despite failing reallocator"); 9441 if (i == max_alloc_count) 9442 fail("Parse failed at maximum reallocation count"); 9443 CharData_CheckXMLChars(&storage, XCS("doce")); 9444 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9445 fail("Element handler not fired"); 9446 } 9447 END_TEST 9448 9449 START_TEST(test_alloc_realloc_nested_groups) { 9450 const char *text 9451 = "<!DOCTYPE doc [\n" 9452 "<!ELEMENT doc " 9453 /* Sixteen elements per line */ 9454 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9455 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9456 "))))))))))))))))))))))))))))))))>\n" 9457 "<!ELEMENT e EMPTY>" 9458 "]>\n" 9459 "<doc><e/></doc>"; 9460 CharData storage; 9461 int i; 9462 const int max_realloc_count = 10; 9463 9464 for (i = 0; i < max_realloc_count; i++) { 9465 reallocation_count = i; 9466 CharData_Init(&storage); 9467 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9468 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9469 XML_SetUserData(g_parser, &storage); 9470 dummy_handler_flags = 0; 9471 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9472 != XML_STATUS_ERROR) 9473 break; 9474 /* See comment in test_alloc_parse_xdecl() */ 9475 alloc_teardown(); 9476 alloc_setup(); 9477 } 9478 9479 if (i == 0) 9480 fail("Parse succeeded despite failing reallocator"); 9481 if (i == max_realloc_count) 9482 fail("Parse failed at maximum reallocation count"); 9483 CharData_CheckXMLChars(&storage, XCS("doce")); 9484 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9485 fail("Element handler not fired"); 9486 } 9487 END_TEST 9488 9489 START_TEST(test_alloc_large_group) { 9490 const char *text = "<!DOCTYPE doc [\n" 9491 "<!ELEMENT doc (" 9492 "a1|a2|a3|a4|a5|a6|a7|a8|" 9493 "b1|b2|b3|b4|b5|b6|b7|b8|" 9494 "c1|c2|c3|c4|c5|c6|c7|c8|" 9495 "d1|d2|d3|d4|d5|d6|d7|d8|" 9496 "e1" 9497 ")+>\n" 9498 "]>\n" 9499 "<doc>\n" 9500 "<a1/>\n" 9501 "</doc>\n"; 9502 int i; 9503 const int max_alloc_count = 50; 9504 9505 for (i = 0; i < max_alloc_count; i++) { 9506 allocation_count = i; 9507 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9508 dummy_handler_flags = 0; 9509 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9510 != XML_STATUS_ERROR) 9511 break; 9512 /* See comment in test_alloc_parse_xdecl() */ 9513 alloc_teardown(); 9514 alloc_setup(); 9515 } 9516 if (i == 0) 9517 fail("Parse succeeded despite failing allocator"); 9518 if (i == max_alloc_count) 9519 fail("Parse failed at maximum allocation count"); 9520 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9521 fail("Element handler flag not raised"); 9522 } 9523 END_TEST 9524 9525 START_TEST(test_alloc_realloc_group_choice) { 9526 const char *text = "<!DOCTYPE doc [\n" 9527 "<!ELEMENT doc (" 9528 "a1|a2|a3|a4|a5|a6|a7|a8|" 9529 "b1|b2|b3|b4|b5|b6|b7|b8|" 9530 "c1|c2|c3|c4|c5|c6|c7|c8|" 9531 "d1|d2|d3|d4|d5|d6|d7|d8|" 9532 "e1" 9533 ")+>\n" 9534 "]>\n" 9535 "<doc>\n" 9536 "<a1/>\n" 9537 "<b2 attr='foo'>This is a foo</b2>\n" 9538 "<c3></c3>\n" 9539 "</doc>\n"; 9540 int i; 9541 const int max_realloc_count = 10; 9542 9543 for (i = 0; i < max_realloc_count; i++) { 9544 reallocation_count = i; 9545 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9546 dummy_handler_flags = 0; 9547 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9548 != XML_STATUS_ERROR) 9549 break; 9550 /* See comment in test_alloc_parse_xdecl() */ 9551 alloc_teardown(); 9552 alloc_setup(); 9553 } 9554 if (i == 0) 9555 fail("Parse succeeded despite failing reallocator"); 9556 if (i == max_realloc_count) 9557 fail("Parse failed at maximum reallocation count"); 9558 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9559 fail("Element handler flag not raised"); 9560 } 9561 END_TEST 9562 9563 START_TEST(test_alloc_pi_in_epilog) { 9564 const char *text = "<doc></doc>\n" 9565 "<?pi in epilog?>"; 9566 int i; 9567 const int max_alloc_count = 15; 9568 9569 for (i = 0; i < max_alloc_count; i++) { 9570 allocation_count = i; 9571 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 9572 dummy_handler_flags = 0; 9573 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9574 != XML_STATUS_ERROR) 9575 break; 9576 /* See comment in test_alloc_parse_xdecl() */ 9577 alloc_teardown(); 9578 alloc_setup(); 9579 } 9580 if (i == 0) 9581 fail("Parse completed despite failing allocator"); 9582 if (i == max_alloc_count) 9583 fail("Parse failed at maximum allocation count"); 9584 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG) 9585 fail("Processing instruction handler not invoked"); 9586 } 9587 END_TEST 9588 9589 START_TEST(test_alloc_comment_in_epilog) { 9590 const char *text = "<doc></doc>\n" 9591 "<!-- comment in epilog -->"; 9592 int i; 9593 const int max_alloc_count = 15; 9594 9595 for (i = 0; i < max_alloc_count; i++) { 9596 allocation_count = i; 9597 XML_SetCommentHandler(g_parser, dummy_comment_handler); 9598 dummy_handler_flags = 0; 9599 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9600 != XML_STATUS_ERROR) 9601 break; 9602 /* See comment in test_alloc_parse_xdecl() */ 9603 alloc_teardown(); 9604 alloc_setup(); 9605 } 9606 if (i == 0) 9607 fail("Parse completed despite failing allocator"); 9608 if (i == max_alloc_count) 9609 fail("Parse failed at maximum allocation count"); 9610 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG) 9611 fail("Processing instruction handler not invoked"); 9612 } 9613 END_TEST 9614 9615 START_TEST(test_alloc_realloc_long_attribute_value) { 9616 const char *text 9617 = "<!DOCTYPE doc [<!ENTITY foo '" 9618 /* Each line is 64 characters */ 9619 "This entity will be substituted as an attribute value, and is " 9620 "calculated to be exactly long enough that the terminating NUL " 9621 "that the library adds internally will trigger the string pool to" 9622 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9623 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9624 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9625 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9626 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9627 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9628 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9629 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9630 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9631 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9632 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9633 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9634 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9635 "'>]>\n" 9636 "<doc a='&foo;'></doc>"; 9637 int i; 9638 const int max_realloc_count = 10; 9639 9640 for (i = 0; i < max_realloc_count; i++) { 9641 reallocation_count = i; 9642 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9643 != XML_STATUS_ERROR) 9644 break; 9645 /* See comment in test_alloc_parse_xdecl() */ 9646 alloc_teardown(); 9647 alloc_setup(); 9648 } 9649 if (i == 0) 9650 fail("Parse succeeded despite failing reallocator"); 9651 if (i == max_realloc_count) 9652 fail("Parse failed at maximum reallocation count"); 9653 } 9654 END_TEST 9655 9656 START_TEST(test_alloc_attribute_whitespace) { 9657 const char *text = "<doc a=' '></doc>"; 9658 int i; 9659 const int max_alloc_count = 15; 9660 9661 for (i = 0; i < max_alloc_count; i++) { 9662 allocation_count = i; 9663 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9664 != XML_STATUS_ERROR) 9665 break; 9666 /* See comment in test_alloc_parse_xdecl() */ 9667 alloc_teardown(); 9668 alloc_setup(); 9669 } 9670 if (i == 0) 9671 fail("Parse succeeded despite failing allocator"); 9672 if (i == max_alloc_count) 9673 fail("Parse failed at maximum allocation count"); 9674 } 9675 END_TEST 9676 9677 START_TEST(test_alloc_attribute_predefined_entity) { 9678 const char *text = "<doc a='&'></doc>"; 9679 int i; 9680 const int max_alloc_count = 15; 9681 9682 for (i = 0; i < max_alloc_count; i++) { 9683 allocation_count = i; 9684 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9685 != XML_STATUS_ERROR) 9686 break; 9687 /* See comment in test_alloc_parse_xdecl() */ 9688 alloc_teardown(); 9689 alloc_setup(); 9690 } 9691 if (i == 0) 9692 fail("Parse succeeded despite failing allocator"); 9693 if (i == max_alloc_count) 9694 fail("Parse failed at maximum allocation count"); 9695 } 9696 END_TEST 9697 9698 /* Test that a character reference at the end of a suitably long 9699 * default value for an attribute can trigger pool growth, and recovers 9700 * if the allocator fails on it. 9701 */ 9702 START_TEST(test_alloc_long_attr_default_with_char_ref) { 9703 const char *text 9704 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '" 9705 /* 64 characters per line */ 9706 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9707 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9708 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9709 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9710 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9711 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9712 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9713 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9714 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9715 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9716 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9717 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9718 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9719 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9720 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9721 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI" 9722 "1'>]>\n" 9723 "<doc/>"; 9724 int i; 9725 const int max_alloc_count = 20; 9726 9727 for (i = 0; i < max_alloc_count; i++) { 9728 allocation_count = i; 9729 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9730 != XML_STATUS_ERROR) 9731 break; 9732 /* See comment in test_alloc_parse_xdecl() */ 9733 alloc_teardown(); 9734 alloc_setup(); 9735 } 9736 if (i == 0) 9737 fail("Parse succeeded despite failing allocator"); 9738 if (i == max_alloc_count) 9739 fail("Parse failed at maximum allocation count"); 9740 } 9741 END_TEST 9742 9743 /* Test that a long character reference substitution triggers a pool 9744 * expansion correctly for an attribute value. 9745 */ 9746 START_TEST(test_alloc_long_attr_value) { 9747 const char *text 9748 = "<!DOCTYPE test [<!ENTITY foo '\n" 9749 /* 64 characters per line */ 9750 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9751 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9752 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9753 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9754 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9755 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9756 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9757 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9758 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9759 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9760 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9761 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9762 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9763 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9764 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9765 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9766 "'>]>\n" 9767 "<test a='&foo;'/>"; 9768 int i; 9769 const int max_alloc_count = 25; 9770 9771 for (i = 0; i < max_alloc_count; i++) { 9772 allocation_count = i; 9773 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9774 != XML_STATUS_ERROR) 9775 break; 9776 /* See comment in test_alloc_parse_xdecl() */ 9777 alloc_teardown(); 9778 alloc_setup(); 9779 } 9780 if (i == 0) 9781 fail("Parse succeeded despite failing allocator"); 9782 if (i == max_alloc_count) 9783 fail("Parse failed at maximum allocation count"); 9784 } 9785 END_TEST 9786 9787 /* Test that an error in a nested parameter entity substitution is 9788 * handled correctly. It seems unlikely that the code path being 9789 * exercised can be reached purely by carefully crafted XML, but an 9790 * allocation error in the right place will definitely do it. 9791 */ 9792 START_TEST(test_alloc_nested_entities) { 9793 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 9794 "<doc />"; 9795 ExtFaults test_data 9796 = {"<!ENTITY % pe1 '" 9797 /* 64 characters per line */ 9798 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9799 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9800 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9801 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9802 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9803 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9804 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9805 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9806 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9807 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9808 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9809 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9810 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9811 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9812 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9813 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9814 "'>\n" 9815 "<!ENTITY % pe2 '%pe1;'>\n" 9816 "%pe2;", 9817 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY}; 9818 9819 /* Causes an allocation error in a nested storeEntityValue() */ 9820 allocation_count = 12; 9821 XML_SetUserData(g_parser, &test_data); 9822 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9823 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 9824 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 9825 "Entity allocation failure not noted"); 9826 } 9827 END_TEST 9828 9829 START_TEST(test_alloc_realloc_param_entity_newline) { 9830 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9831 "<doc/>"; 9832 char dtd_text[] 9833 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9834 /* 64 characters per line */ 9835 "This default value is carefully crafted so that the carriage " 9836 "return right at the end of the entity string causes an internal " 9837 "string pool to have to grow. This allows us to test the alloc " 9838 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9839 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9840 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9841 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9842 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9843 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9844 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9845 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9846 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9847 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9848 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9849 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9850 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE" 9851 "\">\n'>" 9852 "%pe;\n"; 9853 int i; 9854 const int max_realloc_count = 5; 9855 9856 for (i = 0; i < max_realloc_count; i++) { 9857 reallocation_count = i; 9858 XML_SetUserData(g_parser, dtd_text); 9859 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9860 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9861 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9862 != XML_STATUS_ERROR) 9863 break; 9864 /* See comment in test_alloc_parse_xdecl() */ 9865 alloc_teardown(); 9866 alloc_setup(); 9867 } 9868 if (i == 0) 9869 fail("Parse succeeded despite failing reallocator"); 9870 if (i == max_realloc_count) 9871 fail("Parse failed at maximum reallocation count"); 9872 } 9873 END_TEST 9874 9875 START_TEST(test_alloc_realloc_ce_extends_pe) { 9876 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9877 "<doc/>"; 9878 char dtd_text[] 9879 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9880 /* 64 characters per line */ 9881 "This default value is carefully crafted so that the character " 9882 "entity at the end causes an internal string pool to have to " 9883 "grow. This allows us to test the allocation failure path from " 9884 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9885 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9886 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9887 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9888 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9889 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9890 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9891 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9892 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9893 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9894 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9895 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9896 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ" 9897 "\">\n'>" 9898 "%pe;\n"; 9899 int i; 9900 const int max_realloc_count = 5; 9901 9902 for (i = 0; i < max_realloc_count; i++) { 9903 reallocation_count = i; 9904 XML_SetUserData(g_parser, dtd_text); 9905 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9906 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9907 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9908 != XML_STATUS_ERROR) 9909 break; 9910 /* See comment in test_alloc_parse_xdecl() */ 9911 alloc_teardown(); 9912 alloc_setup(); 9913 } 9914 if (i == 0) 9915 fail("Parse succeeded despite failing reallocator"); 9916 if (i == max_realloc_count) 9917 fail("Parse failed at maximum reallocation count"); 9918 } 9919 END_TEST 9920 9921 START_TEST(test_alloc_realloc_attributes) { 9922 const char *text = "<!DOCTYPE doc [\n" 9923 " <!ATTLIST doc\n" 9924 " a1 (a|b|c) 'a'\n" 9925 " a2 (foo|bar) #IMPLIED\n" 9926 " a3 NMTOKEN #IMPLIED\n" 9927 " a4 NMTOKENS #IMPLIED\n" 9928 " a5 ID #IMPLIED\n" 9929 " a6 IDREF #IMPLIED\n" 9930 " a7 IDREFS #IMPLIED\n" 9931 " a8 ENTITY #IMPLIED\n" 9932 " a9 ENTITIES #IMPLIED\n" 9933 " a10 CDATA #IMPLIED\n" 9934 " >]>\n" 9935 "<doc>wombat</doc>\n"; 9936 int i; 9937 const int max_realloc_count = 5; 9938 9939 for (i = 0; i < max_realloc_count; i++) { 9940 reallocation_count = i; 9941 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9942 != XML_STATUS_ERROR) 9943 break; 9944 /* See comment in test_alloc_parse_xdecl() */ 9945 alloc_teardown(); 9946 alloc_setup(); 9947 } 9948 9949 if (i == 0) 9950 fail("Parse succeeded despite failing reallocator"); 9951 if (i == max_realloc_count) 9952 fail("Parse failed at maximum reallocation count"); 9953 } 9954 END_TEST 9955 9956 START_TEST(test_alloc_long_doc_name) { 9957 const char *text = 9958 /* 64 characters per line */ 9959 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr" 9960 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9961 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9962 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9963 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9964 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9965 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9966 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9967 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9968 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9969 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9970 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9971 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9972 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9973 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9974 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9975 " a='1'/>"; 9976 int i; 9977 const int max_alloc_count = 20; 9978 9979 for (i = 0; i < max_alloc_count; i++) { 9980 allocation_count = i; 9981 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9982 != XML_STATUS_ERROR) 9983 break; 9984 /* See comment in test_alloc_parse_xdecl() */ 9985 alloc_teardown(); 9986 alloc_setup(); 9987 } 9988 if (i == 0) 9989 fail("Parsing worked despite failing reallocations"); 9990 else if (i == max_alloc_count) 9991 fail("Parsing failed even at max reallocation count"); 9992 } 9993 END_TEST 9994 9995 START_TEST(test_alloc_long_base) { 9996 const char *text = "<!DOCTYPE doc [\n" 9997 " <!ENTITY e SYSTEM 'foo'>\n" 9998 "]>\n" 9999 "<doc>&e;</doc>"; 10000 char entity_text[] = "Hello world"; 10001 const XML_Char *base = 10002 /* 64 characters per line */ 10003 /* clang-format off */ 10004 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t") 10005 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10006 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10007 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10008 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10009 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10010 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10011 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10012 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10013 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10014 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10015 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10016 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10017 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10018 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 10019 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"); 10020 /* clang-format on */ 10021 int i; 10022 const int max_alloc_count = 25; 10023 10024 for (i = 0; i < max_alloc_count; i++) { 10025 allocation_count = i; 10026 XML_SetUserData(g_parser, entity_text); 10027 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10028 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 10029 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) { 10030 XML_ParserReset(g_parser, NULL); 10031 continue; 10032 } 10033 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10034 != XML_STATUS_ERROR) 10035 break; 10036 /* See comment in test_alloc_parse_xdecl() */ 10037 alloc_teardown(); 10038 alloc_setup(); 10039 } 10040 if (i == 0) 10041 fail("Parsing worked despite failing allocations"); 10042 else if (i == max_alloc_count) 10043 fail("Parsing failed even at max allocation count"); 10044 } 10045 END_TEST 10046 10047 START_TEST(test_alloc_long_public_id) { 10048 const char *text 10049 = "<!DOCTYPE doc [\n" 10050 " <!ENTITY e PUBLIC '" 10051 /* 64 characters per line */ 10052 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec" 10053 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10054 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10055 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10056 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10057 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10058 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10059 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10060 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10061 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10062 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10063 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10064 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10065 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10066 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10067 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10068 "' 'bar'>\n" 10069 "]>\n" 10070 "<doc>&e;</doc>"; 10071 char entity_text[] = "Hello world"; 10072 int i; 10073 const int max_alloc_count = 40; 10074 10075 for (i = 0; i < max_alloc_count; i++) { 10076 allocation_count = i; 10077 XML_SetUserData(g_parser, entity_text); 10078 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10079 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 10080 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10081 != XML_STATUS_ERROR) 10082 break; 10083 /* See comment in test_alloc_parse_xdecl() */ 10084 alloc_teardown(); 10085 alloc_setup(); 10086 } 10087 if (i == 0) 10088 fail("Parsing worked despite failing allocations"); 10089 else if (i == max_alloc_count) 10090 fail("Parsing failed even at max allocation count"); 10091 } 10092 END_TEST 10093 10094 START_TEST(test_alloc_long_entity_value) { 10095 const char *text 10096 = "<!DOCTYPE doc [\n" 10097 " <!ENTITY e1 '" 10098 /* 64 characters per line */ 10099 "Long entity value that should provoke a string pool to grow whil" 10100 "e setting up to parse the external entity below. xyz0123456789AB" 10101 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10102 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10103 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10104 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10105 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10106 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10107 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10108 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10109 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10110 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10111 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10112 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10113 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10114 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10115 "'>\n" 10116 " <!ENTITY e2 SYSTEM 'bar'>\n" 10117 "]>\n" 10118 "<doc>&e2;</doc>"; 10119 char entity_text[] = "Hello world"; 10120 int i; 10121 const int max_alloc_count = 40; 10122 10123 for (i = 0; i < max_alloc_count; i++) { 10124 allocation_count = i; 10125 XML_SetUserData(g_parser, entity_text); 10126 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10127 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 10128 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10129 != XML_STATUS_ERROR) 10130 break; 10131 /* See comment in test_alloc_parse_xdecl() */ 10132 alloc_teardown(); 10133 alloc_setup(); 10134 } 10135 if (i == 0) 10136 fail("Parsing worked despite failing allocations"); 10137 else if (i == max_alloc_count) 10138 fail("Parsing failed even at max allocation count"); 10139 } 10140 END_TEST 10141 10142 START_TEST(test_alloc_long_notation) { 10143 const char *text 10144 = "<!DOCTYPE doc [\n" 10145 " <!NOTATION note SYSTEM '" 10146 /* 64 characters per line */ 10147 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 10148 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10149 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10150 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10151 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10152 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10153 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10154 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10155 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10156 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10157 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10158 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10159 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10160 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10161 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10162 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10163 "'>\n" 10164 " <!ENTITY e1 SYSTEM 'foo' NDATA " 10165 /* 64 characters per line */ 10166 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 10167 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10168 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10169 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10170 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10171 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10172 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10173 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10174 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10175 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10176 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10177 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10178 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10179 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10180 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10181 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 10182 ">\n" 10183 " <!ENTITY e2 SYSTEM 'bar'>\n" 10184 "]>\n" 10185 "<doc>&e2;</doc>"; 10186 ExtOption options[] 10187 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}}; 10188 int i; 10189 const int max_alloc_count = 40; 10190 10191 for (i = 0; i < max_alloc_count; i++) { 10192 allocation_count = i; 10193 XML_SetUserData(g_parser, options); 10194 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10195 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10196 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10197 != XML_STATUS_ERROR) 10198 break; 10199 10200 /* See comment in test_alloc_parse_xdecl() */ 10201 alloc_teardown(); 10202 alloc_setup(); 10203 } 10204 if (i == 0) 10205 fail("Parsing worked despite failing allocations"); 10206 else if (i == max_alloc_count) 10207 fail("Parsing failed even at max allocation count"); 10208 } 10209 END_TEST 10210 10211 static int XMLCALL 10212 external_entity_parser_create_alloc_fail_handler(XML_Parser parser, 10213 const XML_Char *context, 10214 const XML_Char *base, 10215 const XML_Char *systemId, 10216 const XML_Char *publicId) { 10217 UNUSED_P(base); 10218 UNUSED_P(systemId); 10219 UNUSED_P(publicId); 10220 10221 if (context != NULL) 10222 fail("Unexpected non-NULL context"); 10223 10224 // The following number intends to fail the upcoming allocation in line 10225 // "parser->m_protocolEncodingName = copyString(encodingName, 10226 // &(parser->m_mem));" in function parserInit. 10227 allocation_count = 3; 10228 10229 const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL 10230 const XML_Parser ext_parser 10231 = XML_ExternalEntityParserCreate(parser, context, encodingName); 10232 if (ext_parser != NULL) 10233 fail( 10234 "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory"); 10235 10236 allocation_count = ALLOC_ALWAYS_SUCCEED; 10237 return XML_STATUS_ERROR; 10238 } 10239 10240 START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) { 10241 const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>"; 10242 10243 XML_SetExternalEntityRefHandler( 10244 g_parser, external_entity_parser_create_alloc_fail_handler); 10245 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10246 10247 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 10248 != XML_STATUS_ERROR) 10249 fail("Call to parse was expected to fail"); 10250 10251 if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) 10252 fail("Call to parse was expected to fail from the external entity handler"); 10253 10254 XML_ParserReset(g_parser, NULL); 10255 } 10256 END_TEST 10257 10258 static void 10259 nsalloc_setup(void) { 10260 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 10261 XML_Char ns_sep[2] = {' ', '\0'}; 10262 10263 /* Ensure the parser creation will go through */ 10264 allocation_count = ALLOC_ALWAYS_SUCCEED; 10265 reallocation_count = REALLOC_ALWAYS_SUCCEED; 10266 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep); 10267 if (g_parser == NULL) 10268 fail("Parser not created"); 10269 } 10270 10271 static void 10272 nsalloc_teardown(void) { 10273 basic_teardown(); 10274 } 10275 10276 /* Test the effects of allocation failure in simple namespace parsing. 10277 * Based on test_ns_default_with_empty_uri() 10278 */ 10279 START_TEST(test_nsalloc_xmlns) { 10280 const char *text = "<doc xmlns='http://example.org/'>\n" 10281 " <e xmlns=''/>\n" 10282 "</doc>"; 10283 unsigned int i; 10284 const unsigned int max_alloc_count = 30; 10285 10286 for (i = 0; i < max_alloc_count; i++) { 10287 allocation_count = i; 10288 /* Exercise more code paths with a default handler */ 10289 XML_SetDefaultHandler(g_parser, dummy_default_handler); 10290 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10291 != XML_STATUS_ERROR) 10292 break; 10293 /* Resetting the parser is insufficient, because some memory 10294 * allocations are cached within the parser. Instead we use 10295 * the teardown and setup routines to ensure that we have the 10296 * right sort of parser back in our hands. 10297 */ 10298 nsalloc_teardown(); 10299 nsalloc_setup(); 10300 } 10301 if (i == 0) 10302 fail("Parsing worked despite failing allocations"); 10303 else if (i == max_alloc_count) 10304 fail("Parsing failed even at maximum allocation count"); 10305 } 10306 END_TEST 10307 10308 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */ 10309 START_TEST(test_nsalloc_parse_buffer) { 10310 const char *text = "<doc>Hello</doc>"; 10311 void *buffer; 10312 10313 /* Try a parse before the start of the world */ 10314 /* (Exercises new code path) */ 10315 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10316 fail("Pre-init XML_ParseBuffer not faulted"); 10317 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER) 10318 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10319 10320 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */); 10321 if (buffer == NULL) 10322 fail("Could not acquire parse buffer"); 10323 10324 allocation_count = 0; 10325 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10326 fail("Pre-init XML_ParseBuffer not faulted"); 10327 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY) 10328 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10329 10330 /* Now with actual memory allocation */ 10331 allocation_count = ALLOC_ALWAYS_SUCCEED; 10332 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK) 10333 xml_failure(g_parser); 10334 10335 /* Check that resuming an unsuspended parser is faulted */ 10336 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 10337 fail("Resuming unsuspended parser not faulted"); 10338 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED) 10339 xml_failure(g_parser); 10340 10341 /* Get the parser into suspended state */ 10342 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 10343 resumable = XML_TRUE; 10344 buffer = XML_GetBuffer(g_parser, (int)strlen(text)); 10345 if (buffer == NULL) 10346 fail("Could not acquire parse buffer"); 10347 assert(buffer != NULL); 10348 memcpy(buffer, text, strlen(text)); 10349 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10350 != XML_STATUS_SUSPENDED) 10351 xml_failure(g_parser); 10352 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 10353 xml_failure(g_parser); 10354 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10355 != XML_STATUS_ERROR) 10356 fail("Suspended XML_ParseBuffer not faulted"); 10357 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 10358 xml_failure(g_parser); 10359 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10360 fail("Suspended XML_GetBuffer not faulted"); 10361 10362 /* Get it going again and complete the world */ 10363 XML_SetCharacterDataHandler(g_parser, NULL); 10364 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 10365 xml_failure(g_parser); 10366 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10367 != XML_STATUS_ERROR) 10368 fail("Post-finishing XML_ParseBuffer not faulted"); 10369 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED) 10370 xml_failure(g_parser); 10371 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10372 fail("Post-finishing XML_GetBuffer not faulted"); 10373 } 10374 END_TEST 10375 10376 /* Check handling of long prefix names (pool growth) */ 10377 START_TEST(test_nsalloc_long_prefix) { 10378 const char *text 10379 = "<" 10380 /* 64 characters per line */ 10381 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10382 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10383 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10384 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10385 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10386 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10387 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10388 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10389 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10390 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10391 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10392 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10393 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10394 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10395 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10396 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10397 ":foo xmlns:" 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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10412 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10413 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10414 "='http://example.org/'>" 10415 "</" 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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10431 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10432 ":foo>"; 10433 int i; 10434 const int max_alloc_count = 40; 10435 10436 for (i = 0; i < max_alloc_count; i++) { 10437 allocation_count = i; 10438 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10439 != XML_STATUS_ERROR) 10440 break; 10441 /* See comment in test_nsalloc_xmlns() */ 10442 nsalloc_teardown(); 10443 nsalloc_setup(); 10444 } 10445 if (i == 0) 10446 fail("Parsing worked despite failing allocations"); 10447 else if (i == max_alloc_count) 10448 fail("Parsing failed even at max allocation count"); 10449 } 10450 END_TEST 10451 10452 /* Check handling of long uri names (pool growth) */ 10453 START_TEST(test_nsalloc_long_uri) { 10454 const char *text 10455 = "<foo:e xmlns:foo='http://example.org/" 10456 /* 64 characters per line */ 10457 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10458 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10459 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10460 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10461 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10462 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10463 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10464 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10465 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10466 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10467 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10468 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10469 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10470 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10471 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10472 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10473 "' bar:a='12'\n" 10474 "xmlns:bar='http://example.org/" 10475 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10476 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10477 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10478 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10479 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10480 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10481 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10482 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10483 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10484 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10485 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10486 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10487 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10488 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10489 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10490 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10491 "'>" 10492 "</foo:e>"; 10493 int i; 10494 const int max_alloc_count = 40; 10495 10496 for (i = 0; i < max_alloc_count; i++) { 10497 allocation_count = i; 10498 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10499 != XML_STATUS_ERROR) 10500 break; 10501 /* See comment in test_nsalloc_xmlns() */ 10502 nsalloc_teardown(); 10503 nsalloc_setup(); 10504 } 10505 if (i == 0) 10506 fail("Parsing worked despite failing allocations"); 10507 else if (i == max_alloc_count) 10508 fail("Parsing failed even at max allocation count"); 10509 } 10510 END_TEST 10511 10512 /* Test handling of long attribute names with prefixes */ 10513 START_TEST(test_nsalloc_long_attr) { 10514 const char *text 10515 = "<foo:e xmlns:foo='http://example.org/' bar:" 10516 /* 64 characters per line */ 10517 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10518 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10519 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10520 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10521 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10522 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10523 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10525 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10526 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10527 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10528 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10529 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10530 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10531 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10533 "='12'\n" 10534 "xmlns:bar='http://example.org/'>" 10535 "</foo:e>"; 10536 int i; 10537 const int max_alloc_count = 40; 10538 10539 for (i = 0; i < max_alloc_count; i++) { 10540 allocation_count = i; 10541 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10542 != XML_STATUS_ERROR) 10543 break; 10544 /* See comment in test_nsalloc_xmlns() */ 10545 nsalloc_teardown(); 10546 nsalloc_setup(); 10547 } 10548 if (i == 0) 10549 fail("Parsing worked despite failing allocations"); 10550 else if (i == max_alloc_count) 10551 fail("Parsing failed even at max allocation count"); 10552 } 10553 END_TEST 10554 10555 /* Test handling of an attribute name with a long namespace prefix */ 10556 START_TEST(test_nsalloc_long_attr_prefix) { 10557 const char *text 10558 = "<foo:e xmlns:foo='http://example.org/' " 10559 /* 64 characters per line */ 10560 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10561 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10562 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10563 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10564 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10565 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10566 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10567 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10568 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10569 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10570 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10571 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10572 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10573 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10574 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10575 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10576 ":a='12'\n" 10577 "xmlns:" 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 "='http://example.org/'>" 10596 "</foo:e>"; 10597 const XML_Char *elemstr[] = { 10598 /* clang-format off */ 10599 XCS("http://example.org/ e foo"), 10600 XCS("http://example.org/ a ") 10601 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10602 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10603 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10604 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10605 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10606 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10607 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10608 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10609 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10610 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10611 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10612 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10613 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10614 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10615 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10616 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10617 /* clang-format on */ 10618 }; 10619 int i; 10620 const int max_alloc_count = 40; 10621 10622 for (i = 0; i < max_alloc_count; i++) { 10623 allocation_count = i; 10624 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10625 XML_SetUserData(g_parser, (void *)elemstr); 10626 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10627 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10628 != XML_STATUS_ERROR) 10629 break; 10630 /* See comment in test_nsalloc_xmlns() */ 10631 nsalloc_teardown(); 10632 nsalloc_setup(); 10633 } 10634 if (i == 0) 10635 fail("Parsing worked despite failing allocations"); 10636 else if (i == max_alloc_count) 10637 fail("Parsing failed even at max allocation count"); 10638 } 10639 END_TEST 10640 10641 /* Test attribute handling in the face of a dodgy reallocator */ 10642 START_TEST(test_nsalloc_realloc_attributes) { 10643 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 10644 " xmlns:bar='http://example.org/'>" 10645 "</foo:e>"; 10646 int i; 10647 const int max_realloc_count = 10; 10648 10649 for (i = 0; i < max_realloc_count; i++) { 10650 reallocation_count = i; 10651 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10652 != XML_STATUS_ERROR) 10653 break; 10654 /* See comment in test_nsalloc_xmlns() */ 10655 nsalloc_teardown(); 10656 nsalloc_setup(); 10657 } 10658 if (i == 0) 10659 fail("Parsing worked despite failing reallocations"); 10660 else if (i == max_realloc_count) 10661 fail("Parsing failed at max reallocation count"); 10662 } 10663 END_TEST 10664 10665 /* Test long element names with namespaces under a failing allocator */ 10666 START_TEST(test_nsalloc_long_element) { 10667 const char *text 10668 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 10669 " xmlns:foo='http://example.org/' bar:a='12'\n" 10670 " xmlns:bar='http://example.org/'>" 10671 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 10672 const XML_Char *elemstr[] 10673 = {XCS("http://example.org/") 10674 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 10675 XCS("http://example.org/ a bar")}; 10676 int i; 10677 const int max_alloc_count = 30; 10678 10679 for (i = 0; i < max_alloc_count; i++) { 10680 allocation_count = i; 10681 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10682 XML_SetUserData(g_parser, (void *)elemstr); 10683 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10684 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10685 != XML_STATUS_ERROR) 10686 break; 10687 /* See comment in test_nsalloc_xmlns() */ 10688 nsalloc_teardown(); 10689 nsalloc_setup(); 10690 } 10691 if (i == 0) 10692 fail("Parsing worked despite failing reallocations"); 10693 else if (i == max_alloc_count) 10694 fail("Parsing failed at max reallocation count"); 10695 } 10696 END_TEST 10697 10698 /* Test the effects of reallocation failure when reassigning a 10699 * binding. 10700 * 10701 * XML_ParserReset does not free the BINDING structures used by a 10702 * parser, but instead adds them to an internal free list to be reused 10703 * as necessary. Likewise the URI buffers allocated for the binding 10704 * aren't freed, but kept attached to their existing binding. If the 10705 * new binding has a longer URI, it will need reallocation. This test 10706 * provokes that reallocation, and tests the control path if it fails. 10707 */ 10708 START_TEST(test_nsalloc_realloc_binding_uri) { 10709 const char *first = "<doc xmlns='http://example.org/'>\n" 10710 " <e xmlns='' />\n" 10711 "</doc>"; 10712 const char *second 10713 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n" 10714 " <e xmlns='' />\n" 10715 "</doc>"; 10716 unsigned i; 10717 const unsigned max_realloc_count = 10; 10718 10719 /* First, do a full parse that will leave bindings around */ 10720 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE) 10721 == XML_STATUS_ERROR) 10722 xml_failure(g_parser); 10723 10724 /* Now repeat with a longer URI and a duff reallocator */ 10725 for (i = 0; i < max_realloc_count; i++) { 10726 XML_ParserReset(g_parser, NULL); 10727 reallocation_count = i; 10728 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE) 10729 != XML_STATUS_ERROR) 10730 break; 10731 } 10732 if (i == 0) 10733 fail("Parsing worked despite failing reallocation"); 10734 else if (i == max_realloc_count) 10735 fail("Parsing failed at max reallocation count"); 10736 } 10737 END_TEST 10738 10739 /* Check handling of long prefix names (pool growth) */ 10740 START_TEST(test_nsalloc_realloc_long_prefix) { 10741 const char *text 10742 = "<" 10743 /* 64 characters per line */ 10744 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10745 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10746 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 ":foo xmlns:" 10761 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10762 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10763 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10764 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10765 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10766 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10767 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10768 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10769 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10770 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10771 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10772 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10773 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10774 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10777 "='http://example.org/'>" 10778 "</" 10779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10782 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 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 ":foo>"; 10796 int i; 10797 const int max_realloc_count = 12; 10798 10799 for (i = 0; i < max_realloc_count; i++) { 10800 reallocation_count = i; 10801 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10802 != XML_STATUS_ERROR) 10803 break; 10804 /* See comment in test_nsalloc_xmlns() */ 10805 nsalloc_teardown(); 10806 nsalloc_setup(); 10807 } 10808 if (i == 0) 10809 fail("Parsing worked despite failing reallocations"); 10810 else if (i == max_realloc_count) 10811 fail("Parsing failed even at max reallocation count"); 10812 } 10813 END_TEST 10814 10815 /* Check handling of even long prefix names (different code path) */ 10816 START_TEST(test_nsalloc_realloc_longer_prefix) { 10817 const char *text 10818 = "<" 10819 /* 64 characters per line */ 10820 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10821 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10822 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10823 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10824 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10825 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10826 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10827 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10828 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10829 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10830 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10831 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10832 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10833 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10834 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10835 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10836 "Q:foo xmlns:" 10837 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10838 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10839 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10840 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10841 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10842 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10843 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10844 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10845 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10846 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10847 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10848 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10849 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10850 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10851 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10852 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10853 "Q='http://example.org/'>" 10854 "</" 10855 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10856 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10857 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10858 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10859 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10860 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10861 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10862 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10863 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10864 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10865 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10866 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10867 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10868 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10869 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10870 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10871 "Q:foo>"; 10872 int i; 10873 const int max_realloc_count = 12; 10874 10875 for (i = 0; i < max_realloc_count; i++) { 10876 reallocation_count = i; 10877 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10878 != XML_STATUS_ERROR) 10879 break; 10880 /* See comment in test_nsalloc_xmlns() */ 10881 nsalloc_teardown(); 10882 nsalloc_setup(); 10883 } 10884 if (i == 0) 10885 fail("Parsing worked despite failing reallocations"); 10886 else if (i == max_realloc_count) 10887 fail("Parsing failed even at max reallocation count"); 10888 } 10889 END_TEST 10890 10891 START_TEST(test_nsalloc_long_namespace) { 10892 const char *text1 10893 = "<" 10894 /* 64 characters per line */ 10895 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10896 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10897 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10898 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10899 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10900 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10901 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10902 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10903 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10904 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10905 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10906 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10907 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10908 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10909 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10910 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10911 ":e xmlns:" 10912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10913 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10923 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10924 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10925 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10926 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10927 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10928 "='http://example.org/'>\n"; 10929 const char *text2 10930 = "<" 10931 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10932 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10933 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10934 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10935 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10936 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10937 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10938 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10939 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10940 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10941 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10942 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10943 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10944 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10945 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10946 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10947 ":f " 10948 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10949 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10950 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10951 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10952 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10953 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10954 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10955 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10956 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10957 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10958 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10959 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10960 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10961 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10962 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10963 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10964 ":attr='foo'/>\n" 10965 "</" 10966 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10967 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10968 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10969 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10970 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10971 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10972 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10973 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10974 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10975 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10976 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10977 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10978 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10979 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10980 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10981 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10982 ":e>"; 10983 int i; 10984 const int max_alloc_count = 40; 10985 10986 for (i = 0; i < max_alloc_count; i++) { 10987 allocation_count = i; 10988 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 10989 != XML_STATUS_ERROR 10990 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 10991 XML_TRUE) 10992 != XML_STATUS_ERROR) 10993 break; 10994 /* See comment in test_nsalloc_xmlns() */ 10995 nsalloc_teardown(); 10996 nsalloc_setup(); 10997 } 10998 if (i == 0) 10999 fail("Parsing worked despite failing allocations"); 11000 else if (i == max_alloc_count) 11001 fail("Parsing failed even at max allocation count"); 11002 } 11003 END_TEST 11004 11005 /* Using a slightly shorter namespace name provokes allocations in 11006 * slightly different places in the code. 11007 */ 11008 START_TEST(test_nsalloc_less_long_namespace) { 11009 const char *text 11010 = "<" 11011 /* 64 characters per line */ 11012 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11013 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11014 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11015 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11016 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11017 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11018 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11019 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 11020 ":e xmlns:" 11021 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11022 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11023 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11024 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11025 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11026 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11027 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11028 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 11029 "='http://example.org/'>\n" 11030 "<" 11031 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11032 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11033 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11034 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11035 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11036 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11037 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11038 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 11039 ":f " 11040 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11041 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11042 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11043 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11044 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11045 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11046 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11047 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 11048 ":att='foo'/>\n" 11049 "</" 11050 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11051 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11052 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11053 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11054 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11055 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11056 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 11057 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 11058 ":e>"; 11059 int i; 11060 const int max_alloc_count = 40; 11061 11062 for (i = 0; i < max_alloc_count; i++) { 11063 allocation_count = i; 11064 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11065 != XML_STATUS_ERROR) 11066 break; 11067 /* See comment in test_nsalloc_xmlns() */ 11068 nsalloc_teardown(); 11069 nsalloc_setup(); 11070 } 11071 if (i == 0) 11072 fail("Parsing worked despite failing allocations"); 11073 else if (i == max_alloc_count) 11074 fail("Parsing failed even at max allocation count"); 11075 } 11076 END_TEST 11077 11078 START_TEST(test_nsalloc_long_context) { 11079 const char *text 11080 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11081 " <!ATTLIST doc baz ID #REQUIRED>\n" 11082 " <!ENTITY en SYSTEM 'bar'>\n" 11083 "]>\n" 11084 "<doc xmlns='http://example.org/" 11085 /* 64 characters per line */ 11086 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11087 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11088 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11089 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11090 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11091 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11092 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11093 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11094 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11095 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11096 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11097 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11098 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11099 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11100 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11101 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 11102 "' baz='2'>\n" 11103 "&en;" 11104 "</doc>"; 11105 ExtOption options[] = { 11106 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 11107 int i; 11108 const int max_alloc_count = 70; 11109 11110 for (i = 0; i < max_alloc_count; i++) { 11111 allocation_count = i; 11112 XML_SetUserData(g_parser, options); 11113 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11114 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11115 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11116 != XML_STATUS_ERROR) 11117 break; 11118 11119 /* See comment in test_nsalloc_xmlns() */ 11120 nsalloc_teardown(); 11121 nsalloc_setup(); 11122 } 11123 if (i == 0) 11124 fail("Parsing worked despite failing allocations"); 11125 else if (i == max_alloc_count) 11126 fail("Parsing failed even at max allocation count"); 11127 } 11128 END_TEST 11129 11130 /* This function is void; it will throw a fail() on error, so if it 11131 * returns normally it must have succeeded. 11132 */ 11133 static void 11134 context_realloc_test(const char *text) { 11135 ExtOption options[] = { 11136 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 11137 int i; 11138 const int max_realloc_count = 6; 11139 11140 for (i = 0; i < max_realloc_count; i++) { 11141 reallocation_count = i; 11142 XML_SetUserData(g_parser, options); 11143 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11144 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11145 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11146 != XML_STATUS_ERROR) 11147 break; 11148 /* See comment in test_nsalloc_xmlns() */ 11149 nsalloc_teardown(); 11150 nsalloc_setup(); 11151 } 11152 if (i == 0) 11153 fail("Parsing worked despite failing reallocations"); 11154 else if (i == max_realloc_count) 11155 fail("Parsing failed even at max reallocation count"); 11156 } 11157 11158 START_TEST(test_nsalloc_realloc_long_context) { 11159 const char *text 11160 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11161 " <!ENTITY en SYSTEM 'bar'>\n" 11162 "]>\n" 11163 "<doc xmlns='http://example.org/" 11164 /* 64 characters per line */ 11165 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11166 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11167 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11168 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11169 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11170 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11171 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11172 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11173 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11174 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11175 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11176 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11177 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11178 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11179 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11180 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 11181 "'>\n" 11182 "&en;" 11183 "</doc>"; 11184 11185 context_realloc_test(text); 11186 } 11187 END_TEST 11188 11189 START_TEST(test_nsalloc_realloc_long_context_2) { 11190 const char *text 11191 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11192 " <!ENTITY en SYSTEM 'bar'>\n" 11193 "]>\n" 11194 "<doc xmlns='http://example.org/" 11195 /* 64 characters per line */ 11196 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11197 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11198 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11199 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11200 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11201 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11202 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11203 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11204 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11205 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11206 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11207 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11208 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11209 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11210 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11211 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK" 11212 "'>\n" 11213 "&en;" 11214 "</doc>"; 11215 11216 context_realloc_test(text); 11217 } 11218 END_TEST 11219 11220 START_TEST(test_nsalloc_realloc_long_context_3) { 11221 const char *text 11222 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11223 " <!ENTITY en SYSTEM 'bar'>\n" 11224 "]>\n" 11225 "<doc xmlns='http://example.org/" 11226 /* 64 characters per line */ 11227 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11228 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11229 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11230 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11231 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11232 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11233 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11234 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11235 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11236 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11237 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11238 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11239 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11240 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11241 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11242 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH" 11243 "'>\n" 11244 "&en;" 11245 "</doc>"; 11246 11247 context_realloc_test(text); 11248 } 11249 END_TEST 11250 11251 START_TEST(test_nsalloc_realloc_long_context_4) { 11252 const char *text 11253 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11254 " <!ENTITY en SYSTEM 'bar'>\n" 11255 "]>\n" 11256 "<doc xmlns='http://example.org/" 11257 /* 64 characters per line */ 11258 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11259 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11260 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11261 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11262 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11263 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11264 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11265 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11266 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11267 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11268 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11269 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11270 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11271 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11272 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11273 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO" 11274 "'>\n" 11275 "&en;" 11276 "</doc>"; 11277 11278 context_realloc_test(text); 11279 } 11280 END_TEST 11281 11282 START_TEST(test_nsalloc_realloc_long_context_5) { 11283 const char *text 11284 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11285 " <!ENTITY en SYSTEM 'bar'>\n" 11286 "]>\n" 11287 "<doc xmlns='http://example.org/" 11288 /* 64 characters per line */ 11289 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11290 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11291 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11292 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11293 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11294 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11295 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11296 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11297 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11298 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11299 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11300 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11301 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11302 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11303 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11304 "ABC" 11305 "'>\n" 11306 "&en;" 11307 "</doc>"; 11308 11309 context_realloc_test(text); 11310 } 11311 END_TEST 11312 11313 START_TEST(test_nsalloc_realloc_long_context_6) { 11314 const char *text 11315 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11316 " <!ENTITY en SYSTEM 'bar'>\n" 11317 "]>\n" 11318 "<doc xmlns='http://example.org/" 11319 /* 64 characters per line */ 11320 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11321 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11322 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11323 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11324 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11325 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11326 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11327 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11328 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11329 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11330 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11331 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11332 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11333 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11334 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 11335 "'>\n" 11336 "&en;" 11337 "</doc>"; 11338 11339 context_realloc_test(text); 11340 } 11341 END_TEST 11342 11343 START_TEST(test_nsalloc_realloc_long_context_7) { 11344 const char *text 11345 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11346 " <!ENTITY en SYSTEM 'bar'>\n" 11347 "]>\n" 11348 "<doc xmlns='http://example.org/" 11349 /* 64 characters per line */ 11350 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11351 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11352 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11353 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11354 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11355 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11356 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11357 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11358 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11359 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11360 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11361 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11362 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11363 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11364 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11365 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM" 11366 "'>\n" 11367 "&en;" 11368 "</doc>"; 11369 11370 context_realloc_test(text); 11371 } 11372 END_TEST 11373 11374 START_TEST(test_nsalloc_realloc_long_ge_name) { 11375 const char *text 11376 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11377 " <!ENTITY " 11378 /* 64 characters per line */ 11379 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11380 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11381 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11382 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11383 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11384 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11385 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11386 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11387 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11388 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11389 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11390 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11391 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11392 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11393 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11394 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11395 " SYSTEM 'bar'>\n" 11396 "]>\n" 11397 "<doc xmlns='http://example.org/baz'>\n" 11398 "&" 11399 /* 64 characters per line */ 11400 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11401 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11402 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11403 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11404 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11405 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11406 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11407 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11408 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11409 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11410 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11411 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11412 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11413 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11414 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11415 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11416 ";" 11417 "</doc>"; 11418 ExtOption options[] = { 11419 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}}; 11420 int i; 11421 const int max_realloc_count = 10; 11422 11423 for (i = 0; i < max_realloc_count; i++) { 11424 reallocation_count = i; 11425 XML_SetUserData(g_parser, options); 11426 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11427 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11428 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11429 != XML_STATUS_ERROR) 11430 break; 11431 /* See comment in test_nsalloc_xmlns() */ 11432 nsalloc_teardown(); 11433 nsalloc_setup(); 11434 } 11435 if (i == 0) 11436 fail("Parsing worked despite failing reallocations"); 11437 else if (i == max_realloc_count) 11438 fail("Parsing failed even at max reallocation count"); 11439 } 11440 END_TEST 11441 11442 /* Test that when a namespace is passed through the context mechanism 11443 * to an external entity parser, the parsers handle reallocation 11444 * failures correctly. The prefix is exactly the right length to 11445 * provoke particular uncommon code paths. 11446 */ 11447 START_TEST(test_nsalloc_realloc_long_context_in_dtd) { 11448 const char *text1 11449 = "<!DOCTYPE " 11450 /* 64 characters per line */ 11451 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11452 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11453 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11454 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11455 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11456 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11457 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11458 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11459 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11460 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11461 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11462 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11463 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11464 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11465 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11466 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11467 ":doc [\n" 11468 " <!ENTITY First SYSTEM 'foo/First'>\n" 11469 "]>\n" 11470 "<" 11471 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11472 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11473 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11474 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11475 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11476 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11477 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11478 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11479 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11480 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11481 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11482 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11483 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11484 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11485 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11486 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11487 ":doc xmlns:" 11488 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11489 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11490 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11491 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11492 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11493 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11494 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11495 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11496 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11497 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11498 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11499 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11500 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11501 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11502 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11503 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11504 "='foo/Second'>&First;"; 11505 const char *text2 11506 = "</" 11507 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11508 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11509 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11510 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11511 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11512 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11513 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11514 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11515 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11516 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11517 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11518 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11519 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11520 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11521 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11522 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11523 ":doc>"; 11524 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}}; 11525 int i; 11526 const int max_realloc_count = 20; 11527 11528 for (i = 0; i < max_realloc_count; i++) { 11529 reallocation_count = i; 11530 XML_SetUserData(g_parser, options); 11531 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11532 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11533 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 11534 != XML_STATUS_ERROR 11535 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 11536 XML_TRUE) 11537 != XML_STATUS_ERROR) 11538 break; 11539 /* See comment in test_nsalloc_xmlns() */ 11540 nsalloc_teardown(); 11541 nsalloc_setup(); 11542 } 11543 if (i == 0) 11544 fail("Parsing worked despite failing reallocations"); 11545 else if (i == max_realloc_count) 11546 fail("Parsing failed even at max reallocation count"); 11547 } 11548 END_TEST 11549 11550 START_TEST(test_nsalloc_long_default_in_ext) { 11551 const char *text 11552 = "<!DOCTYPE doc [\n" 11553 " <!ATTLIST e a1 CDATA '" 11554 /* 64 characters per line */ 11555 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11556 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11557 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11558 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11559 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11560 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11561 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11562 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11563 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11564 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11565 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11566 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11567 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11568 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11569 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11570 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11571 "'>\n" 11572 " <!ENTITY x SYSTEM 'foo'>\n" 11573 "]>\n" 11574 "<doc>&x;</doc>"; 11575 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}}; 11576 int i; 11577 const int max_alloc_count = 50; 11578 11579 for (i = 0; i < max_alloc_count; i++) { 11580 allocation_count = i; 11581 XML_SetUserData(g_parser, options); 11582 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11583 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11584 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11585 != XML_STATUS_ERROR) 11586 break; 11587 11588 /* See comment in test_nsalloc_xmlns() */ 11589 nsalloc_teardown(); 11590 nsalloc_setup(); 11591 } 11592 if (i == 0) 11593 fail("Parsing worked despite failing allocations"); 11594 else if (i == max_alloc_count) 11595 fail("Parsing failed even at max allocation count"); 11596 } 11597 END_TEST 11598 11599 START_TEST(test_nsalloc_long_systemid_in_ext) { 11600 const char *text 11601 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11602 " <!ENTITY en SYSTEM '" 11603 /* 64 characters per line */ 11604 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11605 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11606 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11607 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11608 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11609 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11610 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11611 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11612 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11613 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11614 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11615 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11616 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11617 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11618 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11619 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11620 "'>\n" 11621 "]>\n" 11622 "<doc>&en;</doc>"; 11623 ExtOption options[] = { 11624 {XCS("foo"), "<!ELEMENT e EMPTY>"}, 11625 {/* clang-format off */ 11626 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11627 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11628 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11629 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11630 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11631 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11632 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11633 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11634 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11635 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11636 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11637 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11638 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11639 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11640 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11641 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"), 11642 /* clang-format on */ 11643 "<e/>"}, 11644 {NULL, NULL}}; 11645 int i; 11646 const int max_alloc_count = 55; 11647 11648 for (i = 0; i < max_alloc_count; i++) { 11649 allocation_count = i; 11650 XML_SetUserData(g_parser, options); 11651 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11652 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11653 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11654 != XML_STATUS_ERROR) 11655 break; 11656 11657 /* See comment in test_nsalloc_xmlns() */ 11658 nsalloc_teardown(); 11659 nsalloc_setup(); 11660 } 11661 if (i == 0) 11662 fail("Parsing worked despite failing allocations"); 11663 else if (i == max_alloc_count) 11664 fail("Parsing failed even at max allocation count"); 11665 } 11666 END_TEST 11667 11668 /* Test the effects of allocation failure on parsing an element in a 11669 * namespace. Based on test_nsalloc_long_context. 11670 */ 11671 START_TEST(test_nsalloc_prefixed_element) { 11672 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n" 11673 " <!ATTLIST pfx:element baz ID #REQUIRED>\n" 11674 " <!ENTITY en SYSTEM 'bar'>\n" 11675 "]>\n" 11676 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n" 11677 "&en;" 11678 "</pfx:element>"; 11679 ExtOption options[] = { 11680 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 11681 int i; 11682 const int max_alloc_count = 70; 11683 11684 for (i = 0; i < max_alloc_count; i++) { 11685 allocation_count = i; 11686 XML_SetUserData(g_parser, options); 11687 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11688 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11689 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11690 != XML_STATUS_ERROR) 11691 break; 11692 11693 /* See comment in test_nsalloc_xmlns() */ 11694 nsalloc_teardown(); 11695 nsalloc_setup(); 11696 } 11697 if (i == 0) 11698 fail("Success despite failing allocator"); 11699 else if (i == max_alloc_count) 11700 fail("Failed even at full allocation count"); 11701 } 11702 END_TEST 11703 11704 #if defined(XML_DTD) 11705 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int); 11706 11707 struct AccountingTestCase { 11708 const char *primaryText; 11709 const char *firstExternalText; /* often NULL */ 11710 const char *secondExternalText; /* often NULL */ 11711 const unsigned long long expectedCountBytesIndirectExtra; 11712 XML_Bool singleBytesWanted; 11713 }; 11714 11715 static int 11716 accounting_external_entity_ref_handler(XML_Parser parser, 11717 const XML_Char *context, 11718 const XML_Char *base, 11719 const XML_Char *systemId, 11720 const XML_Char *publicId) { 11721 UNUSED_P(context); 11722 UNUSED_P(base); 11723 UNUSED_P(publicId); 11724 11725 const struct AccountingTestCase *const testCase 11726 = (const struct AccountingTestCase *)XML_GetUserData(parser); 11727 11728 const char *externalText = NULL; 11729 if (xcstrcmp(systemId, XCS("first.ent")) == 0) { 11730 externalText = testCase->firstExternalText; 11731 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) { 11732 externalText = testCase->secondExternalText; 11733 } else { 11734 assert(! "systemId is neither \"first.ent\" nor \"second.ent\""); 11735 } 11736 assert(externalText); 11737 11738 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 11739 assert(entParser); 11740 11741 const XmlParseFunction xmlParseFunction 11742 = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11743 11744 const enum XML_Status status = xmlParseFunction( 11745 entParser, externalText, (int)strlen(externalText), XML_TRUE); 11746 11747 XML_ParserFree(entParser); 11748 return status; 11749 } 11750 11751 START_TEST(test_accounting_precision) { 11752 const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */ 11753 struct AccountingTestCase cases[] = { 11754 {"<e/>", NULL, NULL, 0, 0}, 11755 {"<e></e>", NULL, NULL, 0, 0}, 11756 11757 /* Attributes */ 11758 {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later}, 11759 {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0}, 11760 {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0, 11761 filled_later}, 11762 {"<e k=\"&'><"\" />", NULL, NULL, 11763 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11764 {"<e1 xmlns='https://example.org/'>\n" 11765 " <e2 xmlns=''/>\n" 11766 "</e1>", 11767 NULL, NULL, 0, filled_later}, 11768 11769 /* Text */ 11770 {"<e>text</e>", NULL, NULL, 0, filled_later}, 11771 {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later}, 11772 {"<e>&'><"</e>", NULL, NULL, 11773 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11774 {"<e>A)</e>", NULL, NULL, 0, filled_later}, 11775 11776 /* Prolog */ 11777 {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later}, 11778 11779 /* Whitespace */ 11780 {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later}, 11781 {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later}, 11782 {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later}, 11783 11784 /* Comments */ 11785 {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later}, 11786 11787 /* Processing instructions */ 11788 {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>", 11789 NULL, NULL, 0, filled_later}, 11790 {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>", 11791 "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>", 11792 0, filled_later}, 11793 11794 /* CDATA */ 11795 {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later}, 11796 /* The following is the essence of this OSS-Fuzz finding: 11797 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302 11798 https://oss-fuzz.com/testcase-detail/4860575394955264 11799 */ 11800 {"<!DOCTYPE r [\n" 11801 "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n" 11802 "]>\n" 11803 "<r>&e;</r>\n", 11804 NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"), 11805 filled_later}, 11806 11807 /* Conditional sections */ 11808 {"<!DOCTYPE r [\n" 11809 "<!ENTITY % draft 'INCLUDE'>\n" 11810 "<!ENTITY % final 'IGNORE'>\n" 11811 "<!ENTITY % import SYSTEM \"first.ent\">\n" 11812 "%import;\n" 11813 "]>\n" 11814 "<r/>\n", 11815 "<![%draft;[<!--1-->]]>\n" 11816 "<![%final;[<!--22-->]]>", 11817 NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")), 11818 filled_later}, 11819 11820 /* General entities */ 11821 {"<!DOCTYPE root [\n" 11822 "<!ENTITY nine \"123456789\">\n" 11823 "]>\n" 11824 "<root>&nine;</root>", 11825 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11826 {"<!DOCTYPE root [\n" 11827 "<!ENTITY nine \"123456789\">\n" 11828 "]>\n" 11829 "<root k1=\"&nine;\"/>", 11830 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11831 {"<!DOCTYPE root [\n" 11832 "<!ENTITY nine \"123456789\">\n" 11833 "<!ENTITY nine2 \"&nine;&nine;\">\n" 11834 "]>\n" 11835 "<root>&nine2;&nine2;&nine2;</root>", 11836 NULL, NULL, 11837 sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */ 11838 * (strlen("&nine;") + strlen("123456789")), 11839 filled_later}, 11840 {"<!DOCTYPE r [\n" 11841 " <!ENTITY five SYSTEM 'first.ent'>\n" 11842 "]>\n" 11843 "<r>&five;</r>", 11844 "12345", NULL, 0, filled_later}, 11845 11846 /* Parameter entities */ 11847 {"<!DOCTYPE r [\n" 11848 "<!ENTITY % comment \"<!---->\">\n" 11849 "%comment;\n" 11850 "]>\n" 11851 "<r/>", 11852 NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later}, 11853 {"<!DOCTYPE r [\n" 11854 "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n" 11855 "%ninedef;\n" 11856 "]>\n" 11857 "<r>&nine;</r>", 11858 NULL, NULL, 11859 sizeof(XML_Char) 11860 * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")), 11861 filled_later}, 11862 {"<!DOCTYPE r [\n" 11863 "<!ENTITY % comment \"<!--1-->\">\n" 11864 "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n" 11865 "%comment2;\n" 11866 "]>\n" 11867 "<r/>\n", 11868 NULL, NULL, 11869 sizeof(XML_Char) 11870 * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")), 11871 filled_later}, 11872 {"<!DOCTYPE r [\n" 11873 " <!ENTITY % five \"12345\">\n" 11874 " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n" 11875 " %five2def;\n" 11876 "]>\n" 11877 "<r>&five2;</r>", 11878 NULL, NULL, /* from "%five2def;": */ 11879 sizeof(XML_Char) 11880 * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">") 11881 + 2 /* calls to "%five;" */ * strlen("12345") 11882 + /* from "&five2;": */ strlen("[12345][12345]]]]")), 11883 filled_later}, 11884 {"<!DOCTYPE r SYSTEM \"first.ent\">\n" 11885 "<r/>", 11886 "<!ENTITY % comment '<!--1-->'>\n" 11887 "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n" 11888 "%comment2;", 11889 NULL, 11890 sizeof(XML_Char) 11891 * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->") 11892 + 2 /* calls to "%comment;" */ * strlen("<!---->")), 11893 filled_later}, 11894 {"<!DOCTYPE r SYSTEM 'first.ent'>\n" 11895 "<r/>", 11896 "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n" 11897 "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n" 11898 "%e2;\n", 11899 "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"), 11900 filled_later}, 11901 { 11902 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11903 "<r/>", 11904 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11905 "<!ENTITY % e2 '%e1;'>", 11906 "<?xml version='1.0' encoding='utf-8'?>\n" 11907 "hello\n" 11908 "xml" /* without trailing newline! */, 11909 0, 11910 filled_later, 11911 }, 11912 { 11913 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11914 "<r/>", 11915 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11916 "<!ENTITY % e2 '%e1;'>", 11917 "<?xml version='1.0' encoding='utf-8'?>\n" 11918 "hello\n" 11919 "xml\n" /* with trailing newline! */, 11920 0, 11921 filled_later, 11922 }, 11923 {"<!DOCTYPE doc SYSTEM 'first.ent'>\n" 11924 "<doc></doc>\n", 11925 "<!ELEMENT doc EMPTY>\n" 11926 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11927 "<!ENTITY % e2 '%e1;'>\n" 11928 "%e1;\n", 11929 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */, 11930 strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later}, 11931 {"<!DOCTYPE r [\n" 11932 " <!ENTITY five SYSTEM 'first.ent'>\n" 11933 "]>\n" 11934 "<r>&five;</r>", 11935 "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later}, 11936 }; 11937 11938 const size_t countCases = sizeof(cases) / sizeof(cases[0]); 11939 size_t u = 0; 11940 for (; u < countCases; u++) { 11941 size_t v = 0; 11942 for (; v < 2; v++) { 11943 const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE; 11944 const unsigned long long expectedCountBytesDirect 11945 = strlen(cases[u].primaryText); 11946 const unsigned long long expectedCountBytesIndirect 11947 = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText) 11948 : 0) 11949 + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText) 11950 : 0) 11951 + cases[u].expectedCountBytesIndirectExtra; 11952 11953 XML_Parser parser = XML_ParserCreate(NULL); 11954 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11955 if (cases[u].firstExternalText) { 11956 XML_SetExternalEntityRefHandler(parser, 11957 accounting_external_entity_ref_handler); 11958 XML_SetUserData(parser, (void *)&cases[u]); 11959 cases[u].singleBytesWanted = singleBytesWanted; 11960 } 11961 11962 const XmlParseFunction xmlParseFunction 11963 = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11964 11965 enum XML_Status status 11966 = xmlParseFunction(parser, cases[u].primaryText, 11967 (int)strlen(cases[u].primaryText), XML_TRUE); 11968 if (status != XML_STATUS_OK) { 11969 _xml_failure(parser, __FILE__, __LINE__); 11970 } 11971 11972 const unsigned long long actualCountBytesDirect 11973 = testingAccountingGetCountBytesDirect(parser); 11974 const unsigned long long actualCountBytesIndirect 11975 = testingAccountingGetCountBytesIndirect(parser); 11976 11977 XML_ParserFree(parser); 11978 11979 if (actualCountBytesDirect != expectedCountBytesDirect) { 11980 fprintf( 11981 stderr, 11982 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11983 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11984 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11985 expectedCountBytesDirect, actualCountBytesDirect); 11986 fail("Count of direct bytes is off"); 11987 } 11988 11989 if (actualCountBytesIndirect != expectedCountBytesIndirect) { 11990 fprintf( 11991 stderr, 11992 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11993 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11994 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11995 expectedCountBytesIndirect, actualCountBytesIndirect); 11996 fail("Count of indirect bytes is off"); 11997 } 11998 } 11999 } 12000 } 12001 END_TEST 12002 12003 static float 12004 portableNAN(void) { 12005 return strtof("nan", NULL); 12006 } 12007 12008 static float 12009 portableINFINITY(void) { 12010 return strtof("infinity", NULL); 12011 } 12012 12013 START_TEST(test_billion_laughs_attack_protection_api) { 12014 XML_Parser parserWithoutParent = XML_ParserCreate(NULL); 12015 XML_Parser parserWithParent 12016 = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL); 12017 if (parserWithoutParent == NULL) 12018 fail("parserWithoutParent is NULL"); 12019 if (parserWithParent == NULL) 12020 fail("parserWithParent is NULL"); 12021 12022 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases 12023 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f) 12024 == XML_TRUE) 12025 fail("Call with NULL parser is NOT supposed to succeed"); 12026 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent, 12027 123.0f) 12028 == XML_TRUE) 12029 fail("Call with non-root parser is NOT supposed to succeed"); 12030 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 12031 parserWithoutParent, portableNAN()) 12032 == XML_TRUE) 12033 fail("Call with NaN limit is NOT supposed to succeed"); 12034 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 12035 parserWithoutParent, -1.0f) 12036 == XML_TRUE) 12037 fail("Call with negative limit is NOT supposed to succeed"); 12038 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 12039 parserWithoutParent, 0.9f) 12040 == XML_TRUE) 12041 fail("Call with positive limit <1.0 is NOT supposed to succeed"); 12042 12043 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases 12044 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 12045 parserWithoutParent, 1.0f) 12046 == XML_FALSE) 12047 fail("Call with positive limit >=1.0 is supposed to succeed"); 12048 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 12049 parserWithoutParent, 123456.789f) 12050 == XML_FALSE) 12051 fail("Call with positive limit >=1.0 is supposed to succeed"); 12052 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 12053 parserWithoutParent, portableINFINITY()) 12054 == XML_FALSE) 12055 fail("Call with positive limit >=1.0 is supposed to succeed"); 12056 12057 // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases 12058 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123) 12059 == XML_TRUE) 12060 fail("Call with NULL parser is NOT supposed to succeed"); 12061 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent, 12062 123) 12063 == XML_TRUE) 12064 fail("Call with non-root parser is NOT supposed to succeed"); 12065 12066 // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases 12067 if (XML_SetBillionLaughsAttackProtectionActivationThreshold( 12068 parserWithoutParent, 123) 12069 == XML_FALSE) 12070 fail("Call with non-NULL parentless parser is supposed to succeed"); 12071 12072 XML_ParserFree(parserWithParent); 12073 XML_ParserFree(parserWithoutParent); 12074 } 12075 END_TEST 12076 12077 START_TEST(test_helper_unsigned_char_to_printable) { 12078 // Smoke test 12079 unsigned char uc = 0; 12080 for (; uc < (unsigned char)-1; uc++) { 12081 const char *const printable = unsignedCharToPrintable(uc); 12082 if (printable == NULL) 12083 fail("unsignedCharToPrintable returned NULL"); 12084 if (strlen(printable) < (size_t)1) 12085 fail("unsignedCharToPrintable returned empty string"); 12086 } 12087 12088 // Two concrete samples 12089 if (strcmp(unsignedCharToPrintable('A'), "A") != 0) 12090 fail("unsignedCharToPrintable result mistaken"); 12091 if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0) 12092 fail("unsignedCharToPrintable result mistaken"); 12093 } 12094 END_TEST 12095 #endif // defined(XML_DTD) 12096 12097 static Suite * 12098 make_suite(void) { 12099 Suite *s = suite_create("basic"); 12100 TCase *tc_basic = tcase_create("basic tests"); 12101 TCase *tc_namespace = tcase_create("XML namespaces"); 12102 TCase *tc_misc = tcase_create("miscellaneous tests"); 12103 TCase *tc_alloc = tcase_create("allocation tests"); 12104 TCase *tc_nsalloc = tcase_create("namespace allocation tests"); 12105 #if defined(XML_DTD) 12106 TCase *tc_accounting = tcase_create("accounting tests"); 12107 #endif 12108 12109 suite_add_tcase(s, tc_basic); 12110 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown); 12111 tcase_add_test(tc_basic, test_nul_byte); 12112 tcase_add_test(tc_basic, test_u0000_char); 12113 tcase_add_test(tc_basic, test_siphash_self); 12114 tcase_add_test(tc_basic, test_siphash_spec); 12115 tcase_add_test(tc_basic, test_bom_utf8); 12116 tcase_add_test(tc_basic, test_bom_utf16_be); 12117 tcase_add_test(tc_basic, test_bom_utf16_le); 12118 tcase_add_test(tc_basic, test_nobom_utf16_le); 12119 tcase_add_test(tc_basic, test_illegal_utf8); 12120 tcase_add_test(tc_basic, test_utf8_auto_align); 12121 tcase_add_test(tc_basic, test_utf16); 12122 tcase_add_test(tc_basic, test_utf16_le_epilog_newline); 12123 tcase_add_test(tc_basic, test_not_utf16); 12124 tcase_add_test(tc_basic, test_bad_encoding); 12125 tcase_add_test(tc_basic, test_latin1_umlauts); 12126 tcase_add_test(tc_basic, test_long_utf8_character); 12127 tcase_add_test(tc_basic, test_long_latin1_attribute); 12128 tcase_add_test(tc_basic, test_long_ascii_attribute); 12129 /* Regression test for SF bug #491986. */ 12130 tcase_add_test(tc_basic, test_danish_latin1); 12131 /* Regression test for SF bug #514281. */ 12132 tcase_add_test(tc_basic, test_french_charref_hexidecimal); 12133 tcase_add_test(tc_basic, test_french_charref_decimal); 12134 tcase_add_test(tc_basic, test_french_latin1); 12135 tcase_add_test(tc_basic, test_french_utf8); 12136 tcase_add_test(tc_basic, test_utf8_false_rejection); 12137 tcase_add_test(tc_basic, test_line_number_after_parse); 12138 tcase_add_test(tc_basic, test_column_number_after_parse); 12139 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers); 12140 tcase_add_test(tc_basic, test_line_number_after_error); 12141 tcase_add_test(tc_basic, test_column_number_after_error); 12142 tcase_add_test(tc_basic, test_really_long_lines); 12143 tcase_add_test(tc_basic, test_really_long_encoded_lines); 12144 tcase_add_test(tc_basic, test_end_element_events); 12145 tcase_add_test(tc_basic, test_attr_whitespace_normalization); 12146 tcase_add_test(tc_basic, test_xmldecl_misplaced); 12147 tcase_add_test(tc_basic, test_xmldecl_invalid); 12148 tcase_add_test(tc_basic, test_xmldecl_missing_attr); 12149 tcase_add_test(tc_basic, test_xmldecl_missing_value); 12150 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity); 12151 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity); 12152 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset); 12153 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset); 12154 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone); 12155 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset); 12156 tcase_add_test(tc_basic, test_not_standalone_handler_reject); 12157 tcase_add_test(tc_basic, test_not_standalone_handler_accept); 12158 tcase_add_test(tc_basic, 12159 test_wfc_undeclared_entity_with_external_subset_standalone); 12160 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone); 12161 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs); 12162 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding); 12163 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler); 12164 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom); 12165 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding); 12166 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2); 12167 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse); 12168 tcase_add_test__ifdef_xml_dtd(tc_basic, 12169 test_ext_entity_invalid_suspended_parse); 12170 tcase_add_test(tc_basic, test_dtd_default_handling); 12171 tcase_add_test(tc_basic, test_dtd_attr_handling); 12172 tcase_add_test(tc_basic, test_empty_ns_without_namespaces); 12173 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces); 12174 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls); 12175 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls); 12176 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls); 12177 tcase_add_test(tc_basic, test_good_cdata_ascii); 12178 tcase_add_test(tc_basic, test_good_cdata_utf16); 12179 tcase_add_test(tc_basic, test_good_cdata_utf16_le); 12180 tcase_add_test(tc_basic, test_long_cdata_utf16); 12181 tcase_add_test(tc_basic, test_multichar_cdata_utf16); 12182 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair); 12183 tcase_add_test(tc_basic, test_bad_cdata); 12184 tcase_add_test(tc_basic, test_bad_cdata_utf16); 12185 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls); 12186 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls); 12187 tcase_add_test(tc_basic, test_memory_allocation); 12188 tcase_add_test(tc_basic, test_default_current); 12189 tcase_add_test(tc_basic, test_dtd_elements); 12190 tcase_add_test(tc_basic, test_dtd_elements_nesting); 12191 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd); 12192 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone); 12193 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd); 12194 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype); 12195 tcase_add_test__ifdef_xml_dtd(tc_basic, 12196 test_foreign_dtd_without_external_subset); 12197 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd); 12198 tcase_add_test(tc_basic, test_set_base); 12199 tcase_add_test(tc_basic, test_attributes); 12200 tcase_add_test(tc_basic, test_reset_in_entity); 12201 tcase_add_test(tc_basic, test_resume_invalid_parse); 12202 tcase_add_test(tc_basic, test_resume_resuspended); 12203 tcase_add_test(tc_basic, test_cdata_default); 12204 tcase_add_test(tc_basic, test_subordinate_reset); 12205 tcase_add_test(tc_basic, test_subordinate_suspend); 12206 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend); 12207 tcase_add_test(tc_basic, test_subordinate_xdecl_abort); 12208 tcase_add_test(tc_basic, test_explicit_encoding); 12209 tcase_add_test(tc_basic, test_trailing_cr); 12210 tcase_add_test(tc_basic, test_ext_entity_trailing_cr); 12211 tcase_add_test(tc_basic, test_trailing_rsqb); 12212 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb); 12213 tcase_add_test(tc_basic, test_ext_entity_good_cdata); 12214 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters); 12215 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter); 12216 tcase_add_test(tc_basic, test_empty_parse); 12217 tcase_add_test(tc_basic, test_get_buffer_1); 12218 tcase_add_test(tc_basic, test_get_buffer_2); 12219 #if defined(XML_CONTEXT_BYTES) 12220 tcase_add_test(tc_basic, test_get_buffer_3_overflow); 12221 #endif 12222 tcase_add_test(tc_basic, test_byte_info_at_end); 12223 tcase_add_test(tc_basic, test_byte_info_at_error); 12224 tcase_add_test(tc_basic, test_byte_info_at_cdata); 12225 tcase_add_test(tc_basic, test_predefined_entities); 12226 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd); 12227 tcase_add_test(tc_basic, test_not_predefined_entities); 12228 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section); 12229 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16); 12230 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be); 12231 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section); 12232 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values); 12233 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone); 12234 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort); 12235 tcase_add_test(tc_basic, test_bad_public_doctype); 12236 tcase_add_test(tc_basic, test_attribute_enum_value); 12237 tcase_add_test(tc_basic, test_predefined_entity_redefinition); 12238 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing); 12239 tcase_add_test(tc_basic, test_public_notation_no_sysid); 12240 tcase_add_test(tc_basic, test_nested_groups); 12241 tcase_add_test(tc_basic, test_group_choice); 12242 tcase_add_test(tc_basic, test_standalone_parameter_entity); 12243 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity); 12244 tcase_add_test__ifdef_xml_dtd(tc_basic, 12245 test_recursive_external_parameter_entity); 12246 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd); 12247 tcase_add_test(tc_basic, test_suspend_xdecl); 12248 tcase_add_test(tc_basic, test_abort_epilog); 12249 tcase_add_test(tc_basic, test_abort_epilog_2); 12250 tcase_add_test(tc_basic, test_suspend_epilog); 12251 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag); 12252 tcase_add_test(tc_basic, test_unfinished_epilog); 12253 tcase_add_test(tc_basic, test_partial_char_in_epilog); 12254 tcase_add_test(tc_basic, test_hash_collision); 12255 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity); 12256 tcase_add_test__ifdef_xml_dtd(tc_basic, 12257 test_suspend_resume_internal_entity_issue_629); 12258 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error); 12259 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity); 12260 tcase_add_test(tc_basic, test_restart_on_error); 12261 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value); 12262 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value); 12263 tcase_add_test(tc_basic, test_trailing_cr_in_att_value); 12264 tcase_add_test(tc_basic, test_standalone_internal_entity); 12265 tcase_add_test(tc_basic, test_skipped_external_entity); 12266 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity); 12267 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity); 12268 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr); 12269 tcase_add_test(tc_basic, test_invalid_character_entity); 12270 tcase_add_test(tc_basic, test_invalid_character_entity_2); 12271 tcase_add_test(tc_basic, test_invalid_character_entity_3); 12272 tcase_add_test(tc_basic, test_invalid_character_entity_4); 12273 tcase_add_test(tc_basic, test_pi_handled_in_default); 12274 tcase_add_test(tc_basic, test_comment_handled_in_default); 12275 tcase_add_test(tc_basic, test_pi_yml); 12276 tcase_add_test(tc_basic, test_pi_xnl); 12277 tcase_add_test(tc_basic, test_pi_xmm); 12278 tcase_add_test(tc_basic, test_utf16_pi); 12279 tcase_add_test(tc_basic, test_utf16_be_pi); 12280 tcase_add_test(tc_basic, test_utf16_be_comment); 12281 tcase_add_test(tc_basic, test_utf16_le_comment); 12282 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn); 12283 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn); 12284 tcase_add_test(tc_basic, test_unknown_encoding_success); 12285 tcase_add_test(tc_basic, test_unknown_encoding_bad_name); 12286 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2); 12287 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1); 12288 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2); 12289 tcase_add_test(tc_basic, test_invalid_unknown_encoding); 12290 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok); 12291 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail); 12292 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length); 12293 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit); 12294 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate); 12295 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high); 12296 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value); 12297 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom); 12298 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom); 12299 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2); 12300 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2); 12301 tcase_add_test(tc_basic, test_ext_entity_utf16_be); 12302 tcase_add_test(tc_basic, test_ext_entity_utf16_le); 12303 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown); 12304 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom); 12305 tcase_add_test(tc_basic, test_utf8_in_cdata_section); 12306 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2); 12307 tcase_add_test(tc_basic, test_utf8_in_start_tags); 12308 tcase_add_test(tc_basic, test_trailing_spaces_in_elements); 12309 tcase_add_test(tc_basic, test_utf16_attribute); 12310 tcase_add_test(tc_basic, test_utf16_second_attr); 12311 tcase_add_test(tc_basic, test_attr_after_solidus); 12312 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe); 12313 tcase_add_test(tc_basic, test_bad_attr_desc_keyword); 12314 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16); 12315 tcase_add_test(tc_basic, test_bad_doctype); 12316 tcase_add_test(tc_basic, test_bad_doctype_utf8); 12317 tcase_add_test(tc_basic, test_bad_doctype_utf16); 12318 tcase_add_test(tc_basic, test_bad_doctype_plus); 12319 tcase_add_test(tc_basic, test_bad_doctype_star); 12320 tcase_add_test(tc_basic, test_bad_doctype_query); 12321 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore); 12322 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr); 12323 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr); 12324 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be); 12325 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le); 12326 tcase_add_test(tc_basic, test_short_doctype); 12327 tcase_add_test(tc_basic, test_short_doctype_2); 12328 tcase_add_test(tc_basic, test_short_doctype_3); 12329 tcase_add_test(tc_basic, test_long_doctype); 12330 tcase_add_test(tc_basic, test_bad_entity); 12331 tcase_add_test(tc_basic, test_bad_entity_2); 12332 tcase_add_test(tc_basic, test_bad_entity_3); 12333 tcase_add_test(tc_basic, test_bad_entity_4); 12334 tcase_add_test(tc_basic, test_bad_notation); 12335 tcase_add_test(tc_basic, test_default_doctype_handler); 12336 tcase_add_test(tc_basic, test_empty_element_abort); 12337 tcase_add_test__ifdef_xml_dtd(tc_basic, 12338 test_pool_integrity_with_unfinished_attr); 12339 tcase_add_test(tc_basic, test_nested_entity_suspend); 12340 12341 suite_add_tcase(s, tc_namespace); 12342 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown); 12343 tcase_add_test(tc_namespace, test_return_ns_triplet); 12344 tcase_add_test(tc_namespace, test_ns_tagname_overwrite); 12345 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet); 12346 tcase_add_test(tc_namespace, test_start_ns_clears_start_element); 12347 tcase_add_test__ifdef_xml_dtd(tc_namespace, 12348 test_default_ns_from_ext_subset_and_ext_ge); 12349 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1); 12350 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2); 12351 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3); 12352 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4); 12353 tcase_add_test(tc_namespace, test_ns_unbound_prefix); 12354 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri); 12355 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes); 12356 tcase_add_test(tc_namespace, test_ns_duplicate_hashes); 12357 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute); 12358 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element); 12359 tcase_add_test(tc_namespace, test_ns_parser_reset); 12360 tcase_add_test(tc_namespace, test_ns_long_element); 12361 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts); 12362 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer); 12363 tcase_add_test(tc_namespace, test_ns_reserved_attributes); 12364 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2); 12365 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix); 12366 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success); 12367 tcase_add_test(tc_namespace, test_ns_double_colon); 12368 tcase_add_test(tc_namespace, test_ns_double_colon_element); 12369 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname); 12370 tcase_add_test(tc_namespace, test_ns_bad_element_leafname); 12371 tcase_add_test(tc_namespace, test_ns_utf16_leafname); 12372 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname); 12373 tcase_add_test(tc_namespace, test_ns_utf16_doctype); 12374 tcase_add_test(tc_namespace, test_ns_invalid_doctype); 12375 tcase_add_test(tc_namespace, test_ns_double_colon_doctype); 12376 tcase_add_test(tc_namespace, test_ns_separator_in_uri); 12377 12378 suite_add_tcase(s, tc_misc); 12379 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); 12380 tcase_add_test(tc_misc, test_misc_alloc_create_parser); 12381 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding); 12382 tcase_add_test(tc_misc, test_misc_null_parser); 12383 tcase_add_test(tc_misc, test_misc_error_string); 12384 tcase_add_test(tc_misc, test_misc_version); 12385 tcase_add_test(tc_misc, test_misc_features); 12386 tcase_add_test(tc_misc, test_misc_attribute_leak); 12387 tcase_add_test(tc_misc, test_misc_utf16le); 12388 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1); 12389 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2); 12390 tcase_add_test__ifdef_xml_dtd( 12391 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317); 12392 tcase_add_test(tc_misc, test_misc_tag_mismatch_reset_leak); 12393 12394 suite_add_tcase(s, tc_alloc); 12395 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); 12396 tcase_add_test(tc_alloc, test_alloc_parse_xdecl); 12397 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2); 12398 tcase_add_test(tc_alloc, test_alloc_parse_pi); 12399 tcase_add_test(tc_alloc, test_alloc_parse_pi_2); 12400 tcase_add_test(tc_alloc, test_alloc_parse_pi_3); 12401 tcase_add_test(tc_alloc, test_alloc_parse_comment); 12402 tcase_add_test(tc_alloc, test_alloc_parse_comment_2); 12403 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser); 12404 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser); 12405 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts); 12406 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity); 12407 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding); 12408 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity); 12409 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling); 12410 tcase_add_test(tc_alloc, test_alloc_explicit_encoding); 12411 tcase_add_test(tc_alloc, test_alloc_set_base); 12412 tcase_add_test(tc_alloc, test_alloc_realloc_buffer); 12413 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer); 12414 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes); 12415 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value); 12416 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12417 test_alloc_realloc_subst_public_entity_value); 12418 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype); 12419 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name); 12420 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd); 12421 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value); 12422 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12423 test_alloc_realloc_attribute_enum_value); 12424 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute); 12425 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute); 12426 tcase_add_test(tc_alloc, test_alloc_notation); 12427 tcase_add_test(tc_alloc, test_alloc_public_notation); 12428 tcase_add_test(tc_alloc, test_alloc_system_notation); 12429 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups); 12430 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups); 12431 tcase_add_test(tc_alloc, test_alloc_large_group); 12432 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice); 12433 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog); 12434 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog); 12435 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12436 test_alloc_realloc_long_attribute_value); 12437 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace); 12438 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity); 12439 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref); 12440 tcase_add_test(tc_alloc, test_alloc_long_attr_value); 12441 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities); 12442 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12443 test_alloc_realloc_param_entity_newline); 12444 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe); 12445 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes); 12446 tcase_add_test(tc_alloc, test_alloc_long_doc_name); 12447 tcase_add_test(tc_alloc, test_alloc_long_base); 12448 tcase_add_test(tc_alloc, test_alloc_long_public_id); 12449 tcase_add_test(tc_alloc, test_alloc_long_entity_value); 12450 tcase_add_test(tc_alloc, test_alloc_long_notation); 12451 tcase_add_test__ifdef_xml_dtd( 12452 tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail); 12453 12454 suite_add_tcase(s, tc_nsalloc); 12455 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown); 12456 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns); 12457 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer); 12458 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix); 12459 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri); 12460 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr); 12461 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix); 12462 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes); 12463 tcase_add_test(tc_nsalloc, test_nsalloc_long_element); 12464 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri); 12465 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix); 12466 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix); 12467 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace); 12468 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace); 12469 tcase_add_test(tc_nsalloc, test_nsalloc_long_context); 12470 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context); 12471 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2); 12472 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3); 12473 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4); 12474 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5); 12475 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6); 12476 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7); 12477 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name); 12478 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd); 12479 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext); 12480 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext); 12481 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element); 12482 12483 #if defined(XML_DTD) 12484 suite_add_tcase(s, tc_accounting); 12485 tcase_add_test(tc_accounting, test_accounting_precision); 12486 tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); 12487 tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); 12488 #endif 12489 12490 return s; 12491 } 12492 12493 int 12494 main(int argc, char *argv[]) { 12495 int i, nf; 12496 int verbosity = CK_NORMAL; 12497 Suite *s = make_suite(); 12498 SRunner *sr = srunner_create(s); 12499 12500 /* run the tests for internal helper functions */ 12501 testhelper_is_whitespace_normalized(); 12502 12503 for (i = 1; i < argc; ++i) { 12504 char *opt = argv[i]; 12505 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0) 12506 verbosity = CK_VERBOSE; 12507 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0) 12508 verbosity = CK_SILENT; 12509 else { 12510 fprintf(stderr, "runtests: unknown option '%s'\n", opt); 12511 return 2; 12512 } 12513 } 12514 if (verbosity != CK_SILENT) 12515 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion()); 12516 srunner_run_all(sr, verbosity); 12517 nf = srunner_ntests_failed(sr); 12518 srunner_free(sr); 12519 12520 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 12521 } 12522