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 <ssolie@users.sourceforge.net> 12 Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> 13 Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org> 14 Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk> 15 Copyright (c) 2017 Joe Orton <jorton@redhat.com> 16 Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> 17 Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it> 18 Copyright (c) 2019 David Loffredo <loffredo@steptools.com> 19 Copyright (c) 2020 Tim Gates <tim.gates@iress.com> 20 Copyright (c) 2021 Dong-hee Na <donghee.na@python.org> 21 Licensed under the MIT license: 22 23 Permission is hereby granted, free of charge, to any person obtaining 24 a copy of this software and associated documentation files (the 25 "Software"), to deal in the Software without restriction, including 26 without limitation the rights to use, copy, modify, merge, publish, 27 distribute, sublicense, and/or sell copies of the Software, and to permit 28 persons to whom the Software is furnished to do so, subject to the 29 following conditions: 30 31 The above copyright notice and this permission notice shall be included 32 in all copies or substantial portions of the Software. 33 34 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 35 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 36 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 37 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 38 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 39 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 40 USE OR OTHER DEALINGS IN THE SOFTWARE. 41 */ 42 43 #include <expat_config.h> 44 45 #if defined(NDEBUG) 46 # undef NDEBUG /* because test suite relies on assert(...) at the moment */ 47 #endif 48 49 #include <assert.h> 50 #include <stdlib.h> 51 #include <stdio.h> 52 #include <string.h> 53 #include <stddef.h> /* ptrdiff_t */ 54 #include <ctype.h> 55 #include <limits.h> 56 #include <stdint.h> /* intptr_t uint64_t */ 57 #include <math.h> /* NAN, INFINITY, isnan */ 58 59 #if ! defined(__cplusplus) 60 # include <stdbool.h> 61 #endif 62 63 #include "expat.h" 64 #include "chardata.h" 65 #include "structdata.h" 66 #include "internal.h" 67 #include "minicheck.h" 68 #include "memcheck.h" 69 #include "siphash.h" 70 #include "ascii.h" /* for ASCII_xxx */ 71 72 #ifdef XML_LARGE_SIZE 73 # define XML_FMT_INT_MOD "ll" 74 #else 75 # define XML_FMT_INT_MOD "l" 76 #endif 77 78 #ifdef XML_UNICODE_WCHAR_T 79 # define XML_FMT_CHAR "lc" 80 # define XML_FMT_STR "ls" 81 # include <wchar.h> 82 # define xcstrlen(s) wcslen(s) 83 # define xcstrcmp(s, t) wcscmp((s), (t)) 84 # define xcstrncmp(s, t, n) wcsncmp((s), (t), (n)) 85 # define XCS(s) _XCS(s) 86 # define _XCS(s) L##s 87 #else 88 # ifdef XML_UNICODE 89 # error "No support for UTF-16 character without wchar_t in tests" 90 # else 91 # define XML_FMT_CHAR "c" 92 # define XML_FMT_STR "s" 93 # define xcstrlen(s) strlen(s) 94 # define xcstrcmp(s, t) strcmp((s), (t)) 95 # define xcstrncmp(s, t, n) strncmp((s), (t), (n)) 96 # define XCS(s) s 97 # endif /* XML_UNICODE */ 98 #endif /* XML_UNICODE_WCHAR_T */ 99 100 static XML_Parser g_parser = NULL; 101 102 static void 103 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) { 104 #ifdef XML_DTD 105 tcase_add_test(tc, test); 106 #else 107 UNUSED_P(tc); 108 UNUSED_P(test); 109 #endif 110 } 111 112 static void 113 basic_setup(void) { 114 g_parser = XML_ParserCreate(NULL); 115 if (g_parser == NULL) 116 fail("Parser not created."); 117 } 118 119 static void 120 basic_teardown(void) { 121 if (g_parser != NULL) { 122 XML_ParserFree(g_parser); 123 g_parser = NULL; 124 } 125 } 126 127 /* Generate a failure using the parser state to create an error message; 128 this should be used when the parser reports an error we weren't 129 expecting. 130 */ 131 static void 132 _xml_failure(XML_Parser parser, const char *file, int line) { 133 char buffer[1024]; 134 enum XML_Error err = XML_GetErrorCode(parser); 135 sprintf(buffer, 136 " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD 137 "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n", 138 err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser), 139 XML_GetCurrentColumnNumber(parser), file, line); 140 _fail_unless(0, file, line, buffer); 141 } 142 143 static enum XML_Status 144 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len, 145 int isFinal) { 146 enum XML_Status res = XML_STATUS_ERROR; 147 int offset = 0; 148 149 if (len == 0) { 150 return XML_Parse(parser, s, len, isFinal); 151 } 152 153 for (; offset < len; offset++) { 154 const int innerIsFinal = (offset == len - 1) && isFinal; 155 const char c = s[offset]; /* to help out-of-bounds detection */ 156 res = XML_Parse(parser, &c, sizeof(char), innerIsFinal); 157 if (res != XML_STATUS_OK) { 158 return res; 159 } 160 } 161 return res; 162 } 163 164 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__) 165 166 static void 167 _expect_failure(const char *text, enum XML_Error errorCode, 168 const char *errorMessage, const char *file, int lineno) { 169 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 170 == XML_STATUS_OK) 171 /* Hackish use of _fail_unless() macro, but let's us report 172 the right filename and line number. */ 173 _fail_unless(0, file, lineno, errorMessage); 174 if (XML_GetErrorCode(g_parser) != errorCode) 175 _xml_failure(g_parser, file, lineno); 176 } 177 178 #define expect_failure(text, errorCode, errorMessage) \ 179 _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__) 180 181 /* Dummy handlers for when we need to set a handler to tickle a bug, 182 but it doesn't need to do anything. 183 */ 184 static unsigned long dummy_handler_flags = 0; 185 186 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0) 187 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1) 188 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2) 189 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3) 190 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4) 191 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5) 192 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6) 193 #define DUMMY_PI_HANDLER_FLAG (1UL << 7) 194 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8) 195 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9) 196 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10) 197 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11) 198 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12) 199 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13) 200 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14) 201 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15) 202 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16) 203 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17) 204 205 static void XMLCALL 206 dummy_xdecl_handler(void *userData, const XML_Char *version, 207 const XML_Char *encoding, int standalone) { 208 UNUSED_P(userData); 209 UNUSED_P(version); 210 UNUSED_P(encoding); 211 UNUSED_P(standalone); 212 } 213 214 static void XMLCALL 215 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName, 216 const XML_Char *sysid, const XML_Char *pubid, 217 int has_internal_subset) { 218 UNUSED_P(userData); 219 UNUSED_P(doctypeName); 220 UNUSED_P(sysid); 221 UNUSED_P(pubid); 222 UNUSED_P(has_internal_subset); 223 dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG; 224 } 225 226 static void XMLCALL 227 dummy_end_doctype_handler(void *userData) { 228 UNUSED_P(userData); 229 dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG; 230 } 231 232 static void XMLCALL 233 dummy_entity_decl_handler(void *userData, const XML_Char *entityName, 234 int is_parameter_entity, const XML_Char *value, 235 int value_length, const XML_Char *base, 236 const XML_Char *systemId, const XML_Char *publicId, 237 const XML_Char *notationName) { 238 UNUSED_P(userData); 239 UNUSED_P(entityName); 240 UNUSED_P(is_parameter_entity); 241 UNUSED_P(value); 242 UNUSED_P(value_length); 243 UNUSED_P(base); 244 UNUSED_P(systemId); 245 UNUSED_P(publicId); 246 UNUSED_P(notationName); 247 dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG; 248 } 249 250 static void XMLCALL 251 dummy_notation_decl_handler(void *userData, const XML_Char *notationName, 252 const XML_Char *base, const XML_Char *systemId, 253 const XML_Char *publicId) { 254 UNUSED_P(userData); 255 UNUSED_P(notationName); 256 UNUSED_P(base); 257 UNUSED_P(systemId); 258 UNUSED_P(publicId); 259 dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG; 260 } 261 262 static void XMLCALL 263 dummy_element_decl_handler(void *userData, const XML_Char *name, 264 XML_Content *model) { 265 UNUSED_P(userData); 266 UNUSED_P(name); 267 /* The content model must be freed by the handler. Unfortunately 268 * we cannot pass the parser as the userData because this is used 269 * with other handlers that require other userData. 270 */ 271 XML_FreeContentModel(g_parser, model); 272 dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG; 273 } 274 275 static void XMLCALL 276 dummy_attlist_decl_handler(void *userData, const XML_Char *elname, 277 const XML_Char *attname, const XML_Char *att_type, 278 const XML_Char *dflt, int isrequired) { 279 UNUSED_P(userData); 280 UNUSED_P(elname); 281 UNUSED_P(attname); 282 UNUSED_P(att_type); 283 UNUSED_P(dflt); 284 UNUSED_P(isrequired); 285 dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG; 286 } 287 288 static void XMLCALL 289 dummy_comment_handler(void *userData, const XML_Char *data) { 290 UNUSED_P(userData); 291 UNUSED_P(data); 292 dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG; 293 } 294 295 static void XMLCALL 296 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) { 297 UNUSED_P(userData); 298 UNUSED_P(target); 299 UNUSED_P(data); 300 dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG; 301 } 302 303 static void XMLCALL 304 dummy_start_element(void *userData, const XML_Char *name, 305 const XML_Char **atts) { 306 UNUSED_P(userData); 307 UNUSED_P(name); 308 UNUSED_P(atts); 309 dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG; 310 } 311 312 static void XMLCALL 313 dummy_end_element(void *userData, const XML_Char *name) { 314 UNUSED_P(userData); 315 UNUSED_P(name); 316 } 317 318 static void XMLCALL 319 dummy_start_cdata_handler(void *userData) { 320 UNUSED_P(userData); 321 dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG; 322 } 323 324 static void XMLCALL 325 dummy_end_cdata_handler(void *userData) { 326 UNUSED_P(userData); 327 dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG; 328 } 329 330 static void XMLCALL 331 dummy_cdata_handler(void *userData, const XML_Char *s, int len) { 332 UNUSED_P(userData); 333 UNUSED_P(s); 334 UNUSED_P(len); 335 } 336 337 static void XMLCALL 338 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix, 339 const XML_Char *uri) { 340 UNUSED_P(userData); 341 UNUSED_P(prefix); 342 UNUSED_P(uri); 343 dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG; 344 } 345 346 static void XMLCALL 347 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) { 348 UNUSED_P(userData); 349 UNUSED_P(prefix); 350 dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG; 351 } 352 353 /* This handler is obsolete, but while the code exists we should 354 * ensure that dealing with the handler is covered by tests. 355 */ 356 static void XMLCALL 357 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName, 358 const XML_Char *base, 359 const XML_Char *systemId, 360 const XML_Char *publicId, 361 const XML_Char *notationName) { 362 UNUSED_P(userData); 363 UNUSED_P(entityName); 364 UNUSED_P(base); 365 UNUSED_P(systemId); 366 UNUSED_P(publicId); 367 UNUSED_P(notationName); 368 dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG; 369 } 370 371 static void XMLCALL 372 dummy_default_handler(void *userData, const XML_Char *s, int len) { 373 UNUSED_P(userData); 374 UNUSED_P(s); 375 UNUSED_P(len); 376 } 377 378 static void XMLCALL 379 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName, 380 const XML_Char *sysid, const XML_Char *pubid, 381 int has_internal_subset) { 382 UNUSED_P(userData); 383 UNUSED_P(doctypeName); 384 UNUSED_P(sysid); 385 UNUSED_P(pubid); 386 UNUSED_P(has_internal_subset); 387 dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG; 388 } 389 390 static void XMLCALL 391 dummy_end_doctype_decl_handler(void *userData) { 392 UNUSED_P(userData); 393 dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG; 394 } 395 396 static void XMLCALL 397 dummy_skip_handler(void *userData, const XML_Char *entityName, 398 int is_parameter_entity) { 399 UNUSED_P(userData); 400 UNUSED_P(entityName); 401 UNUSED_P(is_parameter_entity); 402 dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG; 403 } 404 405 /* Useful external entity handler */ 406 typedef struct ExtOption { 407 const XML_Char *system_id; 408 const char *parse_text; 409 } ExtOption; 410 411 static int XMLCALL 412 external_entity_optioner(XML_Parser parser, const XML_Char *context, 413 const XML_Char *base, const XML_Char *systemId, 414 const XML_Char *publicId) { 415 ExtOption *options = (ExtOption *)XML_GetUserData(parser); 416 XML_Parser ext_parser; 417 418 UNUSED_P(base); 419 UNUSED_P(publicId); 420 while (options->parse_text != NULL) { 421 if (! xcstrcmp(systemId, options->system_id)) { 422 enum XML_Status rc; 423 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 424 if (ext_parser == NULL) 425 return XML_STATUS_ERROR; 426 rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text, 427 (int)strlen(options->parse_text), XML_TRUE); 428 XML_ParserFree(ext_parser); 429 return rc; 430 } 431 options++; 432 } 433 fail("No suitable option found"); 434 return XML_STATUS_ERROR; 435 } 436 437 /* 438 * Parameter entity evaluation support. 439 */ 440 #define ENTITY_MATCH_FAIL (-1) 441 #define ENTITY_MATCH_NOT_FOUND (0) 442 #define ENTITY_MATCH_SUCCESS (1) 443 static const XML_Char *entity_name_to_match = NULL; 444 static const XML_Char *entity_value_to_match = NULL; 445 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND; 446 447 static void XMLCALL 448 param_entity_match_handler(void *userData, const XML_Char *entityName, 449 int is_parameter_entity, const XML_Char *value, 450 int value_length, const XML_Char *base, 451 const XML_Char *systemId, const XML_Char *publicId, 452 const XML_Char *notationName) { 453 UNUSED_P(userData); 454 UNUSED_P(base); 455 UNUSED_P(systemId); 456 UNUSED_P(publicId); 457 UNUSED_P(notationName); 458 if (! is_parameter_entity || entity_name_to_match == NULL 459 || entity_value_to_match == NULL) { 460 return; 461 } 462 if (! xcstrcmp(entityName, entity_name_to_match)) { 463 /* The cast here is safe because we control the horizontal and 464 * the vertical, and we therefore know our strings are never 465 * going to overflow an int. 466 */ 467 if (value_length != (int)xcstrlen(entity_value_to_match) 468 || xcstrncmp(value, entity_value_to_match, value_length)) { 469 entity_match_flag = ENTITY_MATCH_FAIL; 470 } else { 471 entity_match_flag = ENTITY_MATCH_SUCCESS; 472 } 473 } 474 /* Else leave the match flag alone */ 475 } 476 477 /* 478 * Character & encoding tests. 479 */ 480 481 START_TEST(test_nul_byte) { 482 char text[] = "<doc>\0</doc>"; 483 484 /* test that a NUL byte (in US-ASCII data) is an error */ 485 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 486 == XML_STATUS_OK) 487 fail("Parser did not report error on NUL-byte."); 488 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 489 xml_failure(g_parser); 490 } 491 END_TEST 492 493 START_TEST(test_u0000_char) { 494 /* test that a NUL byte (in US-ASCII data) is an error */ 495 expect_failure("<doc>�</doc>", XML_ERROR_BAD_CHAR_REF, 496 "Parser did not report error on NUL-byte."); 497 } 498 END_TEST 499 500 START_TEST(test_siphash_self) { 501 if (! sip24_valid()) 502 fail("SipHash self-test failed"); 503 } 504 END_TEST 505 506 START_TEST(test_siphash_spec) { 507 /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */ 508 const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" 509 "\x0a\x0b\x0c\x0d\x0e"; 510 const size_t len = sizeof(message) - 1; 511 const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U); 512 struct siphash state; 513 struct sipkey key; 514 515 sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" 516 "\x0a\x0b\x0c\x0d\x0e\x0f"); 517 sip24_init(&state, &key); 518 519 /* Cover spread across calls */ 520 sip24_update(&state, message, 4); 521 sip24_update(&state, message + 4, len - 4); 522 523 /* Cover null length */ 524 sip24_update(&state, message, 0); 525 526 if (sip24_final(&state) != expected) 527 fail("sip24_final failed spec test\n"); 528 529 /* Cover wrapper */ 530 if (siphash24(message, len, &key) != expected) 531 fail("siphash24 failed spec test\n"); 532 } 533 END_TEST 534 535 START_TEST(test_bom_utf8) { 536 /* This test is really just making sure we don't core on a UTF-8 BOM. */ 537 const char *text = "\357\273\277<e/>"; 538 539 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 540 == XML_STATUS_ERROR) 541 xml_failure(g_parser); 542 } 543 END_TEST 544 545 START_TEST(test_bom_utf16_be) { 546 char text[] = "\376\377\0<\0e\0/\0>"; 547 548 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 549 == XML_STATUS_ERROR) 550 xml_failure(g_parser); 551 } 552 END_TEST 553 554 START_TEST(test_bom_utf16_le) { 555 char text[] = "\377\376<\0e\0/\0>\0"; 556 557 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 558 == XML_STATUS_ERROR) 559 xml_failure(g_parser); 560 } 561 END_TEST 562 563 /* Parse whole buffer at once to exercise a different code path */ 564 START_TEST(test_nobom_utf16_le) { 565 char text[] = " \0<\0e\0/\0>\0"; 566 567 if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR) 568 xml_failure(g_parser); 569 } 570 END_TEST 571 572 static void XMLCALL 573 accumulate_characters(void *userData, const XML_Char *s, int len) { 574 CharData_AppendXMLChars((CharData *)userData, s, len); 575 } 576 577 static void XMLCALL 578 accumulate_attribute(void *userData, const XML_Char *name, 579 const XML_Char **atts) { 580 CharData *storage = (CharData *)userData; 581 UNUSED_P(name); 582 /* Check there are attributes to deal with */ 583 if (atts == NULL) 584 return; 585 586 while (storage->count < 0 && atts[0] != NULL) { 587 /* "accumulate" the value of the first attribute we see */ 588 CharData_AppendXMLChars(storage, atts[1], -1); 589 atts += 2; 590 } 591 } 592 593 static void 594 _run_character_check(const char *text, const XML_Char *expected, 595 const char *file, int line) { 596 CharData storage; 597 598 CharData_Init(&storage); 599 XML_SetUserData(g_parser, &storage); 600 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 601 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 602 == XML_STATUS_ERROR) 603 _xml_failure(g_parser, file, line); 604 CharData_CheckXMLChars(&storage, expected); 605 } 606 607 #define run_character_check(text, expected) \ 608 _run_character_check(text, expected, __FILE__, __LINE__) 609 610 static void 611 _run_attribute_check(const char *text, const XML_Char *expected, 612 const char *file, int line) { 613 CharData storage; 614 615 CharData_Init(&storage); 616 XML_SetUserData(g_parser, &storage); 617 XML_SetStartElementHandler(g_parser, accumulate_attribute); 618 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 619 == XML_STATUS_ERROR) 620 _xml_failure(g_parser, file, line); 621 CharData_CheckXMLChars(&storage, expected); 622 } 623 624 #define run_attribute_check(text, expected) \ 625 _run_attribute_check(text, expected, __FILE__, __LINE__) 626 627 typedef struct ExtTest { 628 const char *parse_text; 629 const XML_Char *encoding; 630 CharData *storage; 631 } ExtTest; 632 633 static void XMLCALL 634 ext_accumulate_characters(void *userData, const XML_Char *s, int len) { 635 ExtTest *test_data = (ExtTest *)userData; 636 accumulate_characters(test_data->storage, s, len); 637 } 638 639 static void 640 _run_ext_character_check(const char *text, ExtTest *test_data, 641 const XML_Char *expected, const char *file, int line) { 642 CharData *const storage = (CharData *)malloc(sizeof(CharData)); 643 644 CharData_Init(storage); 645 test_data->storage = storage; 646 XML_SetUserData(g_parser, test_data); 647 XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters); 648 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 649 == XML_STATUS_ERROR) 650 _xml_failure(g_parser, file, line); 651 CharData_CheckXMLChars(storage, expected); 652 653 free(storage); 654 } 655 656 #define run_ext_character_check(text, test_data, expected) \ 657 _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__) 658 659 /* Regression test for SF bug #491986. */ 660 START_TEST(test_danish_latin1) { 661 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 662 "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>"; 663 #ifdef XML_UNICODE 664 const XML_Char *expected 665 = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5"); 666 #else 667 const XML_Char *expected 668 = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85"); 669 #endif 670 run_character_check(text, expected); 671 } 672 END_TEST 673 674 /* Regression test for SF bug #514281. */ 675 START_TEST(test_french_charref_hexidecimal) { 676 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 677 "<doc>éèàçêÈ</doc>"; 678 #ifdef XML_UNICODE 679 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8"); 680 #else 681 const XML_Char *expected 682 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88"); 683 #endif 684 run_character_check(text, expected); 685 } 686 END_TEST 687 688 START_TEST(test_french_charref_decimal) { 689 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 690 "<doc>éèàçêÈ</doc>"; 691 #ifdef XML_UNICODE 692 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8"); 693 #else 694 const XML_Char *expected 695 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88"); 696 #endif 697 run_character_check(text, expected); 698 } 699 END_TEST 700 701 START_TEST(test_french_latin1) { 702 const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 703 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>"; 704 #ifdef XML_UNICODE 705 const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8"); 706 #else 707 const XML_Char *expected 708 = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88"); 709 #endif 710 run_character_check(text, expected); 711 } 712 END_TEST 713 714 START_TEST(test_french_utf8) { 715 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 716 "<doc>\xC3\xA9</doc>"; 717 #ifdef XML_UNICODE 718 const XML_Char *expected = XCS("\x00e9"); 719 #else 720 const XML_Char *expected = XCS("\xC3\xA9"); 721 #endif 722 run_character_check(text, expected); 723 } 724 END_TEST 725 726 /* Regression test for SF bug #600479. 727 XXX There should be a test that exercises all legal XML Unicode 728 characters as PCDATA and attribute value content, and XML Name 729 characters as part of element and attribute names. 730 */ 731 START_TEST(test_utf8_false_rejection) { 732 const char *text = "<doc>\xEF\xBA\xBF</doc>"; 733 #ifdef XML_UNICODE 734 const XML_Char *expected = XCS("\xfebf"); 735 #else 736 const XML_Char *expected = XCS("\xEF\xBA\xBF"); 737 #endif 738 run_character_check(text, expected); 739 } 740 END_TEST 741 742 /* Regression test for SF bug #477667. 743 This test assures that any 8-bit character followed by a 7-bit 744 character will not be mistakenly interpreted as a valid UTF-8 745 sequence. 746 */ 747 START_TEST(test_illegal_utf8) { 748 char text[100]; 749 int i; 750 751 for (i = 128; i <= 255; ++i) { 752 sprintf(text, "<e>%ccd</e>", i); 753 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 754 == XML_STATUS_OK) { 755 sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text", 756 i, i); 757 fail(text); 758 } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 759 xml_failure(g_parser); 760 /* Reset the parser since we use the same parser repeatedly. */ 761 XML_ParserReset(g_parser, NULL); 762 } 763 } 764 END_TEST 765 766 /* Examples, not masks: */ 767 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */ 768 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */ 769 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */ 770 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */ 771 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */ 772 773 START_TEST(test_utf8_auto_align) { 774 struct TestCase { 775 ptrdiff_t expectedMovementInChars; 776 const char *input; 777 }; 778 779 struct TestCase cases[] = { 780 {00, ""}, 781 782 {00, UTF8_LEAD_1}, 783 784 {-1, UTF8_LEAD_2}, 785 {00, UTF8_LEAD_2 UTF8_FOLLOW}, 786 787 {-1, UTF8_LEAD_3}, 788 {-2, UTF8_LEAD_3 UTF8_FOLLOW}, 789 {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW}, 790 791 {-1, UTF8_LEAD_4}, 792 {-2, UTF8_LEAD_4 UTF8_FOLLOW}, 793 {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW}, 794 {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW}, 795 }; 796 797 size_t i = 0; 798 bool success = true; 799 for (; i < sizeof(cases) / sizeof(*cases); i++) { 800 const char *fromLim = cases[i].input + strlen(cases[i].input); 801 const char *const fromLimInitially = fromLim; 802 ptrdiff_t actualMovementInChars; 803 804 _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim); 805 806 actualMovementInChars = (fromLim - fromLimInitially); 807 if (actualMovementInChars != cases[i].expectedMovementInChars) { 808 size_t j = 0; 809 success = false; 810 printf("[-] UTF-8 case %2u: Expected movement by %2d chars" 811 ", actually moved by %2d chars: \"", 812 (unsigned)(i + 1), (int)cases[i].expectedMovementInChars, 813 (int)actualMovementInChars); 814 for (; j < strlen(cases[i].input); j++) { 815 printf("\\x%02x", (unsigned char)cases[i].input[j]); 816 } 817 printf("\"\n"); 818 } 819 } 820 821 if (! success) { 822 fail("UTF-8 auto-alignment is not bullet-proof\n"); 823 } 824 } 825 END_TEST 826 827 START_TEST(test_utf16) { 828 /* <?xml version="1.0" encoding="UTF-16"?> 829 * <doc a='123'>some {A} text</doc> 830 * 831 * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A 832 */ 833 char text[] 834 = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o" 835 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o" 836 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066" 837 "\000'\000?\000>\000\n" 838 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>" 839 "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000" 840 "<\000/\000d\000o\000c\000>"; 841 #ifdef XML_UNICODE 842 const XML_Char *expected = XCS("some \xff21 text"); 843 #else 844 const XML_Char *expected = XCS("some \357\274\241 text"); 845 #endif 846 CharData storage; 847 848 CharData_Init(&storage); 849 XML_SetUserData(g_parser, &storage); 850 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 851 if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE) 852 == XML_STATUS_ERROR) 853 xml_failure(g_parser); 854 CharData_CheckXMLChars(&storage, expected); 855 } 856 END_TEST 857 858 START_TEST(test_utf16_le_epilog_newline) { 859 unsigned int first_chunk_bytes = 17; 860 char text[] = "\xFF\xFE" /* BOM */ 861 "<\000e\000/\000>\000" /* document element */ 862 "\r\000\n\000\r\000\n\000"; /* epilog */ 863 864 if (first_chunk_bytes >= sizeof(text) - 1) 865 fail("bad value of first_chunk_bytes"); 866 if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE) 867 == XML_STATUS_ERROR) 868 xml_failure(g_parser); 869 else { 870 enum XML_Status rc; 871 rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes, 872 sizeof(text) - first_chunk_bytes - 1, 873 XML_TRUE); 874 if (rc == XML_STATUS_ERROR) 875 xml_failure(g_parser); 876 } 877 } 878 END_TEST 879 880 /* Test that an outright lie in the encoding is faulted */ 881 START_TEST(test_not_utf16) { 882 const char *text = "<?xml version='1.0' encoding='utf-16'?>" 883 "<doc>Hi</doc>"; 884 885 /* Use a handler to provoke the appropriate code paths */ 886 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 887 expect_failure(text, XML_ERROR_INCORRECT_ENCODING, 888 "UTF-16 declared in UTF-8 not faulted"); 889 } 890 END_TEST 891 892 /* Test that an unknown encoding is rejected */ 893 START_TEST(test_bad_encoding) { 894 const char *text = "<doc>Hi</doc>"; 895 896 if (! XML_SetEncoding(g_parser, XCS("unknown-encoding"))) 897 fail("XML_SetEncoding failed"); 898 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 899 "Unknown encoding not faulted"); 900 } 901 END_TEST 902 903 /* Regression test for SF bug #481609, #774028. */ 904 START_TEST(test_latin1_umlauts) { 905 const char *text 906 = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 907 "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n" 908 " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>"; 909 #ifdef XML_UNICODE 910 /* Expected results in UTF-16 */ 911 const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ") 912 XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >"); 913 #else 914 /* Expected results in UTF-8 */ 915 const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") 916 XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >"); 917 #endif 918 919 run_character_check(text, expected); 920 XML_ParserReset(g_parser, NULL); 921 run_attribute_check(text, expected); 922 /* Repeat with a default handler */ 923 XML_ParserReset(g_parser, NULL); 924 XML_SetDefaultHandler(g_parser, dummy_default_handler); 925 run_character_check(text, expected); 926 XML_ParserReset(g_parser, NULL); 927 XML_SetDefaultHandler(g_parser, dummy_default_handler); 928 run_attribute_check(text, expected); 929 } 930 END_TEST 931 932 /* Test that an element name with a 4-byte UTF-8 character is rejected */ 933 START_TEST(test_long_utf8_character) { 934 const char *text 935 = "<?xml version='1.0' encoding='utf-8'?>\n" 936 /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */ 937 "<do\xf0\x90\x80\x80/>"; 938 expect_failure(text, XML_ERROR_INVALID_TOKEN, 939 "4-byte UTF-8 character in element name not faulted"); 940 } 941 END_TEST 942 943 /* Test that a long latin-1 attribute (too long to convert in one go) 944 * is correctly converted 945 */ 946 START_TEST(test_long_latin1_attribute) { 947 const char *text 948 = "<?xml version='1.0' encoding='iso-8859-1'?>\n" 949 "<doc att='" 950 /* 64 characters per line */ 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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 966 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 967 /* Last character splits across a buffer boundary */ 968 "\xe4'>\n</doc>"; 969 970 const XML_Char *expected = 971 /* 64 characters per line */ 972 /* clang-format off */ 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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 988 XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO") 989 /* clang-format on */ 990 #ifdef XML_UNICODE 991 XCS("\x00e4"); 992 #else 993 XCS("\xc3\xa4"); 994 #endif 995 996 run_attribute_check(text, expected); 997 } 998 END_TEST 999 1000 /* Test that a long ASCII attribute (too long to convert in one go) 1001 * is correctly converted 1002 */ 1003 START_TEST(test_long_ascii_attribute) { 1004 const char *text 1005 = "<?xml version='1.0' encoding='us-ascii'?>\n" 1006 "<doc att='" 1007 /* 64 characters per line */ 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 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 1024 "01234'>\n</doc>"; 1025 const XML_Char *expected = 1026 /* 64 characters per line */ 1027 /* clang-format off */ 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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 1044 XCS("01234"); 1045 /* clang-format on */ 1046 1047 run_attribute_check(text, expected); 1048 } 1049 END_TEST 1050 1051 /* Regression test #1 for SF bug #653180. */ 1052 START_TEST(test_line_number_after_parse) { 1053 const char *text = "<tag>\n" 1054 "\n" 1055 "\n</tag>"; 1056 XML_Size lineno; 1057 1058 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1059 == XML_STATUS_ERROR) 1060 xml_failure(g_parser); 1061 lineno = XML_GetCurrentLineNumber(g_parser); 1062 if (lineno != 4) { 1063 char buffer[100]; 1064 sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno); 1065 fail(buffer); 1066 } 1067 } 1068 END_TEST 1069 1070 /* Regression test #2 for SF bug #653180. */ 1071 START_TEST(test_column_number_after_parse) { 1072 const char *text = "<tag></tag>"; 1073 XML_Size colno; 1074 1075 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1076 == XML_STATUS_ERROR) 1077 xml_failure(g_parser); 1078 colno = XML_GetCurrentColumnNumber(g_parser); 1079 if (colno != 11) { 1080 char buffer[100]; 1081 sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno); 1082 fail(buffer); 1083 } 1084 } 1085 END_TEST 1086 1087 #define STRUCT_START_TAG 0 1088 #define STRUCT_END_TAG 1 1089 static void XMLCALL 1090 start_element_event_handler2(void *userData, const XML_Char *name, 1091 const XML_Char **attr) { 1092 StructData *storage = (StructData *)userData; 1093 UNUSED_P(attr); 1094 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), 1095 XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG); 1096 } 1097 1098 static void XMLCALL 1099 end_element_event_handler2(void *userData, const XML_Char *name) { 1100 StructData *storage = (StructData *)userData; 1101 StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser), 1102 XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG); 1103 } 1104 1105 /* Regression test #3 for SF bug #653180. */ 1106 START_TEST(test_line_and_column_numbers_inside_handlers) { 1107 const char *text = "<a>\n" /* Unix end-of-line */ 1108 " <b>\r\n" /* Windows end-of-line */ 1109 " <c/>\r" /* Mac OS end-of-line */ 1110 " </b>\n" 1111 " <d>\n" 1112 " <f/>\n" 1113 " </d>\n" 1114 "</a>"; 1115 const StructDataEntry expected[] 1116 = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG}, 1117 {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG}, 1118 {XCS("b"), 2, 4, STRUCT_END_TAG}, {XCS("d"), 2, 5, STRUCT_START_TAG}, 1119 {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG}, 1120 {XCS("d"), 2, 7, STRUCT_END_TAG}, {XCS("a"), 0, 8, STRUCT_END_TAG}}; 1121 const int expected_count = sizeof(expected) / sizeof(StructDataEntry); 1122 StructData storage; 1123 1124 StructData_Init(&storage); 1125 XML_SetUserData(g_parser, &storage); 1126 XML_SetStartElementHandler(g_parser, start_element_event_handler2); 1127 XML_SetEndElementHandler(g_parser, end_element_event_handler2); 1128 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1129 == XML_STATUS_ERROR) 1130 xml_failure(g_parser); 1131 1132 StructData_CheckItems(&storage, expected, expected_count); 1133 StructData_Dispose(&storage); 1134 } 1135 END_TEST 1136 1137 /* Regression test #4 for SF bug #653180. */ 1138 START_TEST(test_line_number_after_error) { 1139 const char *text = "<a>\n" 1140 " <b>\n" 1141 " </a>"; /* missing </b> */ 1142 XML_Size lineno; 1143 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1144 != XML_STATUS_ERROR) 1145 fail("Expected a parse error"); 1146 1147 lineno = XML_GetCurrentLineNumber(g_parser); 1148 if (lineno != 3) { 1149 char buffer[100]; 1150 sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno); 1151 fail(buffer); 1152 } 1153 } 1154 END_TEST 1155 1156 /* Regression test #5 for SF bug #653180. */ 1157 START_TEST(test_column_number_after_error) { 1158 const char *text = "<a>\n" 1159 " <b>\n" 1160 " </a>"; /* missing </b> */ 1161 XML_Size colno; 1162 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 1163 != XML_STATUS_ERROR) 1164 fail("Expected a parse error"); 1165 1166 colno = XML_GetCurrentColumnNumber(g_parser); 1167 if (colno != 4) { 1168 char buffer[100]; 1169 sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno); 1170 fail(buffer); 1171 } 1172 } 1173 END_TEST 1174 1175 /* Regression test for SF bug #478332. */ 1176 START_TEST(test_really_long_lines) { 1177 /* This parses an input line longer than INIT_DATA_BUF_SIZE 1178 characters long (defined to be 1024 in xmlparse.c). We take a 1179 really cheesy approach to building the input buffer, because 1180 this avoids writing bugs in buffer-filling code. 1181 */ 1182 const char *text 1183 = "<e>" 1184 /* 64 chars */ 1185 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1186 /* until we have at least 1024 characters on the line: */ 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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1203 "</e>"; 1204 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1205 == XML_STATUS_ERROR) 1206 xml_failure(g_parser); 1207 } 1208 END_TEST 1209 1210 /* Test cdata processing across a buffer boundary */ 1211 START_TEST(test_really_long_encoded_lines) { 1212 /* As above, except that we want to provoke an output buffer 1213 * overflow with a non-trivial encoding. For this we need to pass 1214 * the whole cdata in one go, not byte-by-byte. 1215 */ 1216 void *buffer; 1217 const char *text 1218 = "<?xml version='1.0' encoding='iso-8859-1'?>" 1219 "<e>" 1220 /* 64 chars */ 1221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1222 /* until we have at least 1024 characters on the line: */ 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 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+" 1239 "</e>"; 1240 int parse_len = (int)strlen(text); 1241 1242 /* Need a cdata handler to provoke the code path we want to test */ 1243 XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler); 1244 buffer = XML_GetBuffer(g_parser, parse_len); 1245 if (buffer == NULL) 1246 fail("Could not allocate parse buffer"); 1247 assert(buffer != NULL); 1248 memcpy(buffer, text, parse_len); 1249 if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR) 1250 xml_failure(g_parser); 1251 } 1252 END_TEST 1253 1254 /* 1255 * Element event tests. 1256 */ 1257 1258 static void XMLCALL 1259 start_element_event_handler(void *userData, const XML_Char *name, 1260 const XML_Char **atts) { 1261 UNUSED_P(atts); 1262 CharData_AppendXMLChars((CharData *)userData, name, -1); 1263 } 1264 1265 static void XMLCALL 1266 end_element_event_handler(void *userData, const XML_Char *name) { 1267 CharData *storage = (CharData *)userData; 1268 CharData_AppendXMLChars(storage, XCS("/"), 1); 1269 CharData_AppendXMLChars(storage, name, -1); 1270 } 1271 1272 START_TEST(test_end_element_events) { 1273 const char *text = "<a><b><c/></b><d><f/></d></a>"; 1274 const XML_Char *expected = XCS("/c/b/f/d/a"); 1275 CharData storage; 1276 1277 CharData_Init(&storage); 1278 XML_SetUserData(g_parser, &storage); 1279 XML_SetEndElementHandler(g_parser, end_element_event_handler); 1280 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1281 == XML_STATUS_ERROR) 1282 xml_failure(g_parser); 1283 CharData_CheckXMLChars(&storage, expected); 1284 } 1285 END_TEST 1286 1287 /* 1288 * Attribute tests. 1289 */ 1290 1291 /* Helpers used by the following test; this checks any "attr" and "refs" 1292 attributes to make sure whitespace has been normalized. 1293 1294 Return true if whitespace has been normalized in a string, using 1295 the rules for attribute value normalization. The 'is_cdata' flag 1296 is needed since CDATA attributes don't need to have multiple 1297 whitespace characters collapsed to a single space, while other 1298 attribute data types do. (Section 3.3.3 of the recommendation.) 1299 */ 1300 static int 1301 is_whitespace_normalized(const XML_Char *s, int is_cdata) { 1302 int blanks = 0; 1303 int at_start = 1; 1304 while (*s) { 1305 if (*s == XCS(' ')) 1306 ++blanks; 1307 else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r')) 1308 return 0; 1309 else { 1310 if (at_start) { 1311 at_start = 0; 1312 if (blanks && ! is_cdata) 1313 /* illegal leading blanks */ 1314 return 0; 1315 } else if (blanks > 1 && ! is_cdata) 1316 return 0; 1317 blanks = 0; 1318 } 1319 ++s; 1320 } 1321 if (blanks && ! is_cdata) 1322 return 0; 1323 return 1; 1324 } 1325 1326 /* Check the attribute whitespace checker: */ 1327 static void 1328 testhelper_is_whitespace_normalized(void) { 1329 assert(is_whitespace_normalized(XCS("abc"), 0)); 1330 assert(is_whitespace_normalized(XCS("abc"), 1)); 1331 assert(is_whitespace_normalized(XCS("abc def ghi"), 0)); 1332 assert(is_whitespace_normalized(XCS("abc def ghi"), 1)); 1333 assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0)); 1334 assert(is_whitespace_normalized(XCS(" abc def ghi"), 1)); 1335 assert(! is_whitespace_normalized(XCS("abc def ghi"), 0)); 1336 assert(is_whitespace_normalized(XCS("abc def ghi"), 1)); 1337 assert(! is_whitespace_normalized(XCS("abc def ghi "), 0)); 1338 assert(is_whitespace_normalized(XCS("abc def ghi "), 1)); 1339 assert(! is_whitespace_normalized(XCS(" "), 0)); 1340 assert(is_whitespace_normalized(XCS(" "), 1)); 1341 assert(! is_whitespace_normalized(XCS("\t"), 0)); 1342 assert(! is_whitespace_normalized(XCS("\t"), 1)); 1343 assert(! is_whitespace_normalized(XCS("\n"), 0)); 1344 assert(! is_whitespace_normalized(XCS("\n"), 1)); 1345 assert(! is_whitespace_normalized(XCS("\r"), 0)); 1346 assert(! is_whitespace_normalized(XCS("\r"), 1)); 1347 assert(! is_whitespace_normalized(XCS("abc\t def"), 1)); 1348 } 1349 1350 static void XMLCALL 1351 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name, 1352 const XML_Char **atts) { 1353 int i; 1354 UNUSED_P(userData); 1355 UNUSED_P(name); 1356 for (i = 0; atts[i] != NULL; i += 2) { 1357 const XML_Char *attrname = atts[i]; 1358 const XML_Char *value = atts[i + 1]; 1359 if (xcstrcmp(XCS("attr"), attrname) == 0 1360 || xcstrcmp(XCS("ents"), attrname) == 0 1361 || xcstrcmp(XCS("refs"), attrname) == 0) { 1362 if (! is_whitespace_normalized(value, 0)) { 1363 char buffer[256]; 1364 sprintf(buffer, 1365 "attribute value not normalized: %" XML_FMT_STR 1366 "='%" XML_FMT_STR "'", 1367 attrname, value); 1368 fail(buffer); 1369 } 1370 } 1371 } 1372 } 1373 1374 START_TEST(test_attr_whitespace_normalization) { 1375 const char *text 1376 = "<!DOCTYPE doc [\n" 1377 " <!ATTLIST doc\n" 1378 " attr NMTOKENS #REQUIRED\n" 1379 " ents ENTITIES #REQUIRED\n" 1380 " refs IDREFS #REQUIRED>\n" 1381 "]>\n" 1382 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n" 1383 " ents=' ent-1 \t\r\n" 1384 " ent-2 ' >\n" 1385 " <e id='id-1'/>\n" 1386 " <e id='id-2'/>\n" 1387 "</doc>"; 1388 1389 XML_SetStartElementHandler(g_parser, 1390 check_attr_contains_normalized_whitespace); 1391 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1392 == XML_STATUS_ERROR) 1393 xml_failure(g_parser); 1394 } 1395 END_TEST 1396 1397 /* 1398 * XML declaration tests. 1399 */ 1400 1401 START_TEST(test_xmldecl_misplaced) { 1402 expect_failure("\n" 1403 "<?xml version='1.0'?>\n" 1404 "<a/>", 1405 XML_ERROR_MISPLACED_XML_PI, 1406 "failed to report misplaced XML declaration"); 1407 } 1408 END_TEST 1409 1410 START_TEST(test_xmldecl_invalid) { 1411 expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL, 1412 "Failed to report invalid XML declaration"); 1413 } 1414 END_TEST 1415 1416 START_TEST(test_xmldecl_missing_attr) { 1417 expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL, 1418 "Failed to report missing XML declaration attribute"); 1419 } 1420 END_TEST 1421 1422 START_TEST(test_xmldecl_missing_value) { 1423 expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n" 1424 "<doc/>", 1425 XML_ERROR_XML_DECL, 1426 "Failed to report missing attribute value"); 1427 } 1428 END_TEST 1429 1430 /* Regression test for SF bug #584832. */ 1431 static int XMLCALL 1432 UnknownEncodingHandler(void *data, const XML_Char *encoding, 1433 XML_Encoding *info) { 1434 UNUSED_P(data); 1435 if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) { 1436 int i; 1437 for (i = 0; i < 256; ++i) 1438 info->map[i] = i; 1439 info->data = NULL; 1440 info->convert = NULL; 1441 info->release = NULL; 1442 return XML_STATUS_OK; 1443 } 1444 return XML_STATUS_ERROR; 1445 } 1446 1447 START_TEST(test_unknown_encoding_internal_entity) { 1448 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 1449 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 1450 "<test a='&foo;'/>"; 1451 1452 XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL); 1453 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1454 == XML_STATUS_ERROR) 1455 xml_failure(g_parser); 1456 } 1457 END_TEST 1458 1459 /* Test unrecognised encoding handler */ 1460 static void 1461 dummy_release(void *data) { 1462 UNUSED_P(data); 1463 } 1464 1465 static int XMLCALL 1466 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding, 1467 XML_Encoding *info) { 1468 UNUSED_P(data); 1469 UNUSED_P(encoding); 1470 info->data = NULL; 1471 info->convert = NULL; 1472 info->release = dummy_release; 1473 return XML_STATUS_ERROR; 1474 } 1475 1476 START_TEST(test_unrecognised_encoding_internal_entity) { 1477 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 1478 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 1479 "<test a='&foo;'/>"; 1480 1481 XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL); 1482 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1483 != XML_STATUS_ERROR) 1484 fail("Unrecognised encoding not rejected"); 1485 } 1486 END_TEST 1487 1488 /* Regression test for SF bug #620106. */ 1489 static int XMLCALL 1490 external_entity_loader(XML_Parser parser, const XML_Char *context, 1491 const XML_Char *base, const XML_Char *systemId, 1492 const XML_Char *publicId) { 1493 ExtTest *test_data = (ExtTest *)XML_GetUserData(parser); 1494 XML_Parser extparser; 1495 1496 UNUSED_P(base); 1497 UNUSED_P(systemId); 1498 UNUSED_P(publicId); 1499 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 1500 if (extparser == NULL) 1501 fail("Could not create external entity parser."); 1502 if (test_data->encoding != NULL) { 1503 if (! XML_SetEncoding(extparser, test_data->encoding)) 1504 fail("XML_SetEncoding() ignored for external entity"); 1505 } 1506 if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text, 1507 (int)strlen(test_data->parse_text), XML_TRUE) 1508 == XML_STATUS_ERROR) { 1509 xml_failure(extparser); 1510 return XML_STATUS_ERROR; 1511 } 1512 XML_ParserFree(extparser); 1513 return XML_STATUS_OK; 1514 } 1515 1516 START_TEST(test_ext_entity_set_encoding) { 1517 const char *text = "<!DOCTYPE doc [\n" 1518 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1519 "]>\n" 1520 "<doc>&en;</doc>"; 1521 ExtTest test_data 1522 = {/* This text says it's an unsupported encoding, but it's really 1523 UTF-8, which we tell Expat using XML_SetEncoding(). 1524 */ 1525 "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL}; 1526 #ifdef XML_UNICODE 1527 const XML_Char *expected = XCS("\x00e9"); 1528 #else 1529 const XML_Char *expected = XCS("\xc3\xa9"); 1530 #endif 1531 1532 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1533 run_ext_character_check(text, &test_data, expected); 1534 } 1535 END_TEST 1536 1537 /* Test external entities with no handler */ 1538 START_TEST(test_ext_entity_no_handler) { 1539 const char *text = "<!DOCTYPE doc [\n" 1540 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1541 "]>\n" 1542 "<doc>&en;</doc>"; 1543 1544 XML_SetDefaultHandler(g_parser, dummy_default_handler); 1545 run_character_check(text, XCS("")); 1546 } 1547 END_TEST 1548 1549 /* Test UTF-8 BOM is accepted */ 1550 START_TEST(test_ext_entity_set_bom) { 1551 const char *text = "<!DOCTYPE doc [\n" 1552 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1553 "]>\n" 1554 "<doc>&en;</doc>"; 1555 ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */ 1556 "<?xml encoding='iso-8859-3'?>" 1557 "\xC3\xA9", 1558 XCS("utf-8"), NULL}; 1559 #ifdef XML_UNICODE 1560 const XML_Char *expected = XCS("\x00e9"); 1561 #else 1562 const XML_Char *expected = XCS("\xc3\xa9"); 1563 #endif 1564 1565 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1566 run_ext_character_check(text, &test_data, expected); 1567 } 1568 END_TEST 1569 1570 /* Test that bad encodings are faulted */ 1571 typedef struct ext_faults { 1572 const char *parse_text; 1573 const char *fail_text; 1574 const XML_Char *encoding; 1575 enum XML_Error error; 1576 } ExtFaults; 1577 1578 static int XMLCALL 1579 external_entity_faulter(XML_Parser parser, const XML_Char *context, 1580 const XML_Char *base, const XML_Char *systemId, 1581 const XML_Char *publicId) { 1582 XML_Parser ext_parser; 1583 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 1584 1585 UNUSED_P(base); 1586 UNUSED_P(systemId); 1587 UNUSED_P(publicId); 1588 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 1589 if (ext_parser == NULL) 1590 fail("Could not create external entity parser"); 1591 if (fault->encoding != NULL) { 1592 if (! XML_SetEncoding(ext_parser, fault->encoding)) 1593 fail("XML_SetEncoding failed"); 1594 } 1595 if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text, 1596 (int)strlen(fault->parse_text), XML_TRUE) 1597 != XML_STATUS_ERROR) 1598 fail(fault->fail_text); 1599 if (XML_GetErrorCode(ext_parser) != fault->error) 1600 xml_failure(ext_parser); 1601 1602 XML_ParserFree(ext_parser); 1603 return XML_STATUS_ERROR; 1604 } 1605 1606 START_TEST(test_ext_entity_bad_encoding) { 1607 const char *text = "<!DOCTYPE doc [\n" 1608 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1609 "]>\n" 1610 "<doc>&en;</doc>"; 1611 ExtFaults fault 1612 = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted", 1613 XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING}; 1614 1615 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 1616 XML_SetUserData(g_parser, &fault); 1617 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 1618 "Bad encoding should not have been accepted"); 1619 } 1620 END_TEST 1621 1622 /* Try handing an invalid encoding to an external entity parser */ 1623 START_TEST(test_ext_entity_bad_encoding_2) { 1624 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1625 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1626 "<doc>&entity;</doc>"; 1627 ExtFaults fault 1628 = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted", 1629 XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING}; 1630 1631 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1632 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 1633 XML_SetUserData(g_parser, &fault); 1634 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 1635 "Bad encoding not faulted in external entity handler"); 1636 } 1637 END_TEST 1638 1639 /* Test that no error is reported for unknown entities if we don't 1640 read an external subset. This was fixed in Expat 1.95.5. 1641 */ 1642 START_TEST(test_wfc_undeclared_entity_unread_external_subset) { 1643 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 1644 "<doc>&entity;</doc>"; 1645 1646 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1647 == XML_STATUS_ERROR) 1648 xml_failure(g_parser); 1649 } 1650 END_TEST 1651 1652 /* Test that an error is reported for unknown entities if we don't 1653 have an external subset. 1654 */ 1655 START_TEST(test_wfc_undeclared_entity_no_external_subset) { 1656 expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY, 1657 "Parser did not report undefined entity w/out a DTD."); 1658 } 1659 END_TEST 1660 1661 /* Test that an error is reported for unknown entities if we don't 1662 read an external subset, but have been declared standalone. 1663 */ 1664 START_TEST(test_wfc_undeclared_entity_standalone) { 1665 const char *text 1666 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n" 1667 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1668 "<doc>&entity;</doc>"; 1669 1670 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 1671 "Parser did not report undefined entity (standalone)."); 1672 } 1673 END_TEST 1674 1675 /* Test that an error is reported for unknown entities if we have read 1676 an external subset, and standalone is true. 1677 */ 1678 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) { 1679 const char *text 1680 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n" 1681 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1682 "<doc>&entity;</doc>"; 1683 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1684 1685 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1686 XML_SetUserData(g_parser, &test_data); 1687 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1688 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 1689 "Parser did not report undefined entity (external DTD)."); 1690 } 1691 END_TEST 1692 1693 /* Test that external entity handling is not done if the parsing flag 1694 * is set to UNLESS_STANDALONE 1695 */ 1696 START_TEST(test_entity_with_external_subset_unless_standalone) { 1697 const char *text 1698 = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n" 1699 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1700 "<doc>&entity;</doc>"; 1701 ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL}; 1702 1703 XML_SetParamEntityParsing(g_parser, 1704 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); 1705 XML_SetUserData(g_parser, &test_data); 1706 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1707 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 1708 "Parser did not report undefined entity"); 1709 } 1710 END_TEST 1711 1712 /* Test that no error is reported for unknown entities if we have read 1713 an external subset, and standalone is false. 1714 */ 1715 START_TEST(test_wfc_undeclared_entity_with_external_subset) { 1716 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1717 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1718 "<doc>&entity;</doc>"; 1719 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1720 1721 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1722 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1723 run_ext_character_check(text, &test_data, XCS("")); 1724 } 1725 END_TEST 1726 1727 /* Test that an error is reported if our NotStandalone handler fails */ 1728 static int XMLCALL 1729 reject_not_standalone_handler(void *userData) { 1730 UNUSED_P(userData); 1731 return XML_STATUS_ERROR; 1732 } 1733 1734 START_TEST(test_not_standalone_handler_reject) { 1735 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1736 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1737 "<doc>&entity;</doc>"; 1738 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1739 1740 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1741 XML_SetUserData(g_parser, &test_data); 1742 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1743 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler); 1744 expect_failure(text, XML_ERROR_NOT_STANDALONE, 1745 "NotStandalone handler failed to reject"); 1746 1747 /* Try again but without external entity handling */ 1748 XML_ParserReset(g_parser, NULL); 1749 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler); 1750 expect_failure(text, XML_ERROR_NOT_STANDALONE, 1751 "NotStandalone handler failed to reject"); 1752 } 1753 END_TEST 1754 1755 /* Test that no error is reported if our NotStandalone handler succeeds */ 1756 static int XMLCALL 1757 accept_not_standalone_handler(void *userData) { 1758 UNUSED_P(userData); 1759 return XML_STATUS_OK; 1760 } 1761 1762 START_TEST(test_not_standalone_handler_accept) { 1763 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 1764 "<!DOCTYPE doc SYSTEM 'foo'>\n" 1765 "<doc>&entity;</doc>"; 1766 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 1767 1768 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1769 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 1770 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler); 1771 run_ext_character_check(text, &test_data, XCS("")); 1772 1773 /* Repeat without the external entity handler */ 1774 XML_ParserReset(g_parser, NULL); 1775 XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler); 1776 run_character_check(text, XCS("")); 1777 } 1778 END_TEST 1779 1780 START_TEST(test_wfc_no_recursive_entity_refs) { 1781 const char *text = "<!DOCTYPE doc [\n" 1782 " <!ENTITY entity '&entity;'>\n" 1783 "]>\n" 1784 "<doc>&entity;</doc>"; 1785 1786 expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF, 1787 "Parser did not report recursive entity reference."); 1788 } 1789 END_TEST 1790 1791 /* Test incomplete external entities are faulted */ 1792 START_TEST(test_ext_entity_invalid_parse) { 1793 const char *text = "<!DOCTYPE doc [\n" 1794 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 1795 "]>\n" 1796 "<doc>&en;</doc>"; 1797 const ExtFaults faults[] 1798 = {{"<", "Incomplete element declaration not faulted", NULL, 1799 XML_ERROR_UNCLOSED_TOKEN}, 1800 {"<\xe2\x82", /* First two bytes of a three-byte char */ 1801 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR}, 1802 {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL, 1803 XML_ERROR_PARTIAL_CHAR}, 1804 {NULL, NULL, NULL, XML_ERROR_NONE}}; 1805 const ExtFaults *fault = faults; 1806 1807 for (; fault->parse_text != NULL; fault++) { 1808 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 1809 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 1810 XML_SetUserData(g_parser, (void *)fault); 1811 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 1812 "Parser did not report external entity error"); 1813 XML_ParserReset(g_parser, NULL); 1814 } 1815 } 1816 END_TEST 1817 1818 /* Regression test for SF bug #483514. */ 1819 START_TEST(test_dtd_default_handling) { 1820 const char *text = "<!DOCTYPE doc [\n" 1821 "<!ENTITY e SYSTEM 'http://example.org/e'>\n" 1822 "<!NOTATION n SYSTEM 'http://example.org/n'>\n" 1823 "<!ELEMENT doc EMPTY>\n" 1824 "<!ATTLIST doc a CDATA #IMPLIED>\n" 1825 "<?pi in dtd?>\n" 1826 "<!--comment in dtd-->\n" 1827 "]><doc/>"; 1828 1829 XML_SetDefaultHandler(g_parser, accumulate_characters); 1830 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 1831 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 1832 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 1833 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 1834 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 1835 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 1836 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 1837 XML_SetCommentHandler(g_parser, dummy_comment_handler); 1838 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler); 1839 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler); 1840 run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>")); 1841 } 1842 END_TEST 1843 1844 /* Test handling of attribute declarations */ 1845 typedef struct AttTest { 1846 const char *definition; 1847 const XML_Char *element_name; 1848 const XML_Char *attr_name; 1849 const XML_Char *attr_type; 1850 const XML_Char *default_value; 1851 int is_required; 1852 } AttTest; 1853 1854 static void XMLCALL 1855 verify_attlist_decl_handler(void *userData, const XML_Char *element_name, 1856 const XML_Char *attr_name, 1857 const XML_Char *attr_type, 1858 const XML_Char *default_value, int is_required) { 1859 AttTest *at = (AttTest *)userData; 1860 1861 if (xcstrcmp(element_name, at->element_name)) 1862 fail("Unexpected element name in attribute declaration"); 1863 if (xcstrcmp(attr_name, at->attr_name)) 1864 fail("Unexpected attribute name in attribute declaration"); 1865 if (xcstrcmp(attr_type, at->attr_type)) 1866 fail("Unexpected attribute type in attribute declaration"); 1867 if ((default_value == NULL && at->default_value != NULL) 1868 || (default_value != NULL && at->default_value == NULL) 1869 || (default_value != NULL && xcstrcmp(default_value, at->default_value))) 1870 fail("Unexpected default value in attribute declaration"); 1871 if (is_required != at->is_required) 1872 fail("Requirement mismatch in attribute declaration"); 1873 } 1874 1875 START_TEST(test_dtd_attr_handling) { 1876 const char *prolog = "<!DOCTYPE doc [\n" 1877 "<!ELEMENT doc EMPTY>\n"; 1878 AttTest attr_data[] 1879 = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n" 1880 "]>" 1881 "<doc a='two'/>", 1882 XCS("doc"), XCS("a"), 1883 XCS("(one|two|three)"), /* Extraneous spaces will be removed */ 1884 NULL, XML_TRUE}, 1885 {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n" 1886 "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n" 1887 "]>" 1888 "<doc/>", 1889 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE}, 1890 {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n" 1891 "]>" 1892 "<doc/>", 1893 XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE}, 1894 {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n" 1895 "]>" 1896 "<doc/>", 1897 XCS("doc"), XCS("a"), XCS("CDATA"), 1898 #ifdef XML_UNICODE 1899 XCS("\x06f2"), 1900 #else 1901 XCS("\xdb\xb2"), 1902 #endif 1903 XML_FALSE}, 1904 {NULL, NULL, NULL, NULL, NULL, XML_FALSE}}; 1905 AttTest *test; 1906 1907 for (test = attr_data; test->definition != NULL; test++) { 1908 XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler); 1909 XML_SetUserData(g_parser, test); 1910 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog), 1911 XML_FALSE) 1912 == XML_STATUS_ERROR) 1913 xml_failure(g_parser); 1914 if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition, 1915 (int)strlen(test->definition), XML_TRUE) 1916 == XML_STATUS_ERROR) 1917 xml_failure(g_parser); 1918 XML_ParserReset(g_parser, NULL); 1919 } 1920 } 1921 END_TEST 1922 1923 /* See related SF bug #673791. 1924 When namespace processing is enabled, setting the namespace URI for 1925 a prefix is not allowed; this test ensures that it *is* allowed 1926 when namespace processing is not enabled. 1927 (See Namespaces in XML, section 2.) 1928 */ 1929 START_TEST(test_empty_ns_without_namespaces) { 1930 const char *text = "<doc xmlns:prefix='http://example.org/'>\n" 1931 " <e xmlns:prefix=''/>\n" 1932 "</doc>"; 1933 1934 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1935 == XML_STATUS_ERROR) 1936 xml_failure(g_parser); 1937 } 1938 END_TEST 1939 1940 /* Regression test for SF bug #824420. 1941 Checks that an xmlns:prefix attribute set in an attribute's default 1942 value isn't misinterpreted. 1943 */ 1944 START_TEST(test_ns_in_attribute_default_without_namespaces) { 1945 const char *text = "<!DOCTYPE e:element [\n" 1946 " <!ATTLIST e:element\n" 1947 " xmlns:e CDATA 'http://example.org/'>\n" 1948 " ]>\n" 1949 "<e:element/>"; 1950 1951 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 1952 == XML_STATUS_ERROR) 1953 xml_failure(g_parser); 1954 } 1955 END_TEST 1956 1957 static const char *long_character_data_text 1958 = "<?xml version='1.0' encoding='iso-8859-1'?><s>" 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 "012345678901234567890123456789012345678901234567890123456789" 1979 "</s>"; 1980 1981 static XML_Bool resumable = XML_FALSE; 1982 1983 static void 1984 clearing_aborting_character_handler(void *userData, const XML_Char *s, 1985 int len) { 1986 UNUSED_P(userData); 1987 UNUSED_P(s); 1988 UNUSED_P(len); 1989 XML_StopParser(g_parser, resumable); 1990 XML_SetCharacterDataHandler(g_parser, NULL); 1991 } 1992 1993 /* Regression test for SF bug #1515266: missing check of stopped 1994 parser in doContext() 'for' loop. */ 1995 START_TEST(test_stop_parser_between_char_data_calls) { 1996 /* The sample data must be big enough that there are two calls to 1997 the character data handler from within the inner "for" loop of 1998 the XML_TOK_DATA_CHARS case in doContent(), and the character 1999 handler must stop the parser and clear the character data 2000 handler. 2001 */ 2002 const char *text = long_character_data_text; 2003 2004 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2005 resumable = XML_FALSE; 2006 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2007 != XML_STATUS_ERROR) 2008 xml_failure(g_parser); 2009 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED) 2010 xml_failure(g_parser); 2011 } 2012 END_TEST 2013 2014 /* Regression test for SF bug #1515266: missing check of stopped 2015 parser in doContext() 'for' loop. */ 2016 START_TEST(test_suspend_parser_between_char_data_calls) { 2017 /* The sample data must be big enough that there are two calls to 2018 the character data handler from within the inner "for" loop of 2019 the XML_TOK_DATA_CHARS case in doContent(), and the character 2020 handler must stop the parser and clear the character data 2021 handler. 2022 */ 2023 const char *text = long_character_data_text; 2024 2025 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2026 resumable = XML_TRUE; 2027 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2028 != XML_STATUS_SUSPENDED) 2029 xml_failure(g_parser); 2030 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 2031 xml_failure(g_parser); 2032 /* Try parsing directly */ 2033 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 2034 != XML_STATUS_ERROR) 2035 fail("Attempt to continue parse while suspended not faulted"); 2036 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 2037 fail("Suspended parse not faulted with correct error"); 2038 } 2039 END_TEST 2040 2041 static XML_Bool abortable = XML_FALSE; 2042 2043 static void 2044 parser_stop_character_handler(void *userData, const XML_Char *s, int len) { 2045 UNUSED_P(userData); 2046 UNUSED_P(s); 2047 UNUSED_P(len); 2048 XML_StopParser(g_parser, resumable); 2049 XML_SetCharacterDataHandler(g_parser, NULL); 2050 if (! resumable) { 2051 /* Check that aborting an aborted parser is faulted */ 2052 if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR) 2053 fail("Aborting aborted parser not faulted"); 2054 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED) 2055 xml_failure(g_parser); 2056 } else if (abortable) { 2057 /* Check that aborting a suspended parser works */ 2058 if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR) 2059 xml_failure(g_parser); 2060 } else { 2061 /* Check that suspending a suspended parser works */ 2062 if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR) 2063 fail("Suspending suspended parser not faulted"); 2064 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 2065 xml_failure(g_parser); 2066 } 2067 } 2068 2069 /* Test repeated calls to XML_StopParser are handled correctly */ 2070 START_TEST(test_repeated_stop_parser_between_char_data_calls) { 2071 const char *text = long_character_data_text; 2072 2073 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler); 2074 resumable = XML_FALSE; 2075 abortable = XML_FALSE; 2076 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2077 != XML_STATUS_ERROR) 2078 fail("Failed to double-stop parser"); 2079 2080 XML_ParserReset(g_parser, NULL); 2081 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler); 2082 resumable = XML_TRUE; 2083 abortable = XML_FALSE; 2084 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2085 != XML_STATUS_SUSPENDED) 2086 fail("Failed to double-suspend parser"); 2087 2088 XML_ParserReset(g_parser, NULL); 2089 XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler); 2090 resumable = XML_TRUE; 2091 abortable = XML_TRUE; 2092 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2093 != XML_STATUS_ERROR) 2094 fail("Failed to suspend-abort parser"); 2095 } 2096 END_TEST 2097 2098 START_TEST(test_good_cdata_ascii) { 2099 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>"; 2100 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>"); 2101 2102 CharData storage; 2103 CharData_Init(&storage); 2104 XML_SetUserData(g_parser, &storage); 2105 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2106 /* Add start and end handlers for coverage */ 2107 XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler); 2108 XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler); 2109 2110 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2111 == XML_STATUS_ERROR) 2112 xml_failure(g_parser); 2113 CharData_CheckXMLChars(&storage, expected); 2114 2115 /* Try again, this time with a default handler */ 2116 XML_ParserReset(g_parser, NULL); 2117 CharData_Init(&storage); 2118 XML_SetUserData(g_parser, &storage); 2119 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2120 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2121 2122 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2123 == XML_STATUS_ERROR) 2124 xml_failure(g_parser); 2125 CharData_CheckXMLChars(&storage, expected); 2126 } 2127 END_TEST 2128 2129 START_TEST(test_good_cdata_utf16) { 2130 /* Test data is: 2131 * <?xml version='1.0' encoding='utf-16'?> 2132 * <a><![CDATA[hello]]></a> 2133 */ 2134 const char text[] 2135 = "\0<\0?\0x\0m\0l\0" 2136 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2137 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2138 "1\0" 2139 "6\0'" 2140 "\0?\0>\0\n" 2141 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>"; 2142 const XML_Char *expected = XCS("hello"); 2143 2144 CharData storage; 2145 CharData_Init(&storage); 2146 XML_SetUserData(g_parser, &storage); 2147 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2148 2149 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2150 == XML_STATUS_ERROR) 2151 xml_failure(g_parser); 2152 CharData_CheckXMLChars(&storage, expected); 2153 } 2154 END_TEST 2155 2156 START_TEST(test_good_cdata_utf16_le) { 2157 /* Test data is: 2158 * <?xml version='1.0' encoding='utf-16'?> 2159 * <a><![CDATA[hello]]></a> 2160 */ 2161 const char text[] 2162 = "<\0?\0x\0m\0l\0" 2163 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2164 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2165 "1\0" 2166 "6\0'" 2167 "\0?\0>\0\n" 2168 "\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"; 2169 const XML_Char *expected = XCS("hello"); 2170 2171 CharData storage; 2172 CharData_Init(&storage); 2173 XML_SetUserData(g_parser, &storage); 2174 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2175 2176 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2177 == XML_STATUS_ERROR) 2178 xml_failure(g_parser); 2179 CharData_CheckXMLChars(&storage, expected); 2180 } 2181 END_TEST 2182 2183 /* Test UTF16 conversion of a long cdata string */ 2184 2185 /* 16 characters: handy macro to reduce visual clutter */ 2186 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P" 2187 2188 START_TEST(test_long_cdata_utf16) { 2189 /* Test data is: 2190 * <?xlm version='1.0' encoding='utf-16'?> 2191 * <a><![CDATA[ 2192 * ABCDEFGHIJKLMNOP 2193 * ]]></a> 2194 */ 2195 const char text[] 2196 = "\0<\0?\0x\0m\0l\0 " 2197 "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 " 2198 "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>" 2199 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[" 2200 /* 64 characters per line */ 2201 /* clang-format off */ 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 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 A_TO_P_IN_UTF16 2218 A_TO_P_IN_UTF16 2219 /* clang-format on */ 2220 "\0]\0]\0>\0<\0/\0a\0>"; 2221 const XML_Char *expected = 2222 /* clang-format off */ 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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP") 2239 XCS("ABCDEFGHIJKLMNOP"); 2240 /* clang-format on */ 2241 CharData storage; 2242 void *buffer; 2243 2244 CharData_Init(&storage); 2245 XML_SetUserData(g_parser, &storage); 2246 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2247 buffer = XML_GetBuffer(g_parser, sizeof(text) - 1); 2248 if (buffer == NULL) 2249 fail("Could not allocate parse buffer"); 2250 assert(buffer != NULL); 2251 memcpy(buffer, text, sizeof(text) - 1); 2252 if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR) 2253 xml_failure(g_parser); 2254 CharData_CheckXMLChars(&storage, expected); 2255 } 2256 END_TEST 2257 2258 /* Test handling of multiple unit UTF-16 characters */ 2259 START_TEST(test_multichar_cdata_utf16) { 2260 /* Test data is: 2261 * <?xml version='1.0' encoding='utf-16'?> 2262 * <a><![CDATA[{MINIM}{CROTCHET}]]></a> 2263 * 2264 * where {MINIM} is U+1d15e (a minim or half-note) 2265 * UTF-16: 0xd834 0xdd5e 2266 * UTF-8: 0xf0 0x9d 0x85 0x9e 2267 * and {CROTCHET} is U+1d15f (a crotchet or quarter-note) 2268 * UTF-16: 0xd834 0xdd5f 2269 * UTF-8: 0xf0 0x9d 0x85 0x9f 2270 */ 2271 const char text[] = "\0<\0?\0x\0m\0l\0" 2272 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2273 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2274 "1\0" 2275 "6\0'" 2276 "\0?\0>\0\n" 2277 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[" 2278 "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f" 2279 "\0]\0]\0>\0<\0/\0a\0>"; 2280 #ifdef XML_UNICODE 2281 const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f"); 2282 #else 2283 const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f"); 2284 #endif 2285 CharData storage; 2286 2287 CharData_Init(&storage); 2288 XML_SetUserData(g_parser, &storage); 2289 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 2290 2291 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2292 == XML_STATUS_ERROR) 2293 xml_failure(g_parser); 2294 CharData_CheckXMLChars(&storage, expected); 2295 } 2296 END_TEST 2297 2298 /* Test that an element name with a UTF-16 surrogate pair is rejected */ 2299 START_TEST(test_utf16_bad_surrogate_pair) { 2300 /* Test data is: 2301 * <?xml version='1.0' encoding='utf-16'?> 2302 * <a><![CDATA[{BADLINB}]]></a> 2303 * 2304 * where {BADLINB} is U+10000 (the first Linear B character) 2305 * with the UTF-16 surrogate pair in the wrong order, i.e. 2306 * 0xdc00 0xd800 2307 */ 2308 const char text[] = "\0<\0?\0x\0m\0l\0" 2309 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2310 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2311 "1\0" 2312 "6\0'" 2313 "\0?\0>\0\n" 2314 "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[" 2315 "\xdc\x00\xd8\x00" 2316 "\0]\0]\0>\0<\0/\0a\0>"; 2317 2318 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 2319 != XML_STATUS_ERROR) 2320 fail("Reversed UTF-16 surrogate pair not faulted"); 2321 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 2322 xml_failure(g_parser); 2323 } 2324 END_TEST 2325 2326 START_TEST(test_bad_cdata) { 2327 struct CaseData { 2328 const char *text; 2329 enum XML_Error expectedError; 2330 }; 2331 2332 struct CaseData cases[] 2333 = {{"<a><", XML_ERROR_UNCLOSED_TOKEN}, 2334 {"<a><!", XML_ERROR_UNCLOSED_TOKEN}, 2335 {"<a><![", XML_ERROR_UNCLOSED_TOKEN}, 2336 {"<a><![C", XML_ERROR_UNCLOSED_TOKEN}, 2337 {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN}, 2338 {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN}, 2339 {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN}, 2340 {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN}, 2341 2342 {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2343 {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2344 {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2345 2346 {"<a><!<a/>", XML_ERROR_INVALID_TOKEN}, 2347 {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */ 2348 {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */ 2349 {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN}, 2350 {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN}, 2351 {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN}, 2352 {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN}, 2353 2354 {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2355 {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2356 {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}}; 2357 2358 size_t i = 0; 2359 for (; i < sizeof(cases) / sizeof(struct CaseData); i++) { 2360 const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES( 2361 g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE); 2362 const enum XML_Error actualError = XML_GetErrorCode(g_parser); 2363 2364 assert(actualStatus == XML_STATUS_ERROR); 2365 2366 if (actualError != cases[i].expectedError) { 2367 char message[100]; 2368 sprintf(message, 2369 "Expected error %d but got error %d for case %u: \"%s\"\n", 2370 cases[i].expectedError, actualError, (unsigned int)i + 1, 2371 cases[i].text); 2372 fail(message); 2373 } 2374 2375 XML_ParserReset(g_parser, NULL); 2376 } 2377 } 2378 END_TEST 2379 2380 /* Test failures in UTF-16 CDATA */ 2381 START_TEST(test_bad_cdata_utf16) { 2382 struct CaseData { 2383 size_t text_bytes; 2384 const char *text; 2385 enum XML_Error expected_error; 2386 }; 2387 2388 const char prolog[] = "\0<\0?\0x\0m\0l\0" 2389 " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0" 2390 " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0" 2391 "1\0" 2392 "6\0'" 2393 "\0?\0>\0\n" 2394 "\0<\0a\0>"; 2395 struct CaseData cases[] = { 2396 {1, "\0", XML_ERROR_UNCLOSED_TOKEN}, 2397 {2, "\0<", XML_ERROR_UNCLOSED_TOKEN}, 2398 {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN}, 2399 {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN}, 2400 {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN}, 2401 {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN}, 2402 {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN}, 2403 {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN}, 2404 {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN}, 2405 {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN}, 2406 {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN}, 2407 {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN}, 2408 {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN}, 2409 {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN}, 2410 {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN}, 2411 {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN}, 2412 {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN}, 2413 {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2414 {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2415 {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION}, 2416 /* Now add a four-byte UTF-16 character */ 2417 {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8", 2418 XML_ERROR_UNCLOSED_CDATA_SECTION}, 2419 {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR}, 2420 {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd", 2421 XML_ERROR_PARTIAL_CHAR}, 2422 {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e", 2423 XML_ERROR_UNCLOSED_CDATA_SECTION}}; 2424 size_t i; 2425 2426 for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) { 2427 enum XML_Status actual_status; 2428 enum XML_Error actual_error; 2429 2430 if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1, 2431 XML_FALSE) 2432 == XML_STATUS_ERROR) 2433 xml_failure(g_parser); 2434 actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text, 2435 (int)cases[i].text_bytes, XML_TRUE); 2436 assert(actual_status == XML_STATUS_ERROR); 2437 actual_error = XML_GetErrorCode(g_parser); 2438 if (actual_error != cases[i].expected_error) { 2439 char message[1024]; 2440 2441 sprintf(message, 2442 "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR 2443 ") for case %lu\n", 2444 cases[i].expected_error, XML_ErrorString(cases[i].expected_error), 2445 actual_error, XML_ErrorString(actual_error), 2446 (long unsigned)(i + 1)); 2447 fail(message); 2448 } 2449 XML_ParserReset(g_parser, NULL); 2450 } 2451 } 2452 END_TEST 2453 2454 static const char *long_cdata_text 2455 = "<s><![CDATA[" 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 "012345678901234567890123456789012345678901234567890123456789" 2476 "]]></s>"; 2477 2478 /* Test stopping the parser in cdata handler */ 2479 START_TEST(test_stop_parser_between_cdata_calls) { 2480 const char *text = long_cdata_text; 2481 2482 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2483 resumable = XML_FALSE; 2484 expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler"); 2485 } 2486 END_TEST 2487 2488 /* Test suspending the parser in cdata handler */ 2489 START_TEST(test_suspend_parser_between_cdata_calls) { 2490 const char *text = long_cdata_text; 2491 enum XML_Status result; 2492 2493 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2494 resumable = XML_TRUE; 2495 result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 2496 if (result != XML_STATUS_SUSPENDED) { 2497 if (result == XML_STATUS_ERROR) 2498 xml_failure(g_parser); 2499 fail("Parse not suspended in CDATA handler"); 2500 } 2501 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 2502 xml_failure(g_parser); 2503 } 2504 END_TEST 2505 2506 /* Test memory allocation functions */ 2507 START_TEST(test_memory_allocation) { 2508 char *buffer = (char *)XML_MemMalloc(g_parser, 256); 2509 char *p; 2510 2511 if (buffer == NULL) { 2512 fail("Allocation failed"); 2513 } else { 2514 /* Try writing to memory; some OSes try to cheat! */ 2515 buffer[0] = 'T'; 2516 buffer[1] = 'E'; 2517 buffer[2] = 'S'; 2518 buffer[3] = 'T'; 2519 buffer[4] = '\0'; 2520 if (strcmp(buffer, "TEST") != 0) { 2521 fail("Memory not writable"); 2522 } else { 2523 p = (char *)XML_MemRealloc(g_parser, buffer, 512); 2524 if (p == NULL) { 2525 fail("Reallocation failed"); 2526 } else { 2527 /* Write again, just to be sure */ 2528 buffer = p; 2529 buffer[0] = 'V'; 2530 if (strcmp(buffer, "VEST") != 0) { 2531 fail("Reallocated memory not writable"); 2532 } 2533 } 2534 } 2535 XML_MemFree(g_parser, buffer); 2536 } 2537 } 2538 END_TEST 2539 2540 static void XMLCALL 2541 record_default_handler(void *userData, const XML_Char *s, int len) { 2542 UNUSED_P(s); 2543 UNUSED_P(len); 2544 CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1); 2545 } 2546 2547 static void XMLCALL 2548 record_cdata_handler(void *userData, const XML_Char *s, int len) { 2549 UNUSED_P(s); 2550 UNUSED_P(len); 2551 CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1); 2552 XML_DefaultCurrent(g_parser); 2553 } 2554 2555 static void XMLCALL 2556 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) { 2557 UNUSED_P(s); 2558 UNUSED_P(len); 2559 CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1); 2560 } 2561 2562 static void XMLCALL 2563 record_skip_handler(void *userData, const XML_Char *entityName, 2564 int is_parameter_entity) { 2565 UNUSED_P(entityName); 2566 CharData_AppendXMLChars((CharData *)userData, 2567 is_parameter_entity ? XCS("E") : XCS("e"), 1); 2568 } 2569 2570 /* Test XML_DefaultCurrent() passes handling on correctly */ 2571 START_TEST(test_default_current) { 2572 const char *text = "<doc>hell]</doc>"; 2573 const char *entity_text = "<!DOCTYPE doc [\n" 2574 "<!ENTITY entity '%'>\n" 2575 "]>\n" 2576 "<doc>&entity;</doc>"; 2577 CharData storage; 2578 2579 XML_SetDefaultHandler(g_parser, record_default_handler); 2580 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2581 CharData_Init(&storage); 2582 XML_SetUserData(g_parser, &storage); 2583 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2584 == XML_STATUS_ERROR) 2585 xml_failure(g_parser); 2586 CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD")); 2587 2588 /* Again, without the defaulting */ 2589 XML_ParserReset(g_parser, NULL); 2590 XML_SetDefaultHandler(g_parser, record_default_handler); 2591 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler); 2592 CharData_Init(&storage); 2593 XML_SetUserData(g_parser, &storage); 2594 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2595 == XML_STATUS_ERROR) 2596 xml_failure(g_parser); 2597 CharData_CheckXMLChars(&storage, XCS("DcccccD")); 2598 2599 /* Now with an internal entity to complicate matters */ 2600 XML_ParserReset(g_parser, NULL); 2601 XML_SetDefaultHandler(g_parser, record_default_handler); 2602 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2603 CharData_Init(&storage); 2604 XML_SetUserData(g_parser, &storage); 2605 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2606 XML_TRUE) 2607 == XML_STATUS_ERROR) 2608 xml_failure(g_parser); 2609 /* The default handler suppresses the entity */ 2610 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD")); 2611 2612 /* Again, with a skip handler */ 2613 XML_ParserReset(g_parser, NULL); 2614 XML_SetDefaultHandler(g_parser, record_default_handler); 2615 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2616 XML_SetSkippedEntityHandler(g_parser, record_skip_handler); 2617 CharData_Init(&storage); 2618 XML_SetUserData(g_parser, &storage); 2619 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2620 XML_TRUE) 2621 == XML_STATUS_ERROR) 2622 xml_failure(g_parser); 2623 /* The default handler suppresses the entity */ 2624 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD")); 2625 2626 /* This time, allow the entity through */ 2627 XML_ParserReset(g_parser, NULL); 2628 XML_SetDefaultHandlerExpand(g_parser, record_default_handler); 2629 XML_SetCharacterDataHandler(g_parser, record_cdata_handler); 2630 CharData_Init(&storage); 2631 XML_SetUserData(g_parser, &storage); 2632 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2633 XML_TRUE) 2634 == XML_STATUS_ERROR) 2635 xml_failure(g_parser); 2636 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD")); 2637 2638 /* Finally, without passing the cdata to the default handler */ 2639 XML_ParserReset(g_parser, NULL); 2640 XML_SetDefaultHandlerExpand(g_parser, record_default_handler); 2641 XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler); 2642 CharData_Init(&storage); 2643 XML_SetUserData(g_parser, &storage); 2644 if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text), 2645 XML_TRUE) 2646 == XML_STATUS_ERROR) 2647 xml_failure(g_parser); 2648 CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD")); 2649 } 2650 END_TEST 2651 2652 /* Test DTD element parsing code paths */ 2653 START_TEST(test_dtd_elements) { 2654 const char *text = "<!DOCTYPE doc [\n" 2655 "<!ELEMENT doc (chapter)>\n" 2656 "<!ELEMENT chapter (#PCDATA)>\n" 2657 "]>\n" 2658 "<doc><chapter>Wombats are go</chapter></doc>"; 2659 2660 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 2661 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2662 == XML_STATUS_ERROR) 2663 xml_failure(g_parser); 2664 } 2665 END_TEST 2666 2667 /* Test foreign DTD handling */ 2668 START_TEST(test_set_foreign_dtd) { 2669 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"; 2670 const char *text2 = "<doc>&entity;</doc>"; 2671 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2672 2673 /* Check hash salt is passed through too */ 2674 XML_SetHashSalt(g_parser, 0x12345678); 2675 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2676 XML_SetUserData(g_parser, &test_data); 2677 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2678 /* Add a default handler to exercise more code paths */ 2679 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2680 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2681 fail("Could not set foreign DTD"); 2682 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 2683 == XML_STATUS_ERROR) 2684 xml_failure(g_parser); 2685 2686 /* Ensure that trying to set the DTD after parsing has started 2687 * is faulted, even if it's the same setting. 2688 */ 2689 if (XML_UseForeignDTD(g_parser, XML_TRUE) 2690 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING) 2691 fail("Failed to reject late foreign DTD setting"); 2692 /* Ditto for the hash salt */ 2693 if (XML_SetHashSalt(g_parser, 0x23456789)) 2694 fail("Failed to reject late hash salt change"); 2695 2696 /* Now finish the parse */ 2697 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 2698 == XML_STATUS_ERROR) 2699 xml_failure(g_parser); 2700 } 2701 END_TEST 2702 2703 /* Test foreign DTD handling with a failing NotStandalone handler */ 2704 START_TEST(test_foreign_dtd_not_standalone) { 2705 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2706 "<doc>&entity;</doc>"; 2707 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2708 2709 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2710 XML_SetUserData(g_parser, &test_data); 2711 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2712 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler); 2713 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2714 fail("Could not set foreign DTD"); 2715 expect_failure(text, XML_ERROR_NOT_STANDALONE, 2716 "NotStandalonehandler failed to reject"); 2717 } 2718 END_TEST 2719 2720 /* Test invalid character in a foreign DTD is faulted */ 2721 START_TEST(test_invalid_foreign_dtd) { 2722 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2723 "<doc>&entity;</doc>"; 2724 ExtFaults test_data 2725 = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN}; 2726 2727 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2728 XML_SetUserData(g_parser, &test_data); 2729 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 2730 XML_UseForeignDTD(g_parser, XML_TRUE); 2731 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 2732 "Bad DTD should not have been accepted"); 2733 } 2734 END_TEST 2735 2736 /* Test foreign DTD use with a doctype */ 2737 START_TEST(test_foreign_dtd_with_doctype) { 2738 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 2739 "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n"; 2740 const char *text2 = "<doc>&entity;</doc>"; 2741 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2742 2743 /* Check hash salt is passed through too */ 2744 XML_SetHashSalt(g_parser, 0x12345678); 2745 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2746 XML_SetUserData(g_parser, &test_data); 2747 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2748 /* Add a default handler to exercise more code paths */ 2749 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2750 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2751 fail("Could not set foreign DTD"); 2752 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 2753 == XML_STATUS_ERROR) 2754 xml_failure(g_parser); 2755 2756 /* Ensure that trying to set the DTD after parsing has started 2757 * is faulted, even if it's the same setting. 2758 */ 2759 if (XML_UseForeignDTD(g_parser, XML_TRUE) 2760 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING) 2761 fail("Failed to reject late foreign DTD setting"); 2762 /* Ditto for the hash salt */ 2763 if (XML_SetHashSalt(g_parser, 0x23456789)) 2764 fail("Failed to reject late hash salt change"); 2765 2766 /* Now finish the parse */ 2767 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 2768 == XML_STATUS_ERROR) 2769 xml_failure(g_parser); 2770 } 2771 END_TEST 2772 2773 /* Test XML_UseForeignDTD with no external subset present */ 2774 static int XMLCALL 2775 external_entity_null_loader(XML_Parser parser, const XML_Char *context, 2776 const XML_Char *base, const XML_Char *systemId, 2777 const XML_Char *publicId) { 2778 UNUSED_P(parser); 2779 UNUSED_P(context); 2780 UNUSED_P(base); 2781 UNUSED_P(systemId); 2782 UNUSED_P(publicId); 2783 return XML_STATUS_OK; 2784 } 2785 2786 START_TEST(test_foreign_dtd_without_external_subset) { 2787 const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n" 2788 "<doc>&foo;</doc>"; 2789 2790 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2791 XML_SetUserData(g_parser, NULL); 2792 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 2793 XML_UseForeignDTD(g_parser, XML_TRUE); 2794 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2795 == XML_STATUS_ERROR) 2796 xml_failure(g_parser); 2797 } 2798 END_TEST 2799 2800 START_TEST(test_empty_foreign_dtd) { 2801 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2802 "<doc>&entity;</doc>"; 2803 2804 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2805 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 2806 XML_UseForeignDTD(g_parser, XML_TRUE); 2807 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 2808 "Undefined entity not faulted"); 2809 } 2810 END_TEST 2811 2812 /* Test XML Base is set and unset appropriately */ 2813 START_TEST(test_set_base) { 2814 const XML_Char *old_base; 2815 const XML_Char *new_base = XCS("/local/file/name.xml"); 2816 2817 old_base = XML_GetBase(g_parser); 2818 if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK) 2819 fail("Unable to set base"); 2820 if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0) 2821 fail("Base setting not correct"); 2822 if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK) 2823 fail("Unable to NULL base"); 2824 if (XML_GetBase(g_parser) != NULL) 2825 fail("Base setting not nulled"); 2826 XML_SetBase(g_parser, old_base); 2827 } 2828 END_TEST 2829 2830 /* Test attribute counts, indexing, etc */ 2831 typedef struct attrInfo { 2832 const XML_Char *name; 2833 const XML_Char *value; 2834 } AttrInfo; 2835 2836 typedef struct elementInfo { 2837 const XML_Char *name; 2838 int attr_count; 2839 const XML_Char *id_name; 2840 AttrInfo *attributes; 2841 } ElementInfo; 2842 2843 static void XMLCALL 2844 counting_start_element_handler(void *userData, const XML_Char *name, 2845 const XML_Char **atts) { 2846 ElementInfo *info = (ElementInfo *)userData; 2847 AttrInfo *attr; 2848 int count, id, i; 2849 2850 while (info->name != NULL) { 2851 if (! xcstrcmp(name, info->name)) 2852 break; 2853 info++; 2854 } 2855 if (info->name == NULL) 2856 fail("Element not recognised"); 2857 /* The attribute count is twice what you might expect. It is a 2858 * count of items in atts, an array which contains alternating 2859 * attribute names and attribute values. For the naive user this 2860 * is possibly a little unexpected, but it is what the 2861 * documentation in expat.h tells us to expect. 2862 */ 2863 count = XML_GetSpecifiedAttributeCount(g_parser); 2864 if (info->attr_count * 2 != count) { 2865 fail("Not got expected attribute count"); 2866 return; 2867 } 2868 id = XML_GetIdAttributeIndex(g_parser); 2869 if (id == -1 && info->id_name != NULL) { 2870 fail("ID not present"); 2871 return; 2872 } 2873 if (id != -1 && xcstrcmp(atts[id], info->id_name)) { 2874 fail("ID does not have the correct name"); 2875 return; 2876 } 2877 for (i = 0; i < info->attr_count; i++) { 2878 attr = info->attributes; 2879 while (attr->name != NULL) { 2880 if (! xcstrcmp(atts[0], attr->name)) 2881 break; 2882 attr++; 2883 } 2884 if (attr->name == NULL) { 2885 fail("Attribute not recognised"); 2886 return; 2887 } 2888 if (xcstrcmp(atts[1], attr->value)) { 2889 fail("Attribute has wrong value"); 2890 return; 2891 } 2892 /* Remember, two entries in atts per attribute (see above) */ 2893 atts += 2; 2894 } 2895 } 2896 2897 START_TEST(test_attributes) { 2898 const char *text = "<!DOCTYPE doc [\n" 2899 "<!ELEMENT doc (tag)>\n" 2900 "<!ATTLIST doc id ID #REQUIRED>\n" 2901 "]>" 2902 "<doc a='1' id='one' b='2'>" 2903 "<tag c='3'/>" 2904 "</doc>"; 2905 AttrInfo doc_info[] = {{XCS("a"), XCS("1")}, 2906 {XCS("b"), XCS("2")}, 2907 {XCS("id"), XCS("one")}, 2908 {NULL, NULL}}; 2909 AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}}; 2910 ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL}, 2911 {XCS("tag"), 1, NULL, NULL}, 2912 {NULL, 0, NULL, NULL}}; 2913 info[0].attributes = doc_info; 2914 info[1].attributes = tag_info; 2915 2916 XML_SetStartElementHandler(g_parser, counting_start_element_handler); 2917 XML_SetUserData(g_parser, info); 2918 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2919 == XML_STATUS_ERROR) 2920 xml_failure(g_parser); 2921 } 2922 END_TEST 2923 2924 /* Test reset works correctly in the middle of processing an internal 2925 * entity. Exercises some obscure code in XML_ParserReset(). 2926 */ 2927 START_TEST(test_reset_in_entity) { 2928 const char *text = "<!DOCTYPE doc [\n" 2929 "<!ENTITY wombat 'wom'>\n" 2930 "<!ENTITY entity 'hi &wom; there'>\n" 2931 "]>\n" 2932 "<doc>&entity;</doc>"; 2933 XML_ParsingStatus status; 2934 2935 resumable = XML_TRUE; 2936 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2937 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 2938 == XML_STATUS_ERROR) 2939 xml_failure(g_parser); 2940 XML_GetParsingStatus(g_parser, &status); 2941 if (status.parsing != XML_SUSPENDED) 2942 fail("Parsing status not SUSPENDED"); 2943 XML_ParserReset(g_parser, NULL); 2944 XML_GetParsingStatus(g_parser, &status); 2945 if (status.parsing != XML_INITIALIZED) 2946 fail("Parsing status doesn't reset to INITIALIZED"); 2947 } 2948 END_TEST 2949 2950 /* Test that resume correctly passes through parse errors */ 2951 START_TEST(test_resume_invalid_parse) { 2952 const char *text = "<doc>Hello</doc"; /* Missing closing wedge */ 2953 2954 resumable = XML_TRUE; 2955 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2956 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 2957 == XML_STATUS_ERROR) 2958 xml_failure(g_parser); 2959 if (XML_ResumeParser(g_parser) == XML_STATUS_OK) 2960 fail("Resumed invalid parse not faulted"); 2961 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN) 2962 fail("Invalid parse not correctly faulted"); 2963 } 2964 END_TEST 2965 2966 /* Test that re-suspended parses are correctly passed through */ 2967 START_TEST(test_resume_resuspended) { 2968 const char *text = "<doc>Hello<meep/>world</doc>"; 2969 2970 resumable = XML_TRUE; 2971 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2972 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 2973 == XML_STATUS_ERROR) 2974 xml_failure(g_parser); 2975 resumable = XML_TRUE; 2976 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 2977 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED) 2978 fail("Resumption not suspended"); 2979 /* This one should succeed and finish up */ 2980 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 2981 xml_failure(g_parser); 2982 } 2983 END_TEST 2984 2985 /* Test that CDATA shows up correctly through a default handler */ 2986 START_TEST(test_cdata_default) { 2987 const char *text = "<doc><![CDATA[Hello\nworld]]></doc>"; 2988 const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>"); 2989 CharData storage; 2990 2991 CharData_Init(&storage); 2992 XML_SetUserData(g_parser, &storage); 2993 XML_SetDefaultHandler(g_parser, accumulate_characters); 2994 2995 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2996 == XML_STATUS_ERROR) 2997 xml_failure(g_parser); 2998 CharData_CheckXMLChars(&storage, expected); 2999 } 3000 END_TEST 3001 3002 /* Test resetting a subordinate parser does exactly nothing */ 3003 static int XMLCALL 3004 external_entity_resetter(XML_Parser parser, const XML_Char *context, 3005 const XML_Char *base, const XML_Char *systemId, 3006 const XML_Char *publicId) { 3007 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3008 XML_Parser ext_parser; 3009 XML_ParsingStatus status; 3010 3011 UNUSED_P(base); 3012 UNUSED_P(systemId); 3013 UNUSED_P(publicId); 3014 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3015 if (ext_parser == NULL) 3016 fail("Could not create external entity parser"); 3017 XML_GetParsingStatus(ext_parser, &status); 3018 if (status.parsing != XML_INITIALIZED) { 3019 fail("Parsing status is not INITIALIZED"); 3020 return XML_STATUS_ERROR; 3021 } 3022 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3023 == XML_STATUS_ERROR) { 3024 xml_failure(parser); 3025 return XML_STATUS_ERROR; 3026 } 3027 XML_GetParsingStatus(ext_parser, &status); 3028 if (status.parsing != XML_FINISHED) { 3029 fail("Parsing status is not FINISHED"); 3030 return XML_STATUS_ERROR; 3031 } 3032 /* Check we can't parse here */ 3033 if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE) 3034 != XML_STATUS_ERROR) 3035 fail("Parsing when finished not faulted"); 3036 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED) 3037 fail("Parsing when finished faulted with wrong code"); 3038 XML_ParserReset(ext_parser, NULL); 3039 XML_GetParsingStatus(ext_parser, &status); 3040 if (status.parsing != XML_FINISHED) { 3041 fail("Parsing status not still FINISHED"); 3042 return XML_STATUS_ERROR; 3043 } 3044 XML_ParserFree(ext_parser); 3045 return XML_STATUS_OK; 3046 } 3047 3048 START_TEST(test_subordinate_reset) { 3049 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3050 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3051 "<doc>&entity;</doc>"; 3052 3053 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3054 XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter); 3055 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3056 == XML_STATUS_ERROR) 3057 xml_failure(g_parser); 3058 } 3059 END_TEST 3060 3061 /* Test suspending a subordinate parser */ 3062 3063 static void XMLCALL 3064 entity_suspending_decl_handler(void *userData, const XML_Char *name, 3065 XML_Content *model) { 3066 XML_Parser ext_parser = (XML_Parser)userData; 3067 3068 UNUSED_P(name); 3069 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR) 3070 fail("Attempting to suspend a subordinate parser not faulted"); 3071 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE) 3072 fail("Suspending subordinate parser get wrong code"); 3073 XML_SetElementDeclHandler(ext_parser, NULL); 3074 XML_FreeContentModel(g_parser, model); 3075 } 3076 3077 static int XMLCALL 3078 external_entity_suspender(XML_Parser parser, const XML_Char *context, 3079 const XML_Char *base, const XML_Char *systemId, 3080 const XML_Char *publicId) { 3081 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3082 XML_Parser ext_parser; 3083 3084 UNUSED_P(base); 3085 UNUSED_P(systemId); 3086 UNUSED_P(publicId); 3087 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3088 if (ext_parser == NULL) 3089 fail("Could not create external entity parser"); 3090 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler); 3091 XML_SetUserData(ext_parser, ext_parser); 3092 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3093 == XML_STATUS_ERROR) { 3094 xml_failure(ext_parser); 3095 return XML_STATUS_ERROR; 3096 } 3097 XML_ParserFree(ext_parser); 3098 return XML_STATUS_OK; 3099 } 3100 3101 START_TEST(test_subordinate_suspend) { 3102 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3103 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3104 "<doc>&entity;</doc>"; 3105 3106 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3107 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender); 3108 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3109 == XML_STATUS_ERROR) 3110 xml_failure(g_parser); 3111 } 3112 END_TEST 3113 3114 /* Test suspending a subordinate parser from an XML declaration */ 3115 /* Increases code coverage of the tests */ 3116 static void XMLCALL 3117 entity_suspending_xdecl_handler(void *userData, const XML_Char *version, 3118 const XML_Char *encoding, int standalone) { 3119 XML_Parser ext_parser = (XML_Parser)userData; 3120 3121 UNUSED_P(version); 3122 UNUSED_P(encoding); 3123 UNUSED_P(standalone); 3124 XML_StopParser(ext_parser, resumable); 3125 XML_SetXmlDeclHandler(ext_parser, NULL); 3126 } 3127 3128 static int XMLCALL 3129 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context, 3130 const XML_Char *base, const XML_Char *systemId, 3131 const XML_Char *publicId) { 3132 const char *text = "<?xml version='1.0' encoding='us-ascii'?>"; 3133 XML_Parser ext_parser; 3134 XML_ParsingStatus status; 3135 enum XML_Status rc; 3136 3137 UNUSED_P(base); 3138 UNUSED_P(systemId); 3139 UNUSED_P(publicId); 3140 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3141 if (ext_parser == NULL) 3142 fail("Could not create external entity parser"); 3143 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 3144 XML_SetUserData(ext_parser, ext_parser); 3145 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 3146 XML_GetParsingStatus(ext_parser, &status); 3147 if (resumable) { 3148 if (rc == XML_STATUS_ERROR) 3149 xml_failure(ext_parser); 3150 if (status.parsing != XML_SUSPENDED) 3151 fail("Ext Parsing status not SUSPENDED"); 3152 } else { 3153 if (rc != XML_STATUS_ERROR) 3154 fail("Ext parsing not aborted"); 3155 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED) 3156 xml_failure(ext_parser); 3157 if (status.parsing != XML_FINISHED) 3158 fail("Ext Parsing status not FINISHED"); 3159 } 3160 3161 XML_ParserFree(ext_parser); 3162 return XML_STATUS_OK; 3163 } 3164 3165 START_TEST(test_subordinate_xdecl_suspend) { 3166 const char *text 3167 = "<!DOCTYPE doc [\n" 3168 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n" 3169 "]>\n" 3170 "<doc>&entity;</doc>"; 3171 3172 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3173 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl); 3174 resumable = XML_TRUE; 3175 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3176 == XML_STATUS_ERROR) 3177 xml_failure(g_parser); 3178 } 3179 END_TEST 3180 3181 START_TEST(test_subordinate_xdecl_abort) { 3182 const char *text 3183 = "<!DOCTYPE doc [\n" 3184 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n" 3185 "]>\n" 3186 "<doc>&entity;</doc>"; 3187 3188 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3189 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl); 3190 resumable = XML_FALSE; 3191 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3192 == XML_STATUS_ERROR) 3193 xml_failure(g_parser); 3194 } 3195 END_TEST 3196 3197 /* Test external entity fault handling with suspension */ 3198 static int XMLCALL 3199 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context, 3200 const XML_Char *base, 3201 const XML_Char *systemId, 3202 const XML_Char *publicId) { 3203 XML_Parser ext_parser; 3204 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 3205 void *buffer; 3206 int parse_len = (int)strlen(fault->parse_text); 3207 3208 UNUSED_P(base); 3209 UNUSED_P(systemId); 3210 UNUSED_P(publicId); 3211 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3212 if (ext_parser == NULL) 3213 fail("Could not create external entity parser"); 3214 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 3215 XML_SetUserData(ext_parser, ext_parser); 3216 resumable = XML_TRUE; 3217 buffer = XML_GetBuffer(ext_parser, parse_len); 3218 if (buffer == NULL) 3219 fail("Could not allocate parse buffer"); 3220 assert(buffer != NULL); 3221 memcpy(buffer, fault->parse_text, parse_len); 3222 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED) 3223 fail("XML declaration did not suspend"); 3224 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK) 3225 xml_failure(ext_parser); 3226 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR) 3227 fail(fault->fail_text); 3228 if (XML_GetErrorCode(ext_parser) != fault->error) 3229 xml_failure(ext_parser); 3230 3231 XML_ParserFree(ext_parser); 3232 return XML_STATUS_ERROR; 3233 } 3234 3235 START_TEST(test_ext_entity_invalid_suspended_parse) { 3236 const char *text = "<!DOCTYPE doc [\n" 3237 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3238 "]>\n" 3239 "<doc>&en;</doc>"; 3240 ExtFaults faults[] 3241 = {{"<?xml version='1.0' encoding='us-ascii'?><", 3242 "Incomplete element declaration not faulted", NULL, 3243 XML_ERROR_UNCLOSED_TOKEN}, 3244 {/* First two bytes of a three-byte char */ 3245 "<?xml version='1.0' encoding='utf-8'?>\xe2\x82", 3246 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR}, 3247 {NULL, NULL, NULL, XML_ERROR_NONE}}; 3248 ExtFaults *fault; 3249 3250 for (fault = &faults[0]; fault->parse_text != NULL; fault++) { 3251 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3252 XML_SetExternalEntityRefHandler(g_parser, 3253 external_entity_suspending_faulter); 3254 XML_SetUserData(g_parser, fault); 3255 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 3256 "Parser did not report external entity error"); 3257 XML_ParserReset(g_parser, NULL); 3258 } 3259 } 3260 END_TEST 3261 3262 /* Test setting an explicit encoding */ 3263 START_TEST(test_explicit_encoding) { 3264 const char *text1 = "<doc>Hello "; 3265 const char *text2 = " World</doc>"; 3266 3267 /* Just check that we can set the encoding to NULL before starting */ 3268 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK) 3269 fail("Failed to initialise encoding to NULL"); 3270 /* Say we are UTF-8 */ 3271 if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK) 3272 fail("Failed to set explicit encoding"); 3273 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 3274 == XML_STATUS_ERROR) 3275 xml_failure(g_parser); 3276 /* Try to switch encodings mid-parse */ 3277 if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR) 3278 fail("Allowed encoding change"); 3279 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 3280 == XML_STATUS_ERROR) 3281 xml_failure(g_parser); 3282 /* Try now the parse is over */ 3283 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK) 3284 fail("Failed to unset encoding"); 3285 } 3286 END_TEST 3287 3288 /* Test handling of trailing CR (rather than newline) */ 3289 static void XMLCALL 3290 cr_cdata_handler(void *userData, const XML_Char *s, int len) { 3291 int *pfound = (int *)userData; 3292 3293 /* Internal processing turns the CR into a newline for the 3294 * character data handler, but not for the default handler 3295 */ 3296 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r'))) 3297 *pfound = 1; 3298 } 3299 3300 START_TEST(test_trailing_cr) { 3301 const char *text = "<doc>\r"; 3302 int found_cr; 3303 3304 /* Try with a character handler, for code coverage */ 3305 XML_SetCharacterDataHandler(g_parser, cr_cdata_handler); 3306 XML_SetUserData(g_parser, &found_cr); 3307 found_cr = 0; 3308 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3309 == XML_STATUS_OK) 3310 fail("Failed to fault unclosed doc"); 3311 if (found_cr == 0) 3312 fail("Did not catch the carriage return"); 3313 XML_ParserReset(g_parser, NULL); 3314 3315 /* Now with a default handler instead */ 3316 XML_SetDefaultHandler(g_parser, cr_cdata_handler); 3317 XML_SetUserData(g_parser, &found_cr); 3318 found_cr = 0; 3319 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3320 == XML_STATUS_OK) 3321 fail("Failed to fault unclosed doc"); 3322 if (found_cr == 0) 3323 fail("Did not catch default carriage return"); 3324 } 3325 END_TEST 3326 3327 /* Test trailing CR in an external entity parse */ 3328 static int XMLCALL 3329 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context, 3330 const XML_Char *base, const XML_Char *systemId, 3331 const XML_Char *publicId) { 3332 const char *text = "\r"; 3333 XML_Parser ext_parser; 3334 3335 UNUSED_P(base); 3336 UNUSED_P(systemId); 3337 UNUSED_P(publicId); 3338 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3339 if (ext_parser == NULL) 3340 fail("Could not create external entity parser"); 3341 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler); 3342 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3343 == XML_STATUS_ERROR) 3344 xml_failure(ext_parser); 3345 XML_ParserFree(ext_parser); 3346 return XML_STATUS_OK; 3347 } 3348 3349 static int XMLCALL 3350 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context, 3351 const XML_Char *base, const XML_Char *systemId, 3352 const XML_Char *publicId) { 3353 const char *text = "<tag>\r"; 3354 XML_Parser ext_parser; 3355 3356 UNUSED_P(base); 3357 UNUSED_P(systemId); 3358 UNUSED_P(publicId); 3359 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3360 if (ext_parser == NULL) 3361 fail("Could not create external entity parser"); 3362 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler); 3363 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3364 == XML_STATUS_OK) 3365 fail("Async entity error not caught"); 3366 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY) 3367 xml_failure(ext_parser); 3368 XML_ParserFree(ext_parser); 3369 return XML_STATUS_OK; 3370 } 3371 3372 START_TEST(test_ext_entity_trailing_cr) { 3373 const char *text = "<!DOCTYPE doc [\n" 3374 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3375 "]>\n" 3376 "<doc>&en;</doc>"; 3377 int found_cr; 3378 3379 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3380 XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher); 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 xml_failure(g_parser); 3386 if (found_cr == 0) 3387 fail("No carriage return found"); 3388 XML_ParserReset(g_parser, NULL); 3389 3390 /* Try again with a different trailing CR */ 3391 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3392 XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher); 3393 XML_SetUserData(g_parser, &found_cr); 3394 found_cr = 0; 3395 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3396 != XML_STATUS_OK) 3397 xml_failure(g_parser); 3398 if (found_cr == 0) 3399 fail("No carriage return found"); 3400 } 3401 END_TEST 3402 3403 /* Test handling of trailing square bracket */ 3404 static void XMLCALL 3405 rsqb_handler(void *userData, const XML_Char *s, int len) { 3406 int *pfound = (int *)userData; 3407 3408 if (len == 1 && *s == XCS(']')) 3409 *pfound = 1; 3410 } 3411 3412 START_TEST(test_trailing_rsqb) { 3413 const char *text8 = "<doc>]"; 3414 const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000"; 3415 int found_rsqb; 3416 int text8_len = (int)strlen(text8); 3417 3418 XML_SetCharacterDataHandler(g_parser, rsqb_handler); 3419 XML_SetUserData(g_parser, &found_rsqb); 3420 found_rsqb = 0; 3421 if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE) 3422 == XML_STATUS_OK) 3423 fail("Failed to fault unclosed doc"); 3424 if (found_rsqb == 0) 3425 fail("Did not catch the right square bracket"); 3426 3427 /* Try again with a different encoding */ 3428 XML_ParserReset(g_parser, NULL); 3429 XML_SetCharacterDataHandler(g_parser, rsqb_handler); 3430 XML_SetUserData(g_parser, &found_rsqb); 3431 found_rsqb = 0; 3432 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1, 3433 XML_TRUE) 3434 == XML_STATUS_OK) 3435 fail("Failed to fault unclosed doc"); 3436 if (found_rsqb == 0) 3437 fail("Did not catch the right square bracket"); 3438 3439 /* And finally with a default handler */ 3440 XML_ParserReset(g_parser, NULL); 3441 XML_SetDefaultHandler(g_parser, rsqb_handler); 3442 XML_SetUserData(g_parser, &found_rsqb); 3443 found_rsqb = 0; 3444 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1, 3445 XML_TRUE) 3446 == XML_STATUS_OK) 3447 fail("Failed to fault unclosed doc"); 3448 if (found_rsqb == 0) 3449 fail("Did not catch the right square bracket"); 3450 } 3451 END_TEST 3452 3453 /* Test trailing right square bracket in an external entity parse */ 3454 static int XMLCALL 3455 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context, 3456 const XML_Char *base, const XML_Char *systemId, 3457 const XML_Char *publicId) { 3458 const char *text = "<tag>]"; 3459 XML_Parser ext_parser; 3460 3461 UNUSED_P(base); 3462 UNUSED_P(systemId); 3463 UNUSED_P(publicId); 3464 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3465 if (ext_parser == NULL) 3466 fail("Could not create external entity parser"); 3467 XML_SetCharacterDataHandler(ext_parser, rsqb_handler); 3468 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3469 != XML_STATUS_ERROR) 3470 fail("Async entity error not caught"); 3471 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY) 3472 xml_failure(ext_parser); 3473 XML_ParserFree(ext_parser); 3474 return XML_STATUS_OK; 3475 } 3476 3477 START_TEST(test_ext_entity_trailing_rsqb) { 3478 const char *text = "<!DOCTYPE doc [\n" 3479 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3480 "]>\n" 3481 "<doc>&en;</doc>"; 3482 int found_rsqb; 3483 3484 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3485 XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher); 3486 XML_SetUserData(g_parser, &found_rsqb); 3487 found_rsqb = 0; 3488 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3489 != XML_STATUS_OK) 3490 xml_failure(g_parser); 3491 if (found_rsqb == 0) 3492 fail("No right square bracket found"); 3493 } 3494 END_TEST 3495 3496 /* Test CDATA handling in an external entity */ 3497 static int XMLCALL 3498 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context, 3499 const XML_Char *base, const XML_Char *systemId, 3500 const XML_Char *publicId) { 3501 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>"; 3502 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>"); 3503 CharData storage; 3504 XML_Parser ext_parser; 3505 3506 UNUSED_P(base); 3507 UNUSED_P(systemId); 3508 UNUSED_P(publicId); 3509 CharData_Init(&storage); 3510 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3511 if (ext_parser == NULL) 3512 fail("Could not create external entity parser"); 3513 XML_SetUserData(ext_parser, &storage); 3514 XML_SetCharacterDataHandler(ext_parser, accumulate_characters); 3515 3516 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3517 == XML_STATUS_ERROR) 3518 xml_failure(ext_parser); 3519 CharData_CheckXMLChars(&storage, expected); 3520 3521 XML_ParserFree(ext_parser); 3522 return XML_STATUS_OK; 3523 } 3524 3525 START_TEST(test_ext_entity_good_cdata) { 3526 const char *text = "<!DOCTYPE doc [\n" 3527 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3528 "]>\n" 3529 "<doc>&en;</doc>"; 3530 3531 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3532 XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii); 3533 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3534 != XML_STATUS_OK) 3535 xml_failure(g_parser); 3536 } 3537 END_TEST 3538 3539 /* Test user parameter settings */ 3540 /* Variable holding the expected handler userData */ 3541 static void *handler_data = NULL; 3542 /* Count of the number of times the comment handler has been invoked */ 3543 static int comment_count = 0; 3544 /* Count of the number of skipped entities */ 3545 static int skip_count = 0; 3546 /* Count of the number of times the XML declaration handler is invoked */ 3547 static int xdecl_count = 0; 3548 3549 static void XMLCALL 3550 xml_decl_handler(void *userData, const XML_Char *version, 3551 const XML_Char *encoding, int standalone) { 3552 UNUSED_P(version); 3553 UNUSED_P(encoding); 3554 if (userData != handler_data) 3555 fail("User data (xml decl) not correctly set"); 3556 if (standalone != -1) 3557 fail("Standalone not flagged as not present in XML decl"); 3558 xdecl_count++; 3559 } 3560 3561 static void XMLCALL 3562 param_check_skip_handler(void *userData, const XML_Char *entityName, 3563 int is_parameter_entity) { 3564 UNUSED_P(entityName); 3565 UNUSED_P(is_parameter_entity); 3566 if (userData != handler_data) 3567 fail("User data (skip) not correctly set"); 3568 skip_count++; 3569 } 3570 3571 static void XMLCALL 3572 data_check_comment_handler(void *userData, const XML_Char *data) { 3573 UNUSED_P(data); 3574 /* Check that the userData passed through is what we expect */ 3575 if (userData != handler_data) 3576 fail("User data (parser) not correctly set"); 3577 /* Check that the user data in the parser is appropriate */ 3578 if (XML_GetUserData(userData) != (void *)1) 3579 fail("User data in parser not correctly set"); 3580 comment_count++; 3581 } 3582 3583 static int XMLCALL 3584 external_entity_param_checker(XML_Parser parser, const XML_Char *context, 3585 const XML_Char *base, const XML_Char *systemId, 3586 const XML_Char *publicId) { 3587 const char *text = "<!-- Subordinate parser -->\n" 3588 "<!ELEMENT doc (#PCDATA)*>"; 3589 XML_Parser ext_parser; 3590 3591 UNUSED_P(base); 3592 UNUSED_P(systemId); 3593 UNUSED_P(publicId); 3594 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3595 if (ext_parser == NULL) 3596 fail("Could not create external entity parser"); 3597 handler_data = ext_parser; 3598 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3599 == XML_STATUS_ERROR) { 3600 xml_failure(parser); 3601 return XML_STATUS_ERROR; 3602 } 3603 handler_data = parser; 3604 XML_ParserFree(ext_parser); 3605 return XML_STATUS_OK; 3606 } 3607 3608 START_TEST(test_user_parameters) { 3609 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3610 "<!-- Primary parse -->\n" 3611 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3612 "<doc>&entity;"; 3613 const char *epilog = "<!-- Back to primary parser -->\n" 3614 "</doc>"; 3615 3616 comment_count = 0; 3617 skip_count = 0; 3618 xdecl_count = 0; 3619 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3620 XML_SetXmlDeclHandler(g_parser, xml_decl_handler); 3621 XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker); 3622 XML_SetCommentHandler(g_parser, data_check_comment_handler); 3623 XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler); 3624 XML_UseParserAsHandlerArg(g_parser); 3625 XML_SetUserData(g_parser, (void *)1); 3626 handler_data = g_parser; 3627 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3628 == XML_STATUS_ERROR) 3629 xml_failure(g_parser); 3630 if (comment_count != 2) 3631 fail("Comment handler not invoked enough times"); 3632 /* Ensure we can't change policy mid-parse */ 3633 if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER)) 3634 fail("Changed param entity parsing policy while parsing"); 3635 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 3636 == XML_STATUS_ERROR) 3637 xml_failure(g_parser); 3638 if (comment_count != 3) 3639 fail("Comment handler not invoked enough times"); 3640 if (skip_count != 1) 3641 fail("Skip handler not invoked enough times"); 3642 if (xdecl_count != 1) 3643 fail("XML declaration handler not invoked"); 3644 } 3645 END_TEST 3646 3647 /* Test that an explicit external entity handler argument replaces 3648 * the parser as the first argument. 3649 * 3650 * We do not call the first parameter to the external entity handler 3651 * 'parser' for once, since the first time the handler is called it 3652 * will actually be a text string. We need to be able to access the 3653 * global 'parser' variable to create our external entity parser from, 3654 * since there are code paths we need to ensure get executed. 3655 */ 3656 static int XMLCALL 3657 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context, 3658 const XML_Char *base, 3659 const XML_Char *systemId, 3660 const XML_Char *publicId) { 3661 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3662 XML_Parser ext_parser; 3663 3664 UNUSED_P(base); 3665 UNUSED_P(systemId); 3666 UNUSED_P(publicId); 3667 if ((void *)parameter != handler_data) 3668 fail("External entity ref handler parameter not correct"); 3669 3670 /* Here we use the global 'parser' variable */ 3671 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL); 3672 if (ext_parser == NULL) 3673 fail("Could not create external entity parser"); 3674 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3675 == XML_STATUS_ERROR) 3676 xml_failure(ext_parser); 3677 3678 XML_ParserFree(ext_parser); 3679 return XML_STATUS_OK; 3680 } 3681 3682 START_TEST(test_ext_entity_ref_parameter) { 3683 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3684 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3685 "<doc>&entity;</doc>"; 3686 3687 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3688 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker); 3689 /* Set a handler arg that is not NULL and not parser (which is 3690 * what NULL would cause to be passed. 3691 */ 3692 XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text); 3693 handler_data = (void *)text; 3694 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3695 == XML_STATUS_ERROR) 3696 xml_failure(g_parser); 3697 3698 /* Now try again with unset args */ 3699 XML_ParserReset(g_parser, NULL); 3700 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3701 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker); 3702 XML_SetExternalEntityRefHandlerArg(g_parser, NULL); 3703 handler_data = (void *)g_parser; 3704 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3705 == XML_STATUS_ERROR) 3706 xml_failure(g_parser); 3707 } 3708 END_TEST 3709 3710 /* Test the parsing of an empty string */ 3711 START_TEST(test_empty_parse) { 3712 const char *text = "<doc></doc>"; 3713 const char *partial = "<doc>"; 3714 3715 if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR) 3716 fail("Parsing empty string faulted"); 3717 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 3718 fail("Parsing final empty string not faulted"); 3719 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS) 3720 fail("Parsing final empty string faulted for wrong reason"); 3721 3722 /* Now try with valid text before the empty end */ 3723 XML_ParserReset(g_parser, NULL); 3724 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3725 == XML_STATUS_ERROR) 3726 xml_failure(g_parser); 3727 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR) 3728 fail("Parsing final empty string faulted"); 3729 3730 /* Now try with invalid text before the empty end */ 3731 XML_ParserReset(g_parser, NULL); 3732 if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial), 3733 XML_FALSE) 3734 == XML_STATUS_ERROR) 3735 xml_failure(g_parser); 3736 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 3737 fail("Parsing final incomplete empty string not faulted"); 3738 } 3739 END_TEST 3740 3741 /* Test odd corners of the XML_GetBuffer interface */ 3742 static enum XML_Status 3743 get_feature(enum XML_FeatureEnum feature_id, long *presult) { 3744 const XML_Feature *feature = XML_GetFeatureList(); 3745 3746 if (feature == NULL) 3747 return XML_STATUS_ERROR; 3748 for (; feature->feature != XML_FEATURE_END; feature++) { 3749 if (feature->feature == feature_id) { 3750 *presult = feature->value; 3751 return XML_STATUS_OK; 3752 } 3753 } 3754 return XML_STATUS_ERROR; 3755 } 3756 3757 /* Having an element name longer than 1024 characters exercises some 3758 * of the pool allocation code in the parser that otherwise does not 3759 * get executed. The count at the end of the line is the number of 3760 * characters (bytes) in the element name by that point.x 3761 */ 3762 static const char *get_buffer_test_text 3763 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */ 3764 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */ 3765 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */ 3766 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */ 3767 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */ 3768 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */ 3769 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */ 3770 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */ 3771 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */ 3772 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */ 3773 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */ 3774 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */ 3775 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */ 3776 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */ 3777 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */ 3778 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */ 3779 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */ 3780 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */ 3781 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */ 3782 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */ 3783 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */ 3784 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */ 3785 3786 /* Test odd corners of the XML_GetBuffer interface */ 3787 START_TEST(test_get_buffer_1) { 3788 const char *text = get_buffer_test_text; 3789 void *buffer; 3790 long context_bytes; 3791 3792 /* Attempt to allocate a negative length buffer */ 3793 if (XML_GetBuffer(g_parser, -12) != NULL) 3794 fail("Negative length buffer not failed"); 3795 3796 /* Now get a small buffer and extend it past valid length */ 3797 buffer = XML_GetBuffer(g_parser, 1536); 3798 if (buffer == NULL) 3799 fail("1.5K buffer failed"); 3800 assert(buffer != NULL); 3801 memcpy(buffer, text, strlen(text)); 3802 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 3803 == XML_STATUS_ERROR) 3804 xml_failure(g_parser); 3805 if (XML_GetBuffer(g_parser, INT_MAX) != NULL) 3806 fail("INT_MAX buffer not failed"); 3807 3808 /* Now try extending it a more reasonable but still too large 3809 * amount. The allocator in XML_GetBuffer() doubles the buffer 3810 * size until it exceeds the requested amount or INT_MAX. If it 3811 * exceeds INT_MAX, it rejects the request, so we want a request 3812 * between INT_MAX and INT_MAX/2. A gap of 1K seems comfortable, 3813 * with an extra byte just to ensure that the request is off any 3814 * boundary. The request will be inflated internally by 3815 * XML_CONTEXT_BYTES (if defined), so we subtract that from our 3816 * request. 3817 */ 3818 if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK) 3819 context_bytes = 0; 3820 if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL) 3821 fail("INT_MAX- buffer not failed"); 3822 3823 /* Now try extending it a carefully crafted amount */ 3824 if (XML_GetBuffer(g_parser, 1000) == NULL) 3825 fail("1000 buffer failed"); 3826 } 3827 END_TEST 3828 3829 /* Test more corners of the XML_GetBuffer interface */ 3830 START_TEST(test_get_buffer_2) { 3831 const char *text = get_buffer_test_text; 3832 void *buffer; 3833 3834 /* Now get a decent buffer */ 3835 buffer = XML_GetBuffer(g_parser, 1536); 3836 if (buffer == NULL) 3837 fail("1.5K buffer failed"); 3838 assert(buffer != NULL); 3839 memcpy(buffer, text, strlen(text)); 3840 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 3841 == XML_STATUS_ERROR) 3842 xml_failure(g_parser); 3843 3844 /* Extend it, to catch a different code path */ 3845 if (XML_GetBuffer(g_parser, 1024) == NULL) 3846 fail("1024 buffer failed"); 3847 } 3848 END_TEST 3849 3850 /* Test position information macros */ 3851 START_TEST(test_byte_info_at_end) { 3852 const char *text = "<doc></doc>"; 3853 3854 if (XML_GetCurrentByteIndex(g_parser) != -1 3855 || XML_GetCurrentByteCount(g_parser) != 0) 3856 fail("Byte index/count incorrect at start of parse"); 3857 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3858 == XML_STATUS_ERROR) 3859 xml_failure(g_parser); 3860 /* At end, the count will be zero and the index the end of string */ 3861 if (XML_GetCurrentByteCount(g_parser) != 0) 3862 fail("Terminal byte count incorrect"); 3863 if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text)) 3864 fail("Terminal byte index incorrect"); 3865 } 3866 END_TEST 3867 3868 /* Test position information from errors */ 3869 #define PRE_ERROR_STR "<doc></" 3870 #define POST_ERROR_STR "wombat></doc>" 3871 START_TEST(test_byte_info_at_error) { 3872 const char *text = PRE_ERROR_STR POST_ERROR_STR; 3873 3874 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3875 == XML_STATUS_OK) 3876 fail("Syntax error not faulted"); 3877 if (XML_GetCurrentByteCount(g_parser) != 0) 3878 fail("Error byte count incorrect"); 3879 if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR)) 3880 fail("Error byte index incorrect"); 3881 } 3882 END_TEST 3883 #undef PRE_ERROR_STR 3884 #undef POST_ERROR_STR 3885 3886 /* Test position information in handler */ 3887 typedef struct ByteTestData { 3888 int start_element_len; 3889 int cdata_len; 3890 int total_string_len; 3891 } ByteTestData; 3892 3893 static void 3894 byte_character_handler(void *userData, const XML_Char *s, int len) { 3895 #ifdef XML_CONTEXT_BYTES 3896 int offset, size; 3897 const char *buffer; 3898 ByteTestData *data = (ByteTestData *)userData; 3899 3900 UNUSED_P(s); 3901 buffer = XML_GetInputContext(g_parser, &offset, &size); 3902 if (buffer == NULL) 3903 fail("Failed to get context buffer"); 3904 if (offset != data->start_element_len) 3905 fail("Context offset in unexpected position"); 3906 if (len != data->cdata_len) 3907 fail("CDATA length reported incorrectly"); 3908 if (size != data->total_string_len) 3909 fail("Context size is not full buffer"); 3910 if (XML_GetCurrentByteIndex(g_parser) != offset) 3911 fail("Character byte index incorrect"); 3912 if (XML_GetCurrentByteCount(g_parser) != len) 3913 fail("Character byte count incorrect"); 3914 #else 3915 UNUSED_P(s); 3916 UNUSED_P(userData); 3917 UNUSED_P(len); 3918 #endif 3919 } 3920 3921 #define START_ELEMENT "<e>" 3922 #define CDATA_TEXT "Hello" 3923 #define END_ELEMENT "</e>" 3924 START_TEST(test_byte_info_at_cdata) { 3925 const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT; 3926 int offset, size; 3927 ByteTestData data; 3928 3929 /* Check initial context is empty */ 3930 if (XML_GetInputContext(g_parser, &offset, &size) != NULL) 3931 fail("Unexpected context at start of parse"); 3932 3933 data.start_element_len = (int)strlen(START_ELEMENT); 3934 data.cdata_len = (int)strlen(CDATA_TEXT); 3935 data.total_string_len = (int)strlen(text); 3936 XML_SetCharacterDataHandler(g_parser, byte_character_handler); 3937 XML_SetUserData(g_parser, &data); 3938 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK) 3939 xml_failure(g_parser); 3940 } 3941 END_TEST 3942 #undef START_ELEMENT 3943 #undef CDATA_TEXT 3944 #undef END_ELEMENT 3945 3946 /* Test predefined entities are correctly recognised */ 3947 START_TEST(test_predefined_entities) { 3948 const char *text = "<doc><>&"'</doc>"; 3949 const XML_Char *expected = XCS("<doc><>&"'</doc>"); 3950 const XML_Char *result = XCS("<>&\"'"); 3951 CharData storage; 3952 3953 XML_SetDefaultHandler(g_parser, accumulate_characters); 3954 /* run_character_check uses XML_SetCharacterDataHandler(), which 3955 * unfortunately heads off a code path that we need to exercise. 3956 */ 3957 CharData_Init(&storage); 3958 XML_SetUserData(g_parser, &storage); 3959 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3960 == XML_STATUS_ERROR) 3961 xml_failure(g_parser); 3962 /* The default handler doesn't translate the entities */ 3963 CharData_CheckXMLChars(&storage, expected); 3964 3965 /* Now try again and check the translation */ 3966 XML_ParserReset(g_parser, NULL); 3967 run_character_check(text, result); 3968 } 3969 END_TEST 3970 3971 /* Regression test that an invalid tag in an external parameter 3972 * reference in an external DTD is correctly faulted. 3973 * 3974 * Only a few specific tags are legal in DTDs ignoring comments and 3975 * processing instructions, all of which begin with an exclamation 3976 * mark. "<el/>" is not one of them, so the parser should raise an 3977 * error on encountering it. 3978 */ 3979 static int XMLCALL 3980 external_entity_param(XML_Parser parser, const XML_Char *context, 3981 const XML_Char *base, const XML_Char *systemId, 3982 const XML_Char *publicId) { 3983 const char *text1 = "<!ELEMENT doc EMPTY>\n" 3984 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 3985 "<!ENTITY % e2 '%e1;'>\n" 3986 "%e1;\n"; 3987 const char *text2 = "<!ELEMENT el EMPTY>\n" 3988 "<el/>\n"; 3989 XML_Parser ext_parser; 3990 3991 UNUSED_P(base); 3992 UNUSED_P(publicId); 3993 if (systemId == NULL) 3994 return XML_STATUS_OK; 3995 3996 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3997 if (ext_parser == NULL) 3998 fail("Could not create external entity parser"); 3999 4000 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4001 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4002 != XML_STATUS_ERROR) 4003 fail("Inner DTD with invalid tag not rejected"); 4004 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) 4005 xml_failure(ext_parser); 4006 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4007 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4008 != XML_STATUS_ERROR) 4009 fail("Invalid tag in external param not rejected"); 4010 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX) 4011 xml_failure(ext_parser); 4012 } else { 4013 fail("Unknown system ID"); 4014 } 4015 4016 XML_ParserFree(ext_parser); 4017 return XML_STATUS_ERROR; 4018 } 4019 4020 START_TEST(test_invalid_tag_in_dtd) { 4021 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4022 "<doc></doc>\n"; 4023 4024 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4025 XML_SetExternalEntityRefHandler(g_parser, external_entity_param); 4026 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4027 "Invalid tag IN DTD external param not rejected"); 4028 } 4029 END_TEST 4030 4031 /* Test entities not quite the predefined ones are not mis-recognised */ 4032 START_TEST(test_not_predefined_entities) { 4033 const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>", 4034 "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL}; 4035 int i = 0; 4036 4037 while (text[i] != NULL) { 4038 expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY, 4039 "Undefined entity not rejected"); 4040 XML_ParserReset(g_parser, NULL); 4041 i++; 4042 } 4043 } 4044 END_TEST 4045 4046 /* Test conditional inclusion (IGNORE) */ 4047 static int XMLCALL 4048 external_entity_load_ignore(XML_Parser parser, const XML_Char *context, 4049 const XML_Char *base, const XML_Char *systemId, 4050 const XML_Char *publicId) { 4051 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>"; 4052 XML_Parser ext_parser; 4053 4054 UNUSED_P(base); 4055 UNUSED_P(systemId); 4056 UNUSED_P(publicId); 4057 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4058 if (ext_parser == NULL) 4059 fail("Could not create external entity parser"); 4060 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 4061 == XML_STATUS_ERROR) 4062 xml_failure(parser); 4063 4064 XML_ParserFree(ext_parser); 4065 return XML_STATUS_OK; 4066 } 4067 4068 START_TEST(test_ignore_section) { 4069 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4070 "<doc><e>&entity;</e></doc>"; 4071 const XML_Char *expected 4072 = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;"); 4073 CharData storage; 4074 4075 CharData_Init(&storage); 4076 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4077 XML_SetUserData(g_parser, &storage); 4078 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore); 4079 XML_SetDefaultHandler(g_parser, accumulate_characters); 4080 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4081 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4082 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4083 XML_SetStartElementHandler(g_parser, dummy_start_element); 4084 XML_SetEndElementHandler(g_parser, dummy_end_element); 4085 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4086 == XML_STATUS_ERROR) 4087 xml_failure(g_parser); 4088 CharData_CheckXMLChars(&storage, expected); 4089 } 4090 END_TEST 4091 4092 static int XMLCALL 4093 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context, 4094 const XML_Char *base, 4095 const XML_Char *systemId, 4096 const XML_Char *publicId) { 4097 const char text[] = 4098 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */ 4099 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0" 4100 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0" 4101 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0"; 4102 XML_Parser ext_parser; 4103 4104 UNUSED_P(base); 4105 UNUSED_P(systemId); 4106 UNUSED_P(publicId); 4107 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4108 if (ext_parser == NULL) 4109 fail("Could not create external entity parser"); 4110 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4111 == XML_STATUS_ERROR) 4112 xml_failure(parser); 4113 4114 XML_ParserFree(ext_parser); 4115 return XML_STATUS_OK; 4116 } 4117 4118 START_TEST(test_ignore_section_utf16) { 4119 const char text[] = 4120 /* <!DOCTYPE d SYSTEM 's'> */ 4121 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 " 4122 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0" 4123 /* <d><e>&en;</e></d> */ 4124 "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0"; 4125 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;"); 4126 CharData storage; 4127 4128 CharData_Init(&storage); 4129 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4130 XML_SetUserData(g_parser, &storage); 4131 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16); 4132 XML_SetDefaultHandler(g_parser, accumulate_characters); 4133 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4134 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4135 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4136 XML_SetStartElementHandler(g_parser, dummy_start_element); 4137 XML_SetEndElementHandler(g_parser, dummy_end_element); 4138 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4139 == XML_STATUS_ERROR) 4140 xml_failure(g_parser); 4141 CharData_CheckXMLChars(&storage, expected); 4142 } 4143 END_TEST 4144 4145 static int XMLCALL 4146 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context, 4147 const XML_Char *base, 4148 const XML_Char *systemId, 4149 const XML_Char *publicId) { 4150 const char text[] = 4151 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */ 4152 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0[" 4153 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 " 4154 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>"; 4155 XML_Parser ext_parser; 4156 4157 UNUSED_P(base); 4158 UNUSED_P(systemId); 4159 UNUSED_P(publicId); 4160 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4161 if (ext_parser == NULL) 4162 fail("Could not create external entity parser"); 4163 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4164 == XML_STATUS_ERROR) 4165 xml_failure(parser); 4166 4167 XML_ParserFree(ext_parser); 4168 return XML_STATUS_OK; 4169 } 4170 4171 START_TEST(test_ignore_section_utf16_be) { 4172 const char text[] = 4173 /* <!DOCTYPE d SYSTEM 's'> */ 4174 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 " 4175 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n" 4176 /* <d><e>&en;</e></d> */ 4177 "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>"; 4178 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;"); 4179 CharData storage; 4180 4181 CharData_Init(&storage); 4182 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4183 XML_SetUserData(g_parser, &storage); 4184 XML_SetExternalEntityRefHandler(g_parser, 4185 external_entity_load_ignore_utf16_be); 4186 XML_SetDefaultHandler(g_parser, accumulate_characters); 4187 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4188 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4189 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4190 XML_SetStartElementHandler(g_parser, dummy_start_element); 4191 XML_SetEndElementHandler(g_parser, dummy_end_element); 4192 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4193 == XML_STATUS_ERROR) 4194 xml_failure(g_parser); 4195 CharData_CheckXMLChars(&storage, expected); 4196 } 4197 END_TEST 4198 4199 /* Test mis-formatted conditional exclusion */ 4200 START_TEST(test_bad_ignore_section) { 4201 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4202 "<doc><e>&entity;</e></doc>"; 4203 ExtFaults faults[] 4204 = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL, 4205 XML_ERROR_SYNTAX}, 4206 {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL, 4207 XML_ERROR_INVALID_TOKEN}, 4208 {/* FIrst two bytes of a three-byte char */ 4209 "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL, 4210 XML_ERROR_PARTIAL_CHAR}, 4211 {NULL, NULL, NULL, XML_ERROR_NONE}}; 4212 ExtFaults *fault; 4213 4214 for (fault = &faults[0]; fault->parse_text != NULL; fault++) { 4215 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4216 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 4217 XML_SetUserData(g_parser, fault); 4218 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4219 "Incomplete IGNORE section not failed"); 4220 XML_ParserReset(g_parser, NULL); 4221 } 4222 } 4223 END_TEST 4224 4225 /* Test recursive parsing */ 4226 static int XMLCALL 4227 external_entity_valuer(XML_Parser parser, const XML_Char *context, 4228 const XML_Char *base, const XML_Char *systemId, 4229 const XML_Char *publicId) { 4230 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4231 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4232 "<!ENTITY % e2 '%e1;'>\n" 4233 "%e1;\n"; 4234 XML_Parser ext_parser; 4235 4236 UNUSED_P(base); 4237 UNUSED_P(publicId); 4238 if (systemId == NULL) 4239 return XML_STATUS_OK; 4240 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4241 if (ext_parser == NULL) 4242 fail("Could not create external entity parser"); 4243 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4244 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4245 == XML_STATUS_ERROR) 4246 xml_failure(ext_parser); 4247 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4248 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 4249 enum XML_Status status; 4250 enum XML_Error error; 4251 4252 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text, 4253 (int)strlen(fault->parse_text), XML_TRUE); 4254 if (fault->error == XML_ERROR_NONE) { 4255 if (status == XML_STATUS_ERROR) 4256 xml_failure(ext_parser); 4257 } else { 4258 if (status != XML_STATUS_ERROR) 4259 fail(fault->fail_text); 4260 error = XML_GetErrorCode(ext_parser); 4261 if (error != fault->error 4262 && (fault->error != XML_ERROR_XML_DECL 4263 || error != XML_ERROR_TEXT_DECL)) 4264 xml_failure(ext_parser); 4265 } 4266 } 4267 4268 XML_ParserFree(ext_parser); 4269 return XML_STATUS_OK; 4270 } 4271 4272 START_TEST(test_external_entity_values) { 4273 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4274 "<doc></doc>\n"; 4275 ExtFaults data_004_2[] = { 4276 {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE}, 4277 {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL, 4278 XML_ERROR_INVALID_TOKEN}, 4279 {"'wombat", "Unterminated string not faulted", NULL, 4280 XML_ERROR_UNCLOSED_TOKEN}, 4281 {"\xe2\x82", "Partial UTF-8 character not faulted", NULL, 4282 XML_ERROR_PARTIAL_CHAR}, 4283 {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE}, 4284 {"<?xml?>", "Malformed XML declaration not faulted", NULL, 4285 XML_ERROR_XML_DECL}, 4286 {/* UTF-8 BOM */ 4287 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, 4288 XML_ERROR_NONE}, 4289 {"<?xml version='1.0' encoding='utf-8'?>\n$", 4290 "Invalid token after text declaration not faulted", NULL, 4291 XML_ERROR_INVALID_TOKEN}, 4292 {"<?xml version='1.0' encoding='utf-8'?>\n'wombat", 4293 "Unterminated string after text decl not faulted", NULL, 4294 XML_ERROR_UNCLOSED_TOKEN}, 4295 {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82", 4296 "Partial UTF-8 character after text decl not faulted", NULL, 4297 XML_ERROR_PARTIAL_CHAR}, 4298 {"%e1;", "Recursive parameter entity not faulted", NULL, 4299 XML_ERROR_RECURSIVE_ENTITY_REF}, 4300 {NULL, NULL, NULL, XML_ERROR_NONE}}; 4301 int i; 4302 4303 for (i = 0; data_004_2[i].parse_text != NULL; i++) { 4304 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4305 XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer); 4306 XML_SetUserData(g_parser, &data_004_2[i]); 4307 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4308 == XML_STATUS_ERROR) 4309 xml_failure(g_parser); 4310 XML_ParserReset(g_parser, NULL); 4311 } 4312 } 4313 END_TEST 4314 4315 /* Test the recursive parse interacts with a not standalone handler */ 4316 static int XMLCALL 4317 external_entity_not_standalone(XML_Parser parser, const XML_Char *context, 4318 const XML_Char *base, const XML_Char *systemId, 4319 const XML_Char *publicId) { 4320 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4321 "<!ENTITY % e1 SYSTEM 'bar'>\n" 4322 "%e1;\n"; 4323 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>"; 4324 XML_Parser ext_parser; 4325 4326 UNUSED_P(base); 4327 UNUSED_P(publicId); 4328 if (systemId == NULL) 4329 return XML_STATUS_OK; 4330 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4331 if (ext_parser == NULL) 4332 fail("Could not create external entity parser"); 4333 if (! xcstrcmp(systemId, XCS("foo"))) { 4334 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler); 4335 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4336 != XML_STATUS_ERROR) 4337 fail("Expected not standalone rejection"); 4338 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE) 4339 xml_failure(ext_parser); 4340 XML_SetNotStandaloneHandler(ext_parser, NULL); 4341 XML_ParserFree(ext_parser); 4342 return XML_STATUS_ERROR; 4343 } else if (! xcstrcmp(systemId, XCS("bar"))) { 4344 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4345 == XML_STATUS_ERROR) 4346 xml_failure(ext_parser); 4347 } 4348 4349 XML_ParserFree(ext_parser); 4350 return XML_STATUS_OK; 4351 } 4352 4353 START_TEST(test_ext_entity_not_standalone) { 4354 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4355 "<doc></doc>"; 4356 4357 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4358 XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone); 4359 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4360 "Standalone rejection not caught"); 4361 } 4362 END_TEST 4363 4364 static int XMLCALL 4365 external_entity_value_aborter(XML_Parser parser, const XML_Char *context, 4366 const XML_Char *base, const XML_Char *systemId, 4367 const XML_Char *publicId) { 4368 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4369 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4370 "<!ENTITY % e2 '%e1;'>\n" 4371 "%e1;\n"; 4372 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>"; 4373 XML_Parser ext_parser; 4374 4375 UNUSED_P(base); 4376 UNUSED_P(publicId); 4377 if (systemId == NULL) 4378 return XML_STATUS_OK; 4379 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4380 if (ext_parser == NULL) 4381 fail("Could not create external entity parser"); 4382 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4383 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4384 == XML_STATUS_ERROR) 4385 xml_failure(ext_parser); 4386 } 4387 if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4388 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 4389 XML_SetUserData(ext_parser, ext_parser); 4390 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4391 != XML_STATUS_ERROR) 4392 fail("Aborted parse not faulted"); 4393 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED) 4394 xml_failure(ext_parser); 4395 } 4396 4397 XML_ParserFree(ext_parser); 4398 return XML_STATUS_OK; 4399 } 4400 4401 START_TEST(test_ext_entity_value_abort) { 4402 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4403 "<doc></doc>\n"; 4404 4405 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4406 XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter); 4407 resumable = XML_FALSE; 4408 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4409 == XML_STATUS_ERROR) 4410 xml_failure(g_parser); 4411 } 4412 END_TEST 4413 4414 START_TEST(test_bad_public_doctype) { 4415 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 4416 "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n" 4417 "<doc></doc>"; 4418 4419 /* Setting a handler provokes a particular code path */ 4420 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 4421 dummy_end_doctype_handler); 4422 expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed"); 4423 } 4424 END_TEST 4425 4426 /* Test based on ibm/valid/P32/ibm32v04.xml */ 4427 START_TEST(test_attribute_enum_value) { 4428 const char *text = "<?xml version='1.0' standalone='no'?>\n" 4429 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 4430 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 4431 ExtTest dtd_data 4432 = {"<!ELEMENT animal (#PCDATA|a)*>\n" 4433 "<!ELEMENT a EMPTY>\n" 4434 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>", 4435 NULL, NULL}; 4436 const XML_Char *expected = XCS("This is a \n \n\nyellow tiger"); 4437 4438 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 4439 XML_SetUserData(g_parser, &dtd_data); 4440 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4441 /* An attribute list handler provokes a different code path */ 4442 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 4443 run_ext_character_check(text, &dtd_data, expected); 4444 } 4445 END_TEST 4446 4447 /* Slightly bizarrely, the library seems to silently ignore entity 4448 * definitions for predefined entities, even when they are wrong. The 4449 * language of the XML 1.0 spec is somewhat unhelpful as to what ought 4450 * to happen, so this is currently treated as acceptable. 4451 */ 4452 START_TEST(test_predefined_entity_redefinition) { 4453 const char *text = "<!DOCTYPE doc [\n" 4454 "<!ENTITY apos 'foo'>\n" 4455 "]>\n" 4456 "<doc>'</doc>"; 4457 run_character_check(text, XCS("'")); 4458 } 4459 END_TEST 4460 4461 /* Test that the parser stops processing the DTD after an unresolved 4462 * parameter entity is encountered. 4463 */ 4464 START_TEST(test_dtd_stop_processing) { 4465 const char *text = "<!DOCTYPE doc [\n" 4466 "%foo;\n" 4467 "<!ENTITY bar 'bas'>\n" 4468 "]><doc/>"; 4469 4470 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 4471 dummy_handler_flags = 0; 4472 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4473 == XML_STATUS_ERROR) 4474 xml_failure(g_parser); 4475 if (dummy_handler_flags != 0) 4476 fail("DTD processing still going after undefined PE"); 4477 } 4478 END_TEST 4479 4480 /* Test public notations with no system ID */ 4481 START_TEST(test_public_notation_no_sysid) { 4482 const char *text = "<!DOCTYPE doc [\n" 4483 "<!NOTATION note PUBLIC 'foo'>\n" 4484 "<!ELEMENT doc EMPTY>\n" 4485 "]>\n<doc/>"; 4486 4487 dummy_handler_flags = 0; 4488 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 4489 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4490 == XML_STATUS_ERROR) 4491 xml_failure(g_parser); 4492 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 4493 fail("Notation declaration handler not called"); 4494 } 4495 END_TEST 4496 4497 static void XMLCALL 4498 record_element_start_handler(void *userData, const XML_Char *name, 4499 const XML_Char **atts) { 4500 UNUSED_P(atts); 4501 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name)); 4502 } 4503 4504 START_TEST(test_nested_groups) { 4505 const char *text 4506 = "<!DOCTYPE doc [\n" 4507 "<!ELEMENT doc " 4508 /* Sixteen elements per line */ 4509 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 4510 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 4511 "))))))))))))))))))))))))))))))))>\n" 4512 "<!ELEMENT e EMPTY>" 4513 "]>\n" 4514 "<doc><e/></doc>"; 4515 CharData storage; 4516 4517 CharData_Init(&storage); 4518 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4519 XML_SetStartElementHandler(g_parser, record_element_start_handler); 4520 XML_SetUserData(g_parser, &storage); 4521 dummy_handler_flags = 0; 4522 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4523 == XML_STATUS_ERROR) 4524 xml_failure(g_parser); 4525 CharData_CheckXMLChars(&storage, XCS("doce")); 4526 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 4527 fail("Element handler not fired"); 4528 } 4529 END_TEST 4530 4531 START_TEST(test_group_choice) { 4532 const char *text = "<!DOCTYPE doc [\n" 4533 "<!ELEMENT doc (a|b|c)+>\n" 4534 "<!ELEMENT a EMPTY>\n" 4535 "<!ELEMENT b (#PCDATA)>\n" 4536 "<!ELEMENT c ANY>\n" 4537 "]>\n" 4538 "<doc>\n" 4539 "<a/>\n" 4540 "<b attr='foo'>This is a foo</b>\n" 4541 "<c></c>\n" 4542 "</doc>\n"; 4543 4544 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4545 dummy_handler_flags = 0; 4546 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4547 == XML_STATUS_ERROR) 4548 xml_failure(g_parser); 4549 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 4550 fail("Element handler flag not raised"); 4551 } 4552 END_TEST 4553 4554 static int XMLCALL 4555 external_entity_public(XML_Parser parser, const XML_Char *context, 4556 const XML_Char *base, const XML_Char *systemId, 4557 const XML_Char *publicId) { 4558 const char *text1 = (const char *)XML_GetUserData(parser); 4559 const char *text2 = "<!ATTLIST doc a CDATA 'value'>"; 4560 const char *text = NULL; 4561 XML_Parser ext_parser; 4562 int parse_res; 4563 4564 UNUSED_P(base); 4565 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4566 if (ext_parser == NULL) 4567 return XML_STATUS_ERROR; 4568 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) { 4569 text = text1; 4570 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) { 4571 text = text2; 4572 } else 4573 fail("Unexpected parameters to external entity parser"); 4574 assert(text != NULL); 4575 parse_res 4576 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 4577 XML_ParserFree(ext_parser); 4578 return parse_res; 4579 } 4580 4581 START_TEST(test_standalone_parameter_entity) { 4582 const char *text = "<?xml version='1.0' standalone='yes'?>\n" 4583 "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n" 4584 "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n" 4585 "%entity;\n" 4586 "]>\n" 4587 "<doc></doc>"; 4588 char dtd_data[] = "<!ENTITY % e1 'foo'>\n"; 4589 4590 XML_SetUserData(g_parser, dtd_data); 4591 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4592 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 4593 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4594 == XML_STATUS_ERROR) 4595 xml_failure(g_parser); 4596 } 4597 END_TEST 4598 4599 /* Test skipping of parameter entity in an external DTD */ 4600 /* Derived from ibm/invalid/P69/ibm69i01.xml */ 4601 START_TEST(test_skipped_parameter_entity) { 4602 const char *text = "<?xml version='1.0'?>\n" 4603 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n" 4604 "<!ELEMENT root (#PCDATA|a)* >\n" 4605 "]>\n" 4606 "<root></root>"; 4607 ExtTest dtd_data = {"%pe2;", NULL, NULL}; 4608 4609 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 4610 XML_SetUserData(g_parser, &dtd_data); 4611 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4612 XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler); 4613 dummy_handler_flags = 0; 4614 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4615 == XML_STATUS_ERROR) 4616 xml_failure(g_parser); 4617 if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG) 4618 fail("Skip handler not executed"); 4619 } 4620 END_TEST 4621 4622 /* Test recursive parameter entity definition rejected in external DTD */ 4623 START_TEST(test_recursive_external_parameter_entity) { 4624 const char *text = "<?xml version='1.0'?>\n" 4625 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n" 4626 "<!ELEMENT root (#PCDATA|a)* >\n" 4627 "]>\n" 4628 "<root></root>"; 4629 ExtFaults dtd_data = {"<!ENTITY % pe2 '%pe2;'>\n%pe2;", 4630 "Recursive external parameter entity not faulted", NULL, 4631 XML_ERROR_RECURSIVE_ENTITY_REF}; 4632 4633 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 4634 XML_SetUserData(g_parser, &dtd_data); 4635 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4636 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4637 "Recursive external parameter not spotted"); 4638 } 4639 END_TEST 4640 4641 /* Test undefined parameter entity in external entity handler */ 4642 static int XMLCALL 4643 external_entity_devaluer(XML_Parser parser, const XML_Char *context, 4644 const XML_Char *base, const XML_Char *systemId, 4645 const XML_Char *publicId) { 4646 const char *text = "<!ELEMENT doc EMPTY>\n" 4647 "<!ENTITY % e1 SYSTEM 'bar'>\n" 4648 "%e1;\n"; 4649 XML_Parser ext_parser; 4650 intptr_t clear_handler = (intptr_t)XML_GetUserData(parser); 4651 4652 UNUSED_P(base); 4653 UNUSED_P(publicId); 4654 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar"))) 4655 return XML_STATUS_OK; 4656 if (xcstrcmp(systemId, XCS("foo"))) 4657 fail("Unexpected system ID"); 4658 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4659 if (ext_parser == NULL) 4660 fail("Could note create external entity parser"); 4661 if (clear_handler) 4662 XML_SetExternalEntityRefHandler(ext_parser, NULL); 4663 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 4664 == XML_STATUS_ERROR) 4665 xml_failure(ext_parser); 4666 4667 XML_ParserFree(ext_parser); 4668 return XML_STATUS_OK; 4669 } 4670 4671 START_TEST(test_undefined_ext_entity_in_external_dtd) { 4672 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4673 "<doc></doc>\n"; 4674 4675 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4676 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer); 4677 XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE); 4678 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4679 == XML_STATUS_ERROR) 4680 xml_failure(g_parser); 4681 4682 /* Now repeat without the external entity ref handler invoking 4683 * another copy of itself. 4684 */ 4685 XML_ParserReset(g_parser, NULL); 4686 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4687 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer); 4688 XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE); 4689 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4690 == XML_STATUS_ERROR) 4691 xml_failure(g_parser); 4692 } 4693 END_TEST 4694 4695 static void XMLCALL 4696 aborting_xdecl_handler(void *userData, const XML_Char *version, 4697 const XML_Char *encoding, int standalone) { 4698 UNUSED_P(userData); 4699 UNUSED_P(version); 4700 UNUSED_P(encoding); 4701 UNUSED_P(standalone); 4702 XML_StopParser(g_parser, resumable); 4703 XML_SetXmlDeclHandler(g_parser, NULL); 4704 } 4705 4706 /* Test suspending the parse on receiving an XML declaration works */ 4707 START_TEST(test_suspend_xdecl) { 4708 const char *text = long_character_data_text; 4709 4710 XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler); 4711 resumable = XML_TRUE; 4712 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4713 != XML_STATUS_SUSPENDED) 4714 xml_failure(g_parser); 4715 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 4716 xml_failure(g_parser); 4717 /* Attempt to start a new parse while suspended */ 4718 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4719 != XML_STATUS_ERROR) 4720 fail("Attempt to parse while suspended not faulted"); 4721 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 4722 fail("Suspended parse not faulted with correct error"); 4723 } 4724 END_TEST 4725 4726 /* Test aborting the parse in an epilog works */ 4727 static void XMLCALL 4728 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) { 4729 const XML_Char *match = (const XML_Char *)userData; 4730 4731 if (match == NULL 4732 || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) { 4733 XML_StopParser(g_parser, resumable); 4734 XML_SetDefaultHandler(g_parser, NULL); 4735 } 4736 } 4737 4738 START_TEST(test_abort_epilog) { 4739 const char *text = "<doc></doc>\n\r\n"; 4740 XML_Char match[] = XCS("\r"); 4741 4742 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4743 XML_SetUserData(g_parser, match); 4744 resumable = XML_FALSE; 4745 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4746 != XML_STATUS_ERROR) 4747 fail("Abort not triggered"); 4748 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED) 4749 xml_failure(g_parser); 4750 } 4751 END_TEST 4752 4753 /* Test a different code path for abort in the epilog */ 4754 START_TEST(test_abort_epilog_2) { 4755 const char *text = "<doc></doc>\n"; 4756 XML_Char match[] = XCS("\n"); 4757 4758 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4759 XML_SetUserData(g_parser, match); 4760 resumable = XML_FALSE; 4761 expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered"); 4762 } 4763 END_TEST 4764 4765 /* Test suspension from the epilog */ 4766 START_TEST(test_suspend_epilog) { 4767 const char *text = "<doc></doc>\n"; 4768 XML_Char match[] = XCS("\n"); 4769 4770 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4771 XML_SetUserData(g_parser, match); 4772 resumable = XML_TRUE; 4773 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4774 != XML_STATUS_SUSPENDED) 4775 xml_failure(g_parser); 4776 } 4777 END_TEST 4778 4779 static void XMLCALL 4780 suspending_end_handler(void *userData, const XML_Char *s) { 4781 UNUSED_P(s); 4782 XML_StopParser((XML_Parser)userData, 1); 4783 } 4784 4785 START_TEST(test_suspend_in_sole_empty_tag) { 4786 const char *text = "<doc/>"; 4787 enum XML_Status rc; 4788 4789 XML_SetEndElementHandler(g_parser, suspending_end_handler); 4790 XML_SetUserData(g_parser, g_parser); 4791 rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 4792 if (rc == XML_STATUS_ERROR) 4793 xml_failure(g_parser); 4794 else if (rc != XML_STATUS_SUSPENDED) 4795 fail("Suspend not triggered"); 4796 rc = XML_ResumeParser(g_parser); 4797 if (rc == XML_STATUS_ERROR) 4798 xml_failure(g_parser); 4799 else if (rc != XML_STATUS_OK) 4800 fail("Resume failed"); 4801 } 4802 END_TEST 4803 4804 START_TEST(test_unfinished_epilog) { 4805 const char *text = "<doc></doc><"; 4806 4807 expect_failure(text, XML_ERROR_UNCLOSED_TOKEN, 4808 "Incomplete epilog entry not faulted"); 4809 } 4810 END_TEST 4811 4812 START_TEST(test_partial_char_in_epilog) { 4813 const char *text = "<doc></doc>\xe2\x82"; 4814 4815 /* First check that no fault is raised if the parse is not finished */ 4816 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 4817 == XML_STATUS_ERROR) 4818 xml_failure(g_parser); 4819 /* Now check that it is faulted once we finish */ 4820 if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR) 4821 fail("Partial character in epilog not faulted"); 4822 if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR) 4823 xml_failure(g_parser); 4824 } 4825 END_TEST 4826 4827 START_TEST(test_hash_collision) { 4828 /* For full coverage of the lookup routine, we need to ensure a 4829 * hash collision even though we can only tell that we have one 4830 * through breakpoint debugging or coverage statistics. The 4831 * following will cause a hash collision on machines with a 64-bit 4832 * long type; others will have to experiment. The full coverage 4833 * tests invoked from qa.sh usually provide a hash collision, but 4834 * not always. This is an attempt to provide insurance. 4835 */ 4836 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U) 4837 const char *text 4838 = "<doc>\n" 4839 "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n" 4840 "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n" 4841 "<b5></b5><b6></b6><b7></b7><b8></b8>\n" 4842 "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n" 4843 "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n" 4844 "<d8>This triggers the table growth and collides with b2</d8>\n" 4845 "</doc>\n"; 4846 4847 XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT); 4848 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4849 == XML_STATUS_ERROR) 4850 xml_failure(g_parser); 4851 } 4852 END_TEST 4853 #undef COLLIDING_HASH_SALT 4854 4855 /* Test resuming a parse suspended in entity substitution */ 4856 static void XMLCALL 4857 start_element_suspender(void *userData, const XML_Char *name, 4858 const XML_Char **atts) { 4859 UNUSED_P(userData); 4860 UNUSED_P(atts); 4861 if (! xcstrcmp(name, XCS("suspend"))) 4862 XML_StopParser(g_parser, XML_TRUE); 4863 if (! xcstrcmp(name, XCS("abort"))) 4864 XML_StopParser(g_parser, XML_FALSE); 4865 } 4866 4867 START_TEST(test_suspend_resume_internal_entity) { 4868 const char *text 4869 = "<!DOCTYPE doc [\n" 4870 "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n" 4871 "]>\n" 4872 "<doc>&foo;</doc>\n"; 4873 const XML_Char *expected1 = XCS("Hi"); 4874 const XML_Char *expected2 = XCS("HiHo"); 4875 CharData storage; 4876 4877 CharData_Init(&storage); 4878 XML_SetStartElementHandler(g_parser, start_element_suspender); 4879 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 4880 XML_SetUserData(g_parser, &storage); 4881 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4882 != XML_STATUS_SUSPENDED) 4883 xml_failure(g_parser); 4884 CharData_CheckXMLChars(&storage, XCS("")); 4885 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED) 4886 xml_failure(g_parser); 4887 CharData_CheckXMLChars(&storage, expected1); 4888 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 4889 xml_failure(g_parser); 4890 CharData_CheckXMLChars(&storage, expected2); 4891 } 4892 END_TEST 4893 4894 /* Test syntax error is caught at parse resumption */ 4895 START_TEST(test_resume_entity_with_syntax_error) { 4896 const char *text = "<!DOCTYPE doc [\n" 4897 "<!ENTITY foo '<suspend>Hi</wombat>'>\n" 4898 "]>\n" 4899 "<doc>&foo;</doc>\n"; 4900 4901 XML_SetStartElementHandler(g_parser, start_element_suspender); 4902 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4903 != XML_STATUS_SUSPENDED) 4904 xml_failure(g_parser); 4905 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 4906 fail("Syntax error in entity not faulted"); 4907 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH) 4908 xml_failure(g_parser); 4909 } 4910 END_TEST 4911 4912 /* Test suspending and resuming in a parameter entity substitution */ 4913 static void XMLCALL 4914 element_decl_suspender(void *userData, const XML_Char *name, 4915 XML_Content *model) { 4916 UNUSED_P(userData); 4917 UNUSED_P(name); 4918 XML_StopParser(g_parser, XML_TRUE); 4919 XML_FreeContentModel(g_parser, model); 4920 } 4921 4922 START_TEST(test_suspend_resume_parameter_entity) { 4923 const char *text = "<!DOCTYPE doc [\n" 4924 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n" 4925 "%foo;\n" 4926 "]>\n" 4927 "<doc>Hello, world</doc>"; 4928 const XML_Char *expected = XCS("Hello, world"); 4929 CharData storage; 4930 4931 CharData_Init(&storage); 4932 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4933 XML_SetElementDeclHandler(g_parser, element_decl_suspender); 4934 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 4935 XML_SetUserData(g_parser, &storage); 4936 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4937 != XML_STATUS_SUSPENDED) 4938 xml_failure(g_parser); 4939 CharData_CheckXMLChars(&storage, XCS("")); 4940 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 4941 xml_failure(g_parser); 4942 CharData_CheckXMLChars(&storage, expected); 4943 } 4944 END_TEST 4945 4946 /* Test attempting to use parser after an error is faulted */ 4947 START_TEST(test_restart_on_error) { 4948 const char *text = "<$doc><doc></doc>"; 4949 4950 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4951 != XML_STATUS_ERROR) 4952 fail("Invalid tag name not faulted"); 4953 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 4954 xml_failure(g_parser); 4955 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 4956 fail("Restarting invalid parse not faulted"); 4957 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 4958 xml_failure(g_parser); 4959 } 4960 END_TEST 4961 4962 /* Test that angle brackets in an attribute default value are faulted */ 4963 START_TEST(test_reject_lt_in_attribute_value) { 4964 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n" 4965 "<doc></doc>"; 4966 4967 expect_failure(text, XML_ERROR_INVALID_TOKEN, 4968 "Bad attribute default not faulted"); 4969 } 4970 END_TEST 4971 4972 START_TEST(test_reject_unfinished_param_in_att_value) { 4973 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n" 4974 "<doc></doc>"; 4975 4976 expect_failure(text, XML_ERROR_INVALID_TOKEN, 4977 "Bad attribute default not faulted"); 4978 } 4979 END_TEST 4980 4981 START_TEST(test_trailing_cr_in_att_value) { 4982 const char *text = "<doc a='value\r'/>"; 4983 4984 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4985 == XML_STATUS_ERROR) 4986 xml_failure(g_parser); 4987 } 4988 END_TEST 4989 4990 /* Try parsing a general entity within a parameter entity in a 4991 * standalone internal DTD. Covers a corner case in the parser. 4992 */ 4993 START_TEST(test_standalone_internal_entity) { 4994 const char *text = "<?xml version='1.0' standalone='yes' ?>\n" 4995 "<!DOCTYPE doc [\n" 4996 " <!ELEMENT doc (#PCDATA)>\n" 4997 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n" 4998 " <!ENTITY ge 'AttDefaultValue'>\n" 4999 " %pe;\n" 5000 "]>\n" 5001 "<doc att2='any'/>"; 5002 5003 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5004 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5005 == XML_STATUS_ERROR) 5006 xml_failure(g_parser); 5007 } 5008 END_TEST 5009 5010 /* Test that a reference to an unknown external entity is skipped */ 5011 START_TEST(test_skipped_external_entity) { 5012 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5013 "<doc></doc>\n"; 5014 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n" 5015 "<!ENTITY % e2 '%e1;'>\n", 5016 NULL, NULL}; 5017 5018 XML_SetUserData(g_parser, &test_data); 5019 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5020 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5021 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5022 == XML_STATUS_ERROR) 5023 xml_failure(g_parser); 5024 } 5025 END_TEST 5026 5027 /* Test a different form of unknown external entity */ 5028 typedef struct ext_hdlr_data { 5029 const char *parse_text; 5030 XML_ExternalEntityRefHandler handler; 5031 } ExtHdlrData; 5032 5033 static int XMLCALL 5034 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context, 5035 const XML_Char *base, const XML_Char *systemId, 5036 const XML_Char *publicId) { 5037 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser); 5038 XML_Parser ext_parser; 5039 5040 UNUSED_P(base); 5041 UNUSED_P(systemId); 5042 UNUSED_P(publicId); 5043 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 5044 if (ext_parser == NULL) 5045 fail("Could not create external entity parser."); 5046 /* Use the requested entity parser for further externals */ 5047 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler); 5048 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text, 5049 (int)strlen(test_data->parse_text), XML_TRUE) 5050 == XML_STATUS_ERROR) { 5051 xml_failure(ext_parser); 5052 } 5053 5054 XML_ParserFree(ext_parser); 5055 return XML_STATUS_OK; 5056 } 5057 5058 START_TEST(test_skipped_null_loaded_ext_entity) { 5059 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5060 "<doc />"; 5061 ExtHdlrData test_data 5062 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5063 "<!ENTITY % pe2 '%pe1;'>\n" 5064 "%pe2;\n", 5065 external_entity_null_loader}; 5066 5067 XML_SetUserData(g_parser, &test_data); 5068 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5069 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5070 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5071 == XML_STATUS_ERROR) 5072 xml_failure(g_parser); 5073 } 5074 END_TEST 5075 5076 START_TEST(test_skipped_unloaded_ext_entity) { 5077 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5078 "<doc />"; 5079 ExtHdlrData test_data 5080 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5081 "<!ENTITY % pe2 '%pe1;'>\n" 5082 "%pe2;\n", 5083 NULL}; 5084 5085 XML_SetUserData(g_parser, &test_data); 5086 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5087 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5088 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5089 == XML_STATUS_ERROR) 5090 xml_failure(g_parser); 5091 } 5092 END_TEST 5093 5094 /* Test that a parameter entity value ending with a carriage return 5095 * has it translated internally into a newline. 5096 */ 5097 START_TEST(test_param_entity_with_trailing_cr) { 5098 #define PARAM_ENTITY_NAME "pe" 5099 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">" 5100 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5101 "<doc/>"; 5102 ExtTest test_data 5103 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n" 5104 "%" PARAM_ENTITY_NAME ";\n", 5105 NULL, NULL}; 5106 5107 XML_SetUserData(g_parser, &test_data); 5108 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5109 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5110 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler); 5111 entity_name_to_match = XCS(PARAM_ENTITY_NAME); 5112 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n"); 5113 entity_match_flag = ENTITY_MATCH_NOT_FOUND; 5114 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5115 == XML_STATUS_ERROR) 5116 xml_failure(g_parser); 5117 if (entity_match_flag == ENTITY_MATCH_FAIL) 5118 fail("Parameter entity CR->NEWLINE conversion failed"); 5119 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND) 5120 fail("Parameter entity not parsed"); 5121 } 5122 #undef PARAM_ENTITY_NAME 5123 #undef PARAM_ENTITY_CORE_VALUE 5124 END_TEST 5125 5126 START_TEST(test_invalid_character_entity) { 5127 const char *text = "<!DOCTYPE doc [\n" 5128 " <!ENTITY entity '�'>\n" 5129 "]>\n" 5130 "<doc>&entity;</doc>"; 5131 5132 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5133 "Out of range character reference not faulted"); 5134 } 5135 END_TEST 5136 5137 START_TEST(test_invalid_character_entity_2) { 5138 const char *text = "<!DOCTYPE doc [\n" 5139 " <!ENTITY entity '&#xg0;'>\n" 5140 "]>\n" 5141 "<doc>&entity;</doc>"; 5142 5143 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5144 "Out of range character reference not faulted"); 5145 } 5146 END_TEST 5147 5148 START_TEST(test_invalid_character_entity_3) { 5149 const char text[] = 5150 /* <!DOCTYPE doc [\n */ 5151 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 5152 /* U+0E04 = KHO KHWAI 5153 * U+0E08 = CHO CHAN */ 5154 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */ 5155 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 " 5156 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n" 5157 /* ]>\n */ 5158 "\0]\0>\0\n" 5159 /* <doc>&entity;</doc> */ 5160 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>"; 5161 5162 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5163 != XML_STATUS_ERROR) 5164 fail("Invalid start of entity name not faulted"); 5165 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY) 5166 xml_failure(g_parser); 5167 } 5168 END_TEST 5169 5170 START_TEST(test_invalid_character_entity_4) { 5171 const char *text = "<!DOCTYPE doc [\n" 5172 " <!ENTITY entity '�'>\n" /* = � */ 5173 "]>\n" 5174 "<doc>&entity;</doc>"; 5175 5176 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5177 "Out of range character reference not faulted"); 5178 } 5179 END_TEST 5180 5181 /* Test that processing instructions are picked up by a default handler */ 5182 START_TEST(test_pi_handled_in_default) { 5183 const char *text = "<?test processing instruction?>\n<doc/>"; 5184 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>"); 5185 CharData storage; 5186 5187 CharData_Init(&storage); 5188 XML_SetDefaultHandler(g_parser, accumulate_characters); 5189 XML_SetUserData(g_parser, &storage); 5190 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5191 == XML_STATUS_ERROR) 5192 xml_failure(g_parser); 5193 CharData_CheckXMLChars(&storage, expected); 5194 } 5195 END_TEST 5196 5197 /* Test that comments are picked up by a default handler */ 5198 START_TEST(test_comment_handled_in_default) { 5199 const char *text = "<!-- This is a comment -->\n<doc/>"; 5200 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>"); 5201 CharData storage; 5202 5203 CharData_Init(&storage); 5204 XML_SetDefaultHandler(g_parser, accumulate_characters); 5205 XML_SetUserData(g_parser, &storage); 5206 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5207 == XML_STATUS_ERROR) 5208 xml_failure(g_parser); 5209 CharData_CheckXMLChars(&storage, expected); 5210 } 5211 END_TEST 5212 5213 /* Test PIs that look almost but not quite like XML declarations */ 5214 static void XMLCALL 5215 accumulate_pi_characters(void *userData, const XML_Char *target, 5216 const XML_Char *data) { 5217 CharData *storage = (CharData *)userData; 5218 5219 CharData_AppendXMLChars(storage, target, -1); 5220 CharData_AppendXMLChars(storage, XCS(": "), 2); 5221 CharData_AppendXMLChars(storage, data, -1); 5222 CharData_AppendXMLChars(storage, XCS("\n"), 1); 5223 } 5224 5225 START_TEST(test_pi_yml) { 5226 const char *text = "<?yml something like data?><doc/>"; 5227 const XML_Char *expected = XCS("yml: something like data\n"); 5228 CharData storage; 5229 5230 CharData_Init(&storage); 5231 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5232 XML_SetUserData(g_parser, &storage); 5233 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5234 == XML_STATUS_ERROR) 5235 xml_failure(g_parser); 5236 CharData_CheckXMLChars(&storage, expected); 5237 } 5238 END_TEST 5239 5240 START_TEST(test_pi_xnl) { 5241 const char *text = "<?xnl nothing like data?><doc/>"; 5242 const XML_Char *expected = XCS("xnl: nothing like data\n"); 5243 CharData storage; 5244 5245 CharData_Init(&storage); 5246 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5247 XML_SetUserData(g_parser, &storage); 5248 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5249 == XML_STATUS_ERROR) 5250 xml_failure(g_parser); 5251 CharData_CheckXMLChars(&storage, expected); 5252 } 5253 END_TEST 5254 5255 START_TEST(test_pi_xmm) { 5256 const char *text = "<?xmm everything like data?><doc/>"; 5257 const XML_Char *expected = XCS("xmm: everything like data\n"); 5258 CharData storage; 5259 5260 CharData_Init(&storage); 5261 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5262 XML_SetUserData(g_parser, &storage); 5263 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5264 == XML_STATUS_ERROR) 5265 xml_failure(g_parser); 5266 CharData_CheckXMLChars(&storage, expected); 5267 } 5268 END_TEST 5269 5270 START_TEST(test_utf16_pi) { 5271 const char text[] = 5272 /* <?{KHO KHWAI}{CHO CHAN}?> 5273 * where {KHO KHWAI} = U+0E04 5274 * and {CHO CHAN} = U+0E08 5275 */ 5276 "<\0?\0\x04\x0e\x08\x0e?\0>\0" 5277 /* <q/> */ 5278 "<\0q\0/\0>\0"; 5279 #ifdef XML_UNICODE 5280 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5281 #else 5282 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5283 #endif 5284 CharData storage; 5285 5286 CharData_Init(&storage); 5287 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5288 XML_SetUserData(g_parser, &storage); 5289 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5290 == XML_STATUS_ERROR) 5291 xml_failure(g_parser); 5292 CharData_CheckXMLChars(&storage, expected); 5293 } 5294 END_TEST 5295 5296 START_TEST(test_utf16_be_pi) { 5297 const char text[] = 5298 /* <?{KHO KHWAI}{CHO CHAN}?> 5299 * where {KHO KHWAI} = U+0E04 5300 * and {CHO CHAN} = U+0E08 5301 */ 5302 "\0<\0?\x0e\x04\x0e\x08\0?\0>" 5303 /* <q/> */ 5304 "\0<\0q\0/\0>"; 5305 #ifdef XML_UNICODE 5306 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5307 #else 5308 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5309 #endif 5310 CharData storage; 5311 5312 CharData_Init(&storage); 5313 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5314 XML_SetUserData(g_parser, &storage); 5315 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5316 == XML_STATUS_ERROR) 5317 xml_failure(g_parser); 5318 CharData_CheckXMLChars(&storage, expected); 5319 } 5320 END_TEST 5321 5322 /* Test that comments can be picked up and translated */ 5323 static void XMLCALL 5324 accumulate_comment(void *userData, const XML_Char *data) { 5325 CharData *storage = (CharData *)userData; 5326 5327 CharData_AppendXMLChars(storage, data, -1); 5328 } 5329 5330 START_TEST(test_utf16_be_comment) { 5331 const char text[] = 5332 /* <!-- Comment A --> */ 5333 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n" 5334 /* <doc/> */ 5335 "\0<\0d\0o\0c\0/\0>"; 5336 const XML_Char *expected = XCS(" Comment A "); 5337 CharData storage; 5338 5339 CharData_Init(&storage); 5340 XML_SetCommentHandler(g_parser, accumulate_comment); 5341 XML_SetUserData(g_parser, &storage); 5342 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5343 == XML_STATUS_ERROR) 5344 xml_failure(g_parser); 5345 CharData_CheckXMLChars(&storage, expected); 5346 } 5347 END_TEST 5348 5349 START_TEST(test_utf16_le_comment) { 5350 const char text[] = 5351 /* <!-- Comment B --> */ 5352 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0" 5353 /* <doc/> */ 5354 "<\0d\0o\0c\0/\0>\0"; 5355 const XML_Char *expected = XCS(" Comment B "); 5356 CharData storage; 5357 5358 CharData_Init(&storage); 5359 XML_SetCommentHandler(g_parser, accumulate_comment); 5360 XML_SetUserData(g_parser, &storage); 5361 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5362 == XML_STATUS_ERROR) 5363 xml_failure(g_parser); 5364 CharData_CheckXMLChars(&storage, expected); 5365 } 5366 END_TEST 5367 5368 /* Test that the unknown encoding handler with map entries that expect 5369 * conversion but no conversion function is faulted 5370 */ 5371 static int XMLCALL 5372 failing_converter(void *data, const char *s) { 5373 UNUSED_P(data); 5374 UNUSED_P(s); 5375 /* Always claim to have failed */ 5376 return -1; 5377 } 5378 5379 static int XMLCALL 5380 prefix_converter(void *data, const char *s) { 5381 UNUSED_P(data); 5382 /* If the first byte is 0xff, raise an error */ 5383 if (s[0] == (char)-1) 5384 return -1; 5385 /* Just add the low bits of the first byte to the second */ 5386 return (s[1] + (s[0] & 0x7f)) & 0x01ff; 5387 } 5388 5389 static int XMLCALL 5390 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) { 5391 int i; 5392 int high_map = -2; /* Assume a 2-byte sequence */ 5393 5394 if (! xcstrcmp(encoding, XCS("invalid-9")) 5395 || ! xcstrcmp(encoding, XCS("ascii-like")) 5396 || ! xcstrcmp(encoding, XCS("invalid-len")) 5397 || ! xcstrcmp(encoding, XCS("invalid-a")) 5398 || ! xcstrcmp(encoding, XCS("invalid-surrogate")) 5399 || ! xcstrcmp(encoding, XCS("invalid-high"))) 5400 high_map = -1; 5401 5402 for (i = 0; i < 128; ++i) 5403 info->map[i] = i; 5404 for (; i < 256; ++i) 5405 info->map[i] = high_map; 5406 5407 /* If required, put an invalid value in the ASCII entries */ 5408 if (! xcstrcmp(encoding, XCS("invalid-9"))) 5409 info->map[9] = 5; 5410 /* If required, have a top-bit set character starts a 5-byte sequence */ 5411 if (! xcstrcmp(encoding, XCS("invalid-len"))) 5412 info->map[0x81] = -5; 5413 /* If required, make a top-bit set character a valid ASCII character */ 5414 if (! xcstrcmp(encoding, XCS("invalid-a"))) 5415 info->map[0x82] = 'a'; 5416 /* If required, give a top-bit set character a forbidden value, 5417 * what would otherwise be the first of a surrogate pair. 5418 */ 5419 if (! xcstrcmp(encoding, XCS("invalid-surrogate"))) 5420 info->map[0x83] = 0xd801; 5421 /* If required, give a top-bit set character too high a value */ 5422 if (! xcstrcmp(encoding, XCS("invalid-high"))) 5423 info->map[0x84] = 0x010101; 5424 5425 info->data = data; 5426 info->release = NULL; 5427 if (! xcstrcmp(encoding, XCS("failing-conv"))) 5428 info->convert = failing_converter; 5429 else if (! xcstrcmp(encoding, XCS("prefix-conv"))) 5430 info->convert = prefix_converter; 5431 else 5432 info->convert = NULL; 5433 return XML_STATUS_OK; 5434 } 5435 5436 START_TEST(test_missing_encoding_conversion_fn) { 5437 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n" 5438 "<doc>\x81</doc>"; 5439 5440 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5441 /* MiscEncodingHandler sets up an encoding with every top-bit-set 5442 * character introducing a two-byte sequence. For this, it 5443 * requires a convert function. The above function call doesn't 5444 * pass one through, so when BadEncodingHandler actually gets 5445 * called it should supply an invalid encoding. 5446 */ 5447 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5448 "Encoding with missing convert() not faulted"); 5449 } 5450 END_TEST 5451 5452 START_TEST(test_failing_encoding_conversion_fn) { 5453 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n" 5454 "<doc>\x81</doc>"; 5455 5456 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5457 /* BadEncodingHandler sets up an encoding with every top-bit-set 5458 * character introducing a two-byte sequence. For this, it 5459 * requires a convert function. The above function call passes 5460 * one that insists all possible sequences are invalid anyway. 5461 */ 5462 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5463 "Encoding with failing convert() not faulted"); 5464 } 5465 END_TEST 5466 5467 /* Test unknown encoding conversions */ 5468 START_TEST(test_unknown_encoding_success) { 5469 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5470 /* Equivalent to <eoc>Hello, world</eoc> */ 5471 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>"; 5472 5473 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5474 run_character_check(text, XCS("Hello, world")); 5475 } 5476 END_TEST 5477 5478 /* Test bad name character in unknown encoding */ 5479 START_TEST(test_unknown_encoding_bad_name) { 5480 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5481 "<\xff\x64oc>Hello, world</\xff\x64oc>"; 5482 5483 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5484 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5485 "Bad name start in unknown encoding not faulted"); 5486 } 5487 END_TEST 5488 5489 /* Test bad mid-name character in unknown encoding */ 5490 START_TEST(test_unknown_encoding_bad_name_2) { 5491 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5492 "<d\xffoc>Hello, world</d\xffoc>"; 5493 5494 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5495 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5496 "Bad name in unknown encoding not faulted"); 5497 } 5498 END_TEST 5499 5500 /* Test element name that is long enough to fill the conversion buffer 5501 * in an unknown encoding, finishing with an encoded character. 5502 */ 5503 START_TEST(test_unknown_encoding_long_name_1) { 5504 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5505 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>" 5506 "Hi" 5507 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"; 5508 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5509 CharData storage; 5510 5511 CharData_Init(&storage); 5512 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5513 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5514 XML_SetUserData(g_parser, &storage); 5515 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5516 == XML_STATUS_ERROR) 5517 xml_failure(g_parser); 5518 CharData_CheckXMLChars(&storage, expected); 5519 } 5520 END_TEST 5521 5522 /* Test element name that is long enough to fill the conversion buffer 5523 * in an unknown encoding, finishing with an simple character. 5524 */ 5525 START_TEST(test_unknown_encoding_long_name_2) { 5526 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5527 "<abcdefghabcdefghabcdefghijklmnop>" 5528 "Hi" 5529 "</abcdefghabcdefghabcdefghijklmnop>"; 5530 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5531 CharData storage; 5532 5533 CharData_Init(&storage); 5534 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5535 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5536 XML_SetUserData(g_parser, &storage); 5537 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5538 == XML_STATUS_ERROR) 5539 xml_failure(g_parser); 5540 CharData_CheckXMLChars(&storage, expected); 5541 } 5542 END_TEST 5543 5544 START_TEST(test_invalid_unknown_encoding) { 5545 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n" 5546 "<doc>Hello world</doc>"; 5547 5548 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5549 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5550 "Invalid unknown encoding not faulted"); 5551 } 5552 END_TEST 5553 5554 START_TEST(test_unknown_ascii_encoding_ok) { 5555 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5556 "<doc>Hello, world</doc>"; 5557 5558 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5559 run_character_check(text, XCS("Hello, world")); 5560 } 5561 END_TEST 5562 5563 START_TEST(test_unknown_ascii_encoding_fail) { 5564 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5565 "<doc>Hello, \x80 world</doc>"; 5566 5567 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5568 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5569 "Invalid character not faulted"); 5570 } 5571 END_TEST 5572 5573 START_TEST(test_unknown_encoding_invalid_length) { 5574 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n" 5575 "<doc>Hello, world</doc>"; 5576 5577 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5578 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5579 "Invalid unknown encoding not faulted"); 5580 } 5581 END_TEST 5582 5583 START_TEST(test_unknown_encoding_invalid_topbit) { 5584 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n" 5585 "<doc>Hello, world</doc>"; 5586 5587 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5588 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5589 "Invalid unknown encoding not faulted"); 5590 } 5591 END_TEST 5592 5593 START_TEST(test_unknown_encoding_invalid_surrogate) { 5594 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n" 5595 "<doc>Hello, \x82 world</doc>"; 5596 5597 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5598 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5599 "Invalid unknown encoding not faulted"); 5600 } 5601 END_TEST 5602 5603 START_TEST(test_unknown_encoding_invalid_high) { 5604 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n" 5605 "<doc>Hello, world</doc>"; 5606 5607 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5608 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5609 "Invalid unknown encoding not faulted"); 5610 } 5611 END_TEST 5612 5613 START_TEST(test_unknown_encoding_invalid_attr_value) { 5614 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5615 "<doc attr='\xff\x30'/>"; 5616 5617 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5618 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5619 "Invalid attribute valid not faulted"); 5620 } 5621 END_TEST 5622 5623 /* Test an external entity parser set to use latin-1 detects UTF-16 5624 * BOMs correctly. 5625 */ 5626 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 }; 5627 5628 typedef struct ExtTest2 { 5629 const char *parse_text; 5630 int parse_len; 5631 const XML_Char *encoding; 5632 CharData *storage; 5633 enum ee_parse_flags flags; 5634 } ExtTest2; 5635 5636 static int XMLCALL 5637 external_entity_loader2(XML_Parser parser, const XML_Char *context, 5638 const XML_Char *base, const XML_Char *systemId, 5639 const XML_Char *publicId) { 5640 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser); 5641 XML_Parser extparser; 5642 5643 UNUSED_P(base); 5644 UNUSED_P(systemId); 5645 UNUSED_P(publicId); 5646 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 5647 if (extparser == NULL) 5648 fail("Coulr not create external entity parser"); 5649 if (test_data->encoding != NULL) { 5650 if (! XML_SetEncoding(extparser, test_data->encoding)) 5651 fail("XML_SetEncoding() ignored for external entity"); 5652 } 5653 if (test_data->flags & EE_PARSE_FULL_BUFFER) { 5654 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 5655 XML_TRUE) 5656 == XML_STATUS_ERROR) { 5657 xml_failure(extparser); 5658 } 5659 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text, 5660 test_data->parse_len, XML_TRUE) 5661 == XML_STATUS_ERROR) { 5662 xml_failure(extparser); 5663 } 5664 5665 XML_ParserFree(extparser); 5666 return XML_STATUS_OK; 5667 } 5668 5669 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */ 5670 static void XMLCALL 5671 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) { 5672 ExtTest2 *test_data = (ExtTest2 *)userData; 5673 accumulate_characters(test_data->storage, s, len); 5674 } 5675 5676 START_TEST(test_ext_entity_latin1_utf16le_bom) { 5677 const char *text = "<!DOCTYPE doc [\n" 5678 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5679 "]>\n" 5680 "<doc>&en;</doc>"; 5681 ExtTest2 test_data 5682 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5683 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5684 * 0x4c = L and 0x20 is a space 5685 */ 5686 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5687 #ifdef XML_UNICODE 5688 const XML_Char *expected = XCS("\x00ff\x00feL "); 5689 #else 5690 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5691 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5692 #endif 5693 CharData storage; 5694 5695 CharData_Init(&storage); 5696 test_data.storage = &storage; 5697 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5698 XML_SetUserData(g_parser, &test_data); 5699 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5700 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5701 == XML_STATUS_ERROR) 5702 xml_failure(g_parser); 5703 CharData_CheckXMLChars(&storage, expected); 5704 } 5705 END_TEST 5706 5707 START_TEST(test_ext_entity_latin1_utf16be_bom) { 5708 const char *text = "<!DOCTYPE doc [\n" 5709 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5710 "]>\n" 5711 "<doc>&en;</doc>"; 5712 ExtTest2 test_data 5713 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5714 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5715 * 0x4c = L and 0x20 is a space 5716 */ 5717 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5718 #ifdef XML_UNICODE 5719 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5720 #else 5721 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5722 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L"); 5723 #endif 5724 CharData storage; 5725 5726 CharData_Init(&storage); 5727 test_data.storage = &storage; 5728 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5729 XML_SetUserData(g_parser, &test_data); 5730 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5731 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5732 == XML_STATUS_ERROR) 5733 xml_failure(g_parser); 5734 CharData_CheckXMLChars(&storage, expected); 5735 } 5736 END_TEST 5737 5738 /* Parsing the full buffer rather than a byte at a time makes a 5739 * difference to the encoding scanning code, so repeat the above tests 5740 * without breaking them down by byte. 5741 */ 5742 START_TEST(test_ext_entity_latin1_utf16le_bom2) { 5743 const char *text = "<!DOCTYPE doc [\n" 5744 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5745 "]>\n" 5746 "<doc>&en;</doc>"; 5747 ExtTest2 test_data 5748 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5749 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5750 * 0x4c = L and 0x20 is a space 5751 */ 5752 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5753 #ifdef XML_UNICODE 5754 const XML_Char *expected = XCS("\x00ff\x00feL "); 5755 #else 5756 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5757 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5758 #endif 5759 CharData storage; 5760 5761 CharData_Init(&storage); 5762 test_data.storage = &storage; 5763 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5764 XML_SetUserData(g_parser, &test_data); 5765 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5766 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5767 == XML_STATUS_ERROR) 5768 xml_failure(g_parser); 5769 CharData_CheckXMLChars(&storage, expected); 5770 } 5771 END_TEST 5772 5773 START_TEST(test_ext_entity_latin1_utf16be_bom2) { 5774 const char *text = "<!DOCTYPE doc [\n" 5775 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5776 "]>\n" 5777 "<doc>&en;</doc>"; 5778 ExtTest2 test_data 5779 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5780 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5781 * 0x4c = L and 0x20 is a space 5782 */ 5783 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5784 #ifdef XML_UNICODE 5785 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5786 #else 5787 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5788 const XML_Char *expected = "\xc3\xbe\xc3\xbf L"; 5789 #endif 5790 CharData storage; 5791 5792 CharData_Init(&storage); 5793 test_data.storage = &storage; 5794 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5795 XML_SetUserData(g_parser, &test_data); 5796 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5797 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5798 == XML_STATUS_ERROR) 5799 xml_failure(g_parser); 5800 CharData_CheckXMLChars(&storage, expected); 5801 } 5802 END_TEST 5803 5804 /* Test little-endian UTF-16 given an explicit big-endian encoding */ 5805 START_TEST(test_ext_entity_utf16_be) { 5806 const char *text = "<!DOCTYPE doc [\n" 5807 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5808 "]>\n" 5809 "<doc>&en;</doc>"; 5810 ExtTest2 test_data 5811 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE}; 5812 #ifdef XML_UNICODE 5813 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 5814 #else 5815 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 5816 "\xe6\x94\x80" /* U+6500 */ 5817 "\xe2\xbc\x80" /* U+2F00 */ 5818 "\xe3\xb8\x80"); /* U+3E00 */ 5819 #endif 5820 CharData storage; 5821 5822 CharData_Init(&storage); 5823 test_data.storage = &storage; 5824 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5825 XML_SetUserData(g_parser, &test_data); 5826 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5827 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5828 == XML_STATUS_ERROR) 5829 xml_failure(g_parser); 5830 CharData_CheckXMLChars(&storage, expected); 5831 } 5832 END_TEST 5833 5834 /* Test big-endian UTF-16 given an explicit little-endian encoding */ 5835 START_TEST(test_ext_entity_utf16_le) { 5836 const char *text = "<!DOCTYPE doc [\n" 5837 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5838 "]>\n" 5839 "<doc>&en;</doc>"; 5840 ExtTest2 test_data 5841 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE}; 5842 #ifdef XML_UNICODE 5843 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 5844 #else 5845 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 5846 "\xe6\x94\x80" /* U+6500 */ 5847 "\xe2\xbc\x80" /* U+2F00 */ 5848 "\xe3\xb8\x80"); /* U+3E00 */ 5849 #endif 5850 CharData storage; 5851 5852 CharData_Init(&storage); 5853 test_data.storage = &storage; 5854 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5855 XML_SetUserData(g_parser, &test_data); 5856 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5857 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5858 == XML_STATUS_ERROR) 5859 xml_failure(g_parser); 5860 CharData_CheckXMLChars(&storage, expected); 5861 } 5862 END_TEST 5863 5864 /* Test little-endian UTF-16 given no explicit encoding. 5865 * The existing default encoding (UTF-8) is assumed to hold without a 5866 * BOM to contradict it, so the entity value will in fact provoke an 5867 * error because 0x00 is not a valid XML character. We parse the 5868 * whole buffer in one go rather than feeding it in byte by byte to 5869 * exercise different code paths in the initial scanning routines. 5870 */ 5871 typedef struct ExtFaults2 { 5872 const char *parse_text; 5873 int parse_len; 5874 const char *fail_text; 5875 const XML_Char *encoding; 5876 enum XML_Error error; 5877 } ExtFaults2; 5878 5879 static int XMLCALL 5880 external_entity_faulter2(XML_Parser parser, const XML_Char *context, 5881 const XML_Char *base, const XML_Char *systemId, 5882 const XML_Char *publicId) { 5883 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser); 5884 XML_Parser extparser; 5885 5886 UNUSED_P(base); 5887 UNUSED_P(systemId); 5888 UNUSED_P(publicId); 5889 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 5890 if (extparser == NULL) 5891 fail("Could not create external entity parser"); 5892 if (test_data->encoding != NULL) { 5893 if (! XML_SetEncoding(extparser, test_data->encoding)) 5894 fail("XML_SetEncoding() ignored for external entity"); 5895 } 5896 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 5897 XML_TRUE) 5898 != XML_STATUS_ERROR) 5899 fail(test_data->fail_text); 5900 if (XML_GetErrorCode(extparser) != test_data->error) 5901 xml_failure(extparser); 5902 5903 XML_ParserFree(extparser); 5904 return XML_STATUS_ERROR; 5905 } 5906 5907 START_TEST(test_ext_entity_utf16_unknown) { 5908 const char *text = "<!DOCTYPE doc [\n" 5909 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5910 "]>\n" 5911 "<doc>&en;</doc>"; 5912 ExtFaults2 test_data 5913 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL, 5914 XML_ERROR_INVALID_TOKEN}; 5915 5916 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2); 5917 XML_SetUserData(g_parser, &test_data); 5918 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 5919 "Invalid character should not have been accepted"); 5920 } 5921 END_TEST 5922 5923 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */ 5924 START_TEST(test_ext_entity_utf8_non_bom) { 5925 const char *text = "<!DOCTYPE doc [\n" 5926 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5927 "]>\n" 5928 "<doc>&en;</doc>"; 5929 ExtTest2 test_data 5930 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */ 5931 3, NULL, NULL, EE_PARSE_NONE}; 5932 #ifdef XML_UNICODE 5933 const XML_Char *expected = XCS("\xfec0"); 5934 #else 5935 const XML_Char *expected = XCS("\xef\xbb\x80"); 5936 #endif 5937 CharData storage; 5938 5939 CharData_Init(&storage); 5940 test_data.storage = &storage; 5941 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5942 XML_SetUserData(g_parser, &test_data); 5943 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5944 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5945 == XML_STATUS_ERROR) 5946 xml_failure(g_parser); 5947 CharData_CheckXMLChars(&storage, expected); 5948 } 5949 END_TEST 5950 5951 /* Test that UTF-8 in a CDATA section is correctly passed through */ 5952 START_TEST(test_utf8_in_cdata_section) { 5953 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>"; 5954 #ifdef XML_UNICODE 5955 const XML_Char *expected = XCS("one \x00e9 two"); 5956 #else 5957 const XML_Char *expected = XCS("one \xc3\xa9 two"); 5958 #endif 5959 5960 run_character_check(text, expected); 5961 } 5962 END_TEST 5963 5964 /* Test that little-endian UTF-16 in a CDATA section is handled */ 5965 START_TEST(test_utf8_in_cdata_section_2) { 5966 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>"; 5967 #ifdef XML_UNICODE 5968 const XML_Char *expected = XCS("\x00e9]\x00e9two"); 5969 #else 5970 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two"); 5971 #endif 5972 5973 run_character_check(text, expected); 5974 } 5975 END_TEST 5976 5977 /* Test trailing spaces in elements are accepted */ 5978 static void XMLCALL 5979 record_element_end_handler(void *userData, const XML_Char *name) { 5980 CharData *storage = (CharData *)userData; 5981 5982 CharData_AppendXMLChars(storage, XCS("/"), 1); 5983 CharData_AppendXMLChars(storage, name, -1); 5984 } 5985 5986 START_TEST(test_trailing_spaces_in_elements) { 5987 const char *text = "<doc >Hi</doc >"; 5988 const XML_Char *expected = XCS("doc/doc"); 5989 CharData storage; 5990 5991 CharData_Init(&storage); 5992 XML_SetElementHandler(g_parser, record_element_start_handler, 5993 record_element_end_handler); 5994 XML_SetUserData(g_parser, &storage); 5995 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5996 == XML_STATUS_ERROR) 5997 xml_failure(g_parser); 5998 CharData_CheckXMLChars(&storage, expected); 5999 } 6000 END_TEST 6001 6002 START_TEST(test_utf16_attribute) { 6003 const char text[] = 6004 /* <d {KHO KHWAI}{CHO CHAN}='a'/> 6005 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6006 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6007 */ 6008 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0"; 6009 const XML_Char *expected = XCS("a"); 6010 CharData storage; 6011 6012 CharData_Init(&storage); 6013 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6014 XML_SetUserData(g_parser, &storage); 6015 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6016 == XML_STATUS_ERROR) 6017 xml_failure(g_parser); 6018 CharData_CheckXMLChars(&storage, expected); 6019 } 6020 END_TEST 6021 6022 START_TEST(test_utf16_second_attr) { 6023 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/> 6024 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6025 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6026 */ 6027 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0" 6028 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0"; 6029 const XML_Char *expected = XCS("1"); 6030 CharData storage; 6031 6032 CharData_Init(&storage); 6033 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6034 XML_SetUserData(g_parser, &storage); 6035 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6036 == XML_STATUS_ERROR) 6037 xml_failure(g_parser); 6038 CharData_CheckXMLChars(&storage, expected); 6039 } 6040 END_TEST 6041 6042 START_TEST(test_attr_after_solidus) { 6043 const char *text = "<doc attr1='a' / attr2='b'>"; 6044 6045 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted"); 6046 } 6047 END_TEST 6048 6049 static void XMLCALL 6050 accumulate_entity_decl(void *userData, const XML_Char *entityName, 6051 int is_parameter_entity, const XML_Char *value, 6052 int value_length, const XML_Char *base, 6053 const XML_Char *systemId, const XML_Char *publicId, 6054 const XML_Char *notationName) { 6055 CharData *storage = (CharData *)userData; 6056 6057 UNUSED_P(is_parameter_entity); 6058 UNUSED_P(base); 6059 UNUSED_P(systemId); 6060 UNUSED_P(publicId); 6061 UNUSED_P(notationName); 6062 CharData_AppendXMLChars(storage, entityName, -1); 6063 CharData_AppendXMLChars(storage, XCS("="), 1); 6064 CharData_AppendXMLChars(storage, value, value_length); 6065 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6066 } 6067 6068 START_TEST(test_utf16_pe) { 6069 /* <!DOCTYPE doc [ 6070 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'> 6071 * %{KHO KHWAI}{CHO CHAN}; 6072 * ]> 6073 * <doc></doc> 6074 * 6075 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6076 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6077 */ 6078 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 6079 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 " 6080 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 " 6081 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n" 6082 "\0%\x0e\x04\x0e\x08\0;\0\n" 6083 "\0]\0>\0\n" 6084 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>"; 6085 #ifdef XML_UNICODE 6086 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n"); 6087 #else 6088 const XML_Char *expected 6089 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n"); 6090 #endif 6091 CharData storage; 6092 6093 CharData_Init(&storage); 6094 XML_SetUserData(g_parser, &storage); 6095 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl); 6096 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6097 == XML_STATUS_ERROR) 6098 xml_failure(g_parser); 6099 CharData_CheckXMLChars(&storage, expected); 6100 } 6101 END_TEST 6102 6103 /* Test that duff attribute description keywords are rejected */ 6104 START_TEST(test_bad_attr_desc_keyword) { 6105 const char *text = "<!DOCTYPE doc [\n" 6106 " <!ATTLIST doc attr CDATA #!IMPLIED>\n" 6107 "]>\n" 6108 "<doc />"; 6109 6110 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6111 "Bad keyword !IMPLIED not faulted"); 6112 } 6113 END_TEST 6114 6115 /* Test that an invalid attribute description keyword consisting of 6116 * UTF-16 characters with their top bytes non-zero are correctly 6117 * faulted 6118 */ 6119 START_TEST(test_bad_attr_desc_keyword_utf16) { 6120 /* <!DOCTYPE d [ 6121 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}> 6122 * ]><d/> 6123 * 6124 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6125 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6126 */ 6127 const char text[] 6128 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6129 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 " 6130 "\0#\x0e\x04\x0e\x08\0>\0\n" 6131 "\0]\0>\0<\0d\0/\0>"; 6132 6133 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6134 != XML_STATUS_ERROR) 6135 fail("Invalid UTF16 attribute keyword not faulted"); 6136 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6137 xml_failure(g_parser); 6138 } 6139 END_TEST 6140 6141 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this 6142 * using prefix-encoding (see above) to trigger specific code paths 6143 */ 6144 START_TEST(test_bad_doctype) { 6145 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 6146 "<!DOCTYPE doc [ \x80\x44 ]><doc/>"; 6147 6148 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6149 expect_failure(text, XML_ERROR_SYNTAX, 6150 "Invalid bytes in DOCTYPE not faulted"); 6151 } 6152 END_TEST 6153 6154 START_TEST(test_bad_doctype_utf16) { 6155 const char text[] = 6156 /* <!DOCTYPE doc [ \x06f2 ]><doc/> 6157 * 6158 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number 6159 * (name character) but not a valid letter (name start character) 6160 */ 6161 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 " 6162 "\x06\xf2" 6163 "\0 \0]\0>\0<\0d\0o\0c\0/\0>"; 6164 6165 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6166 != XML_STATUS_ERROR) 6167 fail("Invalid bytes in DOCTYPE not faulted"); 6168 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6169 xml_failure(g_parser); 6170 } 6171 END_TEST 6172 6173 START_TEST(test_bad_doctype_plus) { 6174 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n" 6175 "<1+>&foo;</1+>"; 6176 6177 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6178 "'+' in document name not faulted"); 6179 } 6180 END_TEST 6181 6182 START_TEST(test_bad_doctype_star) { 6183 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n" 6184 "<1*>&foo;</1*>"; 6185 6186 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6187 "'*' in document name not faulted"); 6188 } 6189 END_TEST 6190 6191 START_TEST(test_bad_doctype_query) { 6192 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n" 6193 "<1?>&foo;</1?>"; 6194 6195 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6196 "'?' in document name not faulted"); 6197 } 6198 END_TEST 6199 6200 START_TEST(test_unknown_encoding_bad_ignore) { 6201 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>" 6202 "<!DOCTYPE doc SYSTEM 'foo'>" 6203 "<doc><e>&entity;</e></doc>"; 6204 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>", 6205 "Invalid character not faulted", XCS("prefix-conv"), 6206 XML_ERROR_INVALID_TOKEN}; 6207 6208 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6209 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6210 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 6211 XML_SetUserData(g_parser, &fault); 6212 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 6213 "Bad IGNORE section with unknown encoding not failed"); 6214 } 6215 END_TEST 6216 6217 START_TEST(test_entity_in_utf16_be_attr) { 6218 const char text[] = 6219 /* <e a='ä ä'></e> */ 6220 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 " 6221 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>"; 6222 #ifdef XML_UNICODE 6223 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6224 #else 6225 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6226 #endif 6227 CharData storage; 6228 6229 CharData_Init(&storage); 6230 XML_SetUserData(g_parser, &storage); 6231 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6232 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6233 == XML_STATUS_ERROR) 6234 xml_failure(g_parser); 6235 CharData_CheckXMLChars(&storage, expected); 6236 } 6237 END_TEST 6238 6239 START_TEST(test_entity_in_utf16_le_attr) { 6240 const char text[] = 6241 /* <e a='ä ä'></e> */ 6242 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0" 6243 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0"; 6244 #ifdef XML_UNICODE 6245 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6246 #else 6247 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6248 #endif 6249 CharData storage; 6250 6251 CharData_Init(&storage); 6252 XML_SetUserData(g_parser, &storage); 6253 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6254 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6255 == XML_STATUS_ERROR) 6256 xml_failure(g_parser); 6257 CharData_CheckXMLChars(&storage, expected); 6258 } 6259 END_TEST 6260 6261 START_TEST(test_entity_public_utf16_be) { 6262 const char text[] = 6263 /* <!DOCTYPE d [ */ 6264 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6265 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6266 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 " 6267 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n" 6268 /* %e; */ 6269 "\0%\0e\0;\0\n" 6270 /* ]> */ 6271 "\0]\0>\0\n" 6272 /* <d>&j;</d> */ 6273 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>"; 6274 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6275 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>", 6276 34, NULL, NULL, EE_PARSE_NONE}; 6277 const XML_Char *expected = XCS("baz"); 6278 CharData storage; 6279 6280 CharData_Init(&storage); 6281 test_data.storage = &storage; 6282 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6283 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6284 XML_SetUserData(g_parser, &test_data); 6285 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6286 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6287 == XML_STATUS_ERROR) 6288 xml_failure(g_parser); 6289 CharData_CheckXMLChars(&storage, expected); 6290 } 6291 END_TEST 6292 6293 START_TEST(test_entity_public_utf16_le) { 6294 const char text[] = 6295 /* <!DOCTYPE d [ */ 6296 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0" 6297 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6298 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0" 6299 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0" 6300 /* %e; */ 6301 "%\0e\0;\0\n\0" 6302 /* ]> */ 6303 "]\0>\0\n\0" 6304 /* <d>&j;</d> */ 6305 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0"; 6306 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6307 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0", 6308 34, NULL, NULL, EE_PARSE_NONE}; 6309 const XML_Char *expected = XCS("baz"); 6310 CharData storage; 6311 6312 CharData_Init(&storage); 6313 test_data.storage = &storage; 6314 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6315 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6316 XML_SetUserData(g_parser, &test_data); 6317 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6318 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6319 == XML_STATUS_ERROR) 6320 xml_failure(g_parser); 6321 CharData_CheckXMLChars(&storage, expected); 6322 } 6323 END_TEST 6324 6325 /* Test that a doctype with neither an internal nor external subset is 6326 * faulted 6327 */ 6328 START_TEST(test_short_doctype) { 6329 const char *text = "<!DOCTYPE doc></doc>"; 6330 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6331 "DOCTYPE without subset not rejected"); 6332 } 6333 END_TEST 6334 6335 START_TEST(test_short_doctype_2) { 6336 const char *text = "<!DOCTYPE doc PUBLIC></doc>"; 6337 expect_failure(text, XML_ERROR_SYNTAX, 6338 "DOCTYPE without Public ID not rejected"); 6339 } 6340 END_TEST 6341 6342 START_TEST(test_short_doctype_3) { 6343 const char *text = "<!DOCTYPE doc SYSTEM></doc>"; 6344 expect_failure(text, XML_ERROR_SYNTAX, 6345 "DOCTYPE without System ID not rejected"); 6346 } 6347 END_TEST 6348 6349 START_TEST(test_long_doctype) { 6350 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>"; 6351 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected"); 6352 } 6353 END_TEST 6354 6355 START_TEST(test_bad_entity) { 6356 const char *text = "<!DOCTYPE doc [\n" 6357 " <!ENTITY foo PUBLIC>\n" 6358 "]>\n" 6359 "<doc/>"; 6360 expect_failure(text, XML_ERROR_SYNTAX, 6361 "ENTITY without Public ID is not rejected"); 6362 } 6363 END_TEST 6364 6365 /* Test unquoted value is faulted */ 6366 START_TEST(test_bad_entity_2) { 6367 const char *text = "<!DOCTYPE doc [\n" 6368 " <!ENTITY % foo bar>\n" 6369 "]>\n" 6370 "<doc/>"; 6371 expect_failure(text, XML_ERROR_SYNTAX, 6372 "ENTITY without Public ID is not rejected"); 6373 } 6374 END_TEST 6375 6376 START_TEST(test_bad_entity_3) { 6377 const char *text = "<!DOCTYPE doc [\n" 6378 " <!ENTITY % foo PUBLIC>\n" 6379 "]>\n" 6380 "<doc/>"; 6381 expect_failure(text, XML_ERROR_SYNTAX, 6382 "Parameter ENTITY without Public ID is not rejected"); 6383 } 6384 END_TEST 6385 6386 START_TEST(test_bad_entity_4) { 6387 const char *text = "<!DOCTYPE doc [\n" 6388 " <!ENTITY % foo SYSTEM>\n" 6389 "]>\n" 6390 "<doc/>"; 6391 expect_failure(text, XML_ERROR_SYNTAX, 6392 "Parameter ENTITY without Public ID is not rejected"); 6393 } 6394 END_TEST 6395 6396 START_TEST(test_bad_notation) { 6397 const char *text = "<!DOCTYPE doc [\n" 6398 " <!NOTATION n SYSTEM>\n" 6399 "]>\n" 6400 "<doc/>"; 6401 expect_failure(text, XML_ERROR_SYNTAX, 6402 "Notation without System ID is not rejected"); 6403 } 6404 END_TEST 6405 6406 /* Test for issue #11, wrongly suppressed default handler */ 6407 typedef struct default_check { 6408 const XML_Char *expected; 6409 const int expectedLen; 6410 XML_Bool seen; 6411 } DefaultCheck; 6412 6413 static void XMLCALL 6414 checking_default_handler(void *userData, const XML_Char *s, int len) { 6415 DefaultCheck *data = (DefaultCheck *)userData; 6416 int i; 6417 6418 for (i = 0; data[i].expected != NULL; i++) { 6419 if (data[i].expectedLen == len 6420 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) { 6421 data[i].seen = XML_TRUE; 6422 break; 6423 } 6424 } 6425 } 6426 6427 START_TEST(test_default_doctype_handler) { 6428 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n" 6429 " <!ENTITY foo 'bar'>\n" 6430 "]>\n" 6431 "<doc>&foo;</doc>"; 6432 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE}, 6433 {XCS("'test.dtd'"), 10, XML_FALSE}, 6434 {NULL, 0, XML_FALSE}}; 6435 int i; 6436 6437 XML_SetUserData(g_parser, &test_data); 6438 XML_SetDefaultHandler(g_parser, checking_default_handler); 6439 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 6440 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6441 == XML_STATUS_ERROR) 6442 xml_failure(g_parser); 6443 for (i = 0; test_data[i].expected != NULL; i++) 6444 if (! test_data[i].seen) 6445 fail("Default handler not run for public !DOCTYPE"); 6446 } 6447 END_TEST 6448 6449 START_TEST(test_empty_element_abort) { 6450 const char *text = "<abort/>"; 6451 6452 XML_SetStartElementHandler(g_parser, start_element_suspender); 6453 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6454 != XML_STATUS_ERROR) 6455 fail("Expected to error on abort"); 6456 } 6457 END_TEST 6458 6459 /* 6460 * Namespaces tests. 6461 */ 6462 6463 static void 6464 namespace_setup(void) { 6465 g_parser = XML_ParserCreateNS(NULL, XCS(' ')); 6466 if (g_parser == NULL) 6467 fail("Parser not created."); 6468 } 6469 6470 static void 6471 namespace_teardown(void) { 6472 basic_teardown(); 6473 } 6474 6475 /* Check that an element name and attribute name match the expected values. 6476 The expected values are passed as an array reference of string pointers 6477 provided as the userData argument; the first is the expected 6478 element name, and the second is the expected attribute name. 6479 */ 6480 static int triplet_start_flag = XML_FALSE; 6481 static int triplet_end_flag = XML_FALSE; 6482 6483 static void XMLCALL 6484 triplet_start_checker(void *userData, const XML_Char *name, 6485 const XML_Char **atts) { 6486 XML_Char **elemstr = (XML_Char **)userData; 6487 char buffer[1024]; 6488 if (xcstrcmp(elemstr[0], name) != 0) { 6489 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name); 6490 fail(buffer); 6491 } 6492 if (xcstrcmp(elemstr[1], atts[0]) != 0) { 6493 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]); 6494 fail(buffer); 6495 } 6496 triplet_start_flag = XML_TRUE; 6497 } 6498 6499 /* Check that the element name passed to the end-element handler matches 6500 the expected value. The expected value is passed as the first element 6501 in an array of strings passed as the userData argument. 6502 */ 6503 static void XMLCALL 6504 triplet_end_checker(void *userData, const XML_Char *name) { 6505 XML_Char **elemstr = (XML_Char **)userData; 6506 if (xcstrcmp(elemstr[0], name) != 0) { 6507 char buffer[1024]; 6508 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name); 6509 fail(buffer); 6510 } 6511 triplet_end_flag = XML_TRUE; 6512 } 6513 6514 START_TEST(test_return_ns_triplet) { 6515 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 6516 " xmlns:bar='http://example.org/'>"; 6517 const char *epilog = "</foo:e>"; 6518 const XML_Char *elemstr[] 6519 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")}; 6520 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6521 XML_SetUserData(g_parser, (void *)elemstr); 6522 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 6523 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler, 6524 dummy_end_namespace_decl_handler); 6525 triplet_start_flag = XML_FALSE; 6526 triplet_end_flag = XML_FALSE; 6527 dummy_handler_flags = 0; 6528 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 6529 == XML_STATUS_ERROR) 6530 xml_failure(g_parser); 6531 if (! triplet_start_flag) 6532 fail("triplet_start_checker not invoked"); 6533 /* Check that unsetting "return triplets" fails while still parsing */ 6534 XML_SetReturnNSTriplet(g_parser, XML_FALSE); 6535 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 6536 == XML_STATUS_ERROR) 6537 xml_failure(g_parser); 6538 if (! triplet_end_flag) 6539 fail("triplet_end_checker not invoked"); 6540 if (dummy_handler_flags 6541 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG)) 6542 fail("Namespace handlers not called"); 6543 } 6544 END_TEST 6545 6546 static void XMLCALL 6547 overwrite_start_checker(void *userData, const XML_Char *name, 6548 const XML_Char **atts) { 6549 CharData *storage = (CharData *)userData; 6550 CharData_AppendXMLChars(storage, XCS("start "), 6); 6551 CharData_AppendXMLChars(storage, name, -1); 6552 while (*atts != NULL) { 6553 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11); 6554 CharData_AppendXMLChars(storage, *atts, -1); 6555 atts += 2; 6556 } 6557 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6558 } 6559 6560 static void XMLCALL 6561 overwrite_end_checker(void *userData, const XML_Char *name) { 6562 CharData *storage = (CharData *)userData; 6563 CharData_AppendXMLChars(storage, XCS("end "), 4); 6564 CharData_AppendXMLChars(storage, name, -1); 6565 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6566 } 6567 6568 static void 6569 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) { 6570 CharData storage; 6571 CharData_Init(&storage); 6572 XML_SetUserData(g_parser, &storage); 6573 XML_SetElementHandler(g_parser, overwrite_start_checker, 6574 overwrite_end_checker); 6575 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6576 == XML_STATUS_ERROR) 6577 xml_failure(g_parser); 6578 CharData_CheckXMLChars(&storage, result); 6579 } 6580 6581 /* Regression test for SF bug #566334. */ 6582 START_TEST(test_ns_tagname_overwrite) { 6583 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6584 " <n:f n:attr='foo'/>\n" 6585 " <n:g n:attr2='bar'/>\n" 6586 "</n:e>"; 6587 const XML_Char *result = XCS("start http://example.org/ e\n") 6588 XCS("start http://example.org/ f\n") 6589 XCS("attribute http://example.org/ attr\n") 6590 XCS("end http://example.org/ f\n") 6591 XCS("start http://example.org/ g\n") 6592 XCS("attribute http://example.org/ attr2\n") 6593 XCS("end http://example.org/ g\n") 6594 XCS("end http://example.org/ e\n"); 6595 run_ns_tagname_overwrite_test(text, result); 6596 } 6597 END_TEST 6598 6599 /* Regression test for SF bug #566334. */ 6600 START_TEST(test_ns_tagname_overwrite_triplet) { 6601 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6602 " <n:f n:attr='foo'/>\n" 6603 " <n:g n:attr2='bar'/>\n" 6604 "</n:e>"; 6605 const XML_Char *result = XCS("start http://example.org/ e n\n") 6606 XCS("start http://example.org/ f n\n") 6607 XCS("attribute http://example.org/ attr n\n") 6608 XCS("end http://example.org/ f n\n") 6609 XCS("start http://example.org/ g n\n") 6610 XCS("attribute http://example.org/ attr2 n\n") 6611 XCS("end http://example.org/ g n\n") 6612 XCS("end http://example.org/ e n\n"); 6613 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6614 run_ns_tagname_overwrite_test(text, result); 6615 } 6616 END_TEST 6617 6618 /* Regression test for SF bug #620343. */ 6619 static void XMLCALL 6620 start_element_fail(void *userData, const XML_Char *name, 6621 const XML_Char **atts) { 6622 UNUSED_P(userData); 6623 UNUSED_P(name); 6624 UNUSED_P(atts); 6625 6626 /* We should never get here. */ 6627 fail("should never reach start_element_fail()"); 6628 } 6629 6630 static void XMLCALL 6631 start_ns_clearing_start_element(void *userData, const XML_Char *prefix, 6632 const XML_Char *uri) { 6633 UNUSED_P(prefix); 6634 UNUSED_P(uri); 6635 XML_SetStartElementHandler((XML_Parser)userData, NULL); 6636 } 6637 6638 START_TEST(test_start_ns_clears_start_element) { 6639 /* This needs to use separate start/end tags; using the empty tag 6640 syntax doesn't cause the problematic path through Expat to be 6641 taken. 6642 */ 6643 const char *text = "<e xmlns='http://example.org/'></e>"; 6644 6645 XML_SetStartElementHandler(g_parser, start_element_fail); 6646 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element); 6647 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 6648 XML_UseParserAsHandlerArg(g_parser); 6649 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6650 == XML_STATUS_ERROR) 6651 xml_failure(g_parser); 6652 } 6653 END_TEST 6654 6655 /* Regression test for SF bug #616863. */ 6656 static int XMLCALL 6657 external_entity_handler(XML_Parser parser, const XML_Char *context, 6658 const XML_Char *base, const XML_Char *systemId, 6659 const XML_Char *publicId) { 6660 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser); 6661 const char *text; 6662 XML_Parser p2; 6663 6664 UNUSED_P(base); 6665 UNUSED_P(systemId); 6666 UNUSED_P(publicId); 6667 if (callno == 1) 6668 text = ("<!ELEMENT doc (e+)>\n" 6669 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 6670 "<!ELEMENT e EMPTY>\n"); 6671 else 6672 text = ("<?xml version='1.0' encoding='us-ascii'?>" 6673 "<e/>"); 6674 6675 XML_SetUserData(parser, (void *)callno); 6676 p2 = XML_ExternalEntityParserCreate(parser, context, NULL); 6677 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE) 6678 == XML_STATUS_ERROR) { 6679 xml_failure(p2); 6680 return XML_STATUS_ERROR; 6681 } 6682 XML_ParserFree(p2); 6683 return XML_STATUS_OK; 6684 } 6685 6686 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) { 6687 const char *text = "<?xml version='1.0'?>\n" 6688 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 6689 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 6690 "]>\n" 6691 "<doc xmlns='http://example.org/ns1'>\n" 6692 "&en;\n" 6693 "</doc>"; 6694 6695 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6696 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler); 6697 /* We actually need to set this handler to tickle this bug. */ 6698 XML_SetStartElementHandler(g_parser, dummy_start_element); 6699 XML_SetUserData(g_parser, NULL); 6700 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6701 == XML_STATUS_ERROR) 6702 xml_failure(g_parser); 6703 } 6704 END_TEST 6705 6706 /* Regression test #1 for SF bug #673791. */ 6707 START_TEST(test_ns_prefix_with_empty_uri_1) { 6708 const char *text = "<doc xmlns:prefix='http://example.org/'>\n" 6709 " <e xmlns:prefix=''/>\n" 6710 "</doc>"; 6711 6712 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6713 "Did not report re-setting namespace" 6714 " URI with prefix to ''."); 6715 } 6716 END_TEST 6717 6718 /* Regression test #2 for SF bug #673791. */ 6719 START_TEST(test_ns_prefix_with_empty_uri_2) { 6720 const char *text = "<?xml version='1.0'?>\n" 6721 "<docelem xmlns:pre=''/>"; 6722 6723 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6724 "Did not report setting namespace URI with prefix to ''."); 6725 } 6726 END_TEST 6727 6728 /* Regression test #3 for SF bug #673791. */ 6729 START_TEST(test_ns_prefix_with_empty_uri_3) { 6730 const char *text = "<!DOCTYPE doc [\n" 6731 " <!ELEMENT doc EMPTY>\n" 6732 " <!ATTLIST doc\n" 6733 " xmlns:prefix CDATA ''>\n" 6734 "]>\n" 6735 "<doc/>"; 6736 6737 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6738 "Didn't report attr default setting NS w/ prefix to ''."); 6739 } 6740 END_TEST 6741 6742 /* Regression test #4 for SF bug #673791. */ 6743 START_TEST(test_ns_prefix_with_empty_uri_4) { 6744 const char *text = "<!DOCTYPE doc [\n" 6745 " <!ELEMENT prefix:doc EMPTY>\n" 6746 " <!ATTLIST prefix:doc\n" 6747 " xmlns:prefix CDATA 'http://example.org/'>\n" 6748 "]>\n" 6749 "<prefix:doc/>"; 6750 /* Packaged info expected by the end element handler; 6751 the weird structuring lets us re-use the triplet_end_checker() 6752 function also used for another test. */ 6753 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")}; 6754 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6755 XML_SetUserData(g_parser, (void *)elemstr); 6756 XML_SetEndElementHandler(g_parser, triplet_end_checker); 6757 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6758 == XML_STATUS_ERROR) 6759 xml_failure(g_parser); 6760 } 6761 END_TEST 6762 6763 /* Test with non-xmlns prefix */ 6764 START_TEST(test_ns_unbound_prefix) { 6765 const char *text = "<!DOCTYPE doc [\n" 6766 " <!ELEMENT prefix:doc EMPTY>\n" 6767 " <!ATTLIST prefix:doc\n" 6768 " notxmlns:prefix CDATA 'http://example.org/'>\n" 6769 "]>\n" 6770 "<prefix:doc/>"; 6771 6772 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6773 != XML_STATUS_ERROR) 6774 fail("Unbound prefix incorrectly passed"); 6775 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX) 6776 xml_failure(g_parser); 6777 } 6778 END_TEST 6779 6780 START_TEST(test_ns_default_with_empty_uri) { 6781 const char *text = "<doc xmlns='http://example.org/'>\n" 6782 " <e xmlns=''/>\n" 6783 "</doc>"; 6784 /* Add some handlers to exercise extra code paths */ 6785 XML_SetStartNamespaceDeclHandler(g_parser, 6786 dummy_start_namespace_decl_handler); 6787 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 6788 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6789 == XML_STATUS_ERROR) 6790 xml_failure(g_parser); 6791 } 6792 END_TEST 6793 6794 /* Regression test for SF bug #692964: two prefixes for one namespace. */ 6795 START_TEST(test_ns_duplicate_attrs_diff_prefixes) { 6796 const char *text = "<doc xmlns:a='http://example.org/a'\n" 6797 " xmlns:b='http://example.org/a'\n" 6798 " a:a='v' b:a='v' />"; 6799 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE, 6800 "did not report multiple attributes with same URI+name"); 6801 } 6802 END_TEST 6803 6804 START_TEST(test_ns_duplicate_hashes) { 6805 /* The hash of an attribute is calculated as the hash of its URI 6806 * concatenated with a space followed by its name (after the 6807 * colon). We wish to generate attributes with the same hash 6808 * value modulo the attribute table size so that we can check that 6809 * the attribute hash table works correctly. The attribute hash 6810 * table size will be the smallest power of two greater than the 6811 * number of attributes, but at least eight. There is 6812 * unfortunately no programmatic way of getting the hash or the 6813 * table size at user level, but the test code coverage percentage 6814 * will drop if the hashes cease to point to the same row. 6815 * 6816 * The cunning plan is to have few enough attributes to have a 6817 * reliable table size of 8, and have the single letter attribute 6818 * names be 8 characters apart, producing a hash which will be the 6819 * same modulo 8. 6820 */ 6821 const char *text = "<doc xmlns:a='http://example.org/a'\n" 6822 " a:a='v' a:i='w' />"; 6823 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6824 == XML_STATUS_ERROR) 6825 xml_failure(g_parser); 6826 } 6827 END_TEST 6828 6829 /* Regression test for SF bug #695401: unbound prefix. */ 6830 START_TEST(test_ns_unbound_prefix_on_attribute) { 6831 const char *text = "<doc a:attr=''/>"; 6832 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 6833 "did not report unbound prefix on attribute"); 6834 } 6835 END_TEST 6836 6837 /* Regression test for SF bug #695401: unbound prefix. */ 6838 START_TEST(test_ns_unbound_prefix_on_element) { 6839 const char *text = "<a:doc/>"; 6840 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 6841 "did not report unbound prefix on element"); 6842 } 6843 END_TEST 6844 6845 /* Test that the parsing status is correctly reset by XML_ParserReset(). 6846 * We usE test_return_ns_triplet() for our example parse to improve 6847 * coverage of tidying up code executed. 6848 */ 6849 START_TEST(test_ns_parser_reset) { 6850 XML_ParsingStatus status; 6851 6852 XML_GetParsingStatus(g_parser, &status); 6853 if (status.parsing != XML_INITIALIZED) 6854 fail("parsing status doesn't start INITIALIZED"); 6855 test_return_ns_triplet(); 6856 XML_GetParsingStatus(g_parser, &status); 6857 if (status.parsing != XML_FINISHED) 6858 fail("parsing status doesn't end FINISHED"); 6859 XML_ParserReset(g_parser, NULL); 6860 XML_GetParsingStatus(g_parser, &status); 6861 if (status.parsing != XML_INITIALIZED) 6862 fail("parsing status doesn't reset to INITIALIZED"); 6863 } 6864 END_TEST 6865 6866 /* Test that long element names with namespaces are handled correctly */ 6867 START_TEST(test_ns_long_element) { 6868 const char *text 6869 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 6870 " xmlns:foo='http://example.org/' bar:a='12'\n" 6871 " xmlns:bar='http://example.org/'>" 6872 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 6873 const XML_Char *elemstr[] 6874 = {XCS("http://example.org/") 6875 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 6876 XCS("http://example.org/ a bar")}; 6877 6878 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6879 XML_SetUserData(g_parser, (void *)elemstr); 6880 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 6881 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6882 == XML_STATUS_ERROR) 6883 xml_failure(g_parser); 6884 } 6885 END_TEST 6886 6887 /* Test mixed population of prefixed and unprefixed attributes */ 6888 START_TEST(test_ns_mixed_prefix_atts) { 6889 const char *text = "<e a='12' bar:b='13'\n" 6890 " xmlns:bar='http://example.org/'>" 6891 "</e>"; 6892 6893 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6894 == XML_STATUS_ERROR) 6895 xml_failure(g_parser); 6896 } 6897 END_TEST 6898 6899 /* Test having a long namespaced element name inside a short one. 6900 * This exercises some internal buffer reallocation that is shared 6901 * across elements with the same namespace URI. 6902 */ 6903 START_TEST(test_ns_extend_uri_buffer) { 6904 const char *text = "<foo:e xmlns:foo='http://example.org/'>" 6905 " <foo:thisisalongenoughnametotriggerallocationaction" 6906 " foo:a='12' />" 6907 "</foo:e>"; 6908 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6909 == XML_STATUS_ERROR) 6910 xml_failure(g_parser); 6911 } 6912 END_TEST 6913 6914 /* Test that xmlns is correctly rejected as an attribute in the xmlns 6915 * namespace, but not in other namespaces 6916 */ 6917 START_TEST(test_ns_reserved_attributes) { 6918 const char *text1 6919 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />"; 6920 const char *text2 6921 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />"; 6922 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS, 6923 "xmlns not rejected as an attribute"); 6924 XML_ParserReset(g_parser, NULL); 6925 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 6926 == XML_STATUS_ERROR) 6927 xml_failure(g_parser); 6928 } 6929 END_TEST 6930 6931 /* Test more reserved attributes */ 6932 START_TEST(test_ns_reserved_attributes_2) { 6933 const char *text1 = "<foo:e xmlns:foo='http://example.org/'" 6934 " xmlns:xml='http://example.org/' />"; 6935 const char *text2 6936 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />"; 6937 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />"; 6938 6939 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML, 6940 "xml not rejected as an attribute"); 6941 XML_ParserReset(g_parser, NULL); 6942 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI, 6943 "Use of w3.org URL not faulted"); 6944 XML_ParserReset(g_parser, NULL); 6945 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI, 6946 "Use of w3.org xmlns URL not faulted"); 6947 } 6948 END_TEST 6949 6950 /* Test string pool handling of namespace names of 2048 characters */ 6951 /* Exercises a particular string pool growth path */ 6952 START_TEST(test_ns_extremely_long_prefix) { 6953 /* C99 compilers are only required to support 4095-character 6954 * strings, so the following needs to be split in two to be safe 6955 * for all compilers. 6956 */ 6957 const char *text1 6958 = "<doc " 6959 /* 64 character on each line */ 6960 /* ...gives a total length of 2048 */ 6961 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6962 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6963 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6964 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6965 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6966 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6967 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6968 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6969 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6970 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6971 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6972 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6973 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6974 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6975 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6976 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6982 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6983 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6984 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6985 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6986 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6987 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6988 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6989 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6990 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6991 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6992 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6993 ":a='12'"; 6994 const char *text2 6995 = " xmlns:" 6996 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6997 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6998 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 6999 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7000 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7001 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7002 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7003 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7004 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7005 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7006 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7013 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7023 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7024 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7025 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7026 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7027 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7028 "='foo'\n>" 7029 "</doc>"; 7030 7031 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 7032 == XML_STATUS_ERROR) 7033 xml_failure(g_parser); 7034 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7035 == XML_STATUS_ERROR) 7036 xml_failure(g_parser); 7037 } 7038 END_TEST 7039 7040 /* Test unknown encoding handlers in namespace setup */ 7041 START_TEST(test_ns_unknown_encoding_success) { 7042 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 7043 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>"; 7044 7045 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7046 run_character_check(text, XCS("Hi")); 7047 } 7048 END_TEST 7049 7050 /* Test that too many colons are rejected */ 7051 START_TEST(test_ns_double_colon) { 7052 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />"; 7053 const enum XML_Status status 7054 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7055 #ifdef XML_NS 7056 if ((status == XML_STATUS_OK) 7057 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7058 fail("Double colon in attribute name not faulted" 7059 " (despite active namespace support)"); 7060 } 7061 #else 7062 if (status != XML_STATUS_OK) { 7063 fail("Double colon in attribute name faulted" 7064 " (despite inactive namespace support"); 7065 } 7066 #endif 7067 } 7068 END_TEST 7069 7070 START_TEST(test_ns_double_colon_element) { 7071 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />"; 7072 const enum XML_Status status 7073 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7074 #ifdef XML_NS 7075 if ((status == XML_STATUS_OK) 7076 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7077 fail("Double colon in element name not faulted" 7078 " (despite active namespace support)"); 7079 } 7080 #else 7081 if (status != XML_STATUS_OK) { 7082 fail("Double colon in element name faulted" 7083 " (despite inactive namespace support"); 7084 } 7085 #endif 7086 } 7087 END_TEST 7088 7089 /* Test that non-name characters after a colon are rejected */ 7090 START_TEST(test_ns_bad_attr_leafname) { 7091 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />"; 7092 7093 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7094 "Invalid character in leafname not faulted"); 7095 } 7096 END_TEST 7097 7098 START_TEST(test_ns_bad_element_leafname) { 7099 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />"; 7100 7101 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7102 "Invalid character in element leafname not faulted"); 7103 } 7104 END_TEST 7105 7106 /* Test high-byte-set UTF-16 characters are valid in a leafname */ 7107 START_TEST(test_ns_utf16_leafname) { 7108 const char text[] = 7109 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' /> 7110 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7111 */ 7112 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0" 7113 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0"; 7114 const XML_Char *expected = XCS("a"); 7115 CharData storage; 7116 7117 CharData_Init(&storage); 7118 XML_SetStartElementHandler(g_parser, accumulate_attribute); 7119 XML_SetUserData(g_parser, &storage); 7120 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7121 == XML_STATUS_ERROR) 7122 xml_failure(g_parser); 7123 CharData_CheckXMLChars(&storage, expected); 7124 } 7125 END_TEST 7126 7127 START_TEST(test_ns_utf16_element_leafname) { 7128 const char text[] = 7129 /* <n:{KHO KHWAI} xmlns:n='URI'/> 7130 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7131 */ 7132 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>"; 7133 #ifdef XML_UNICODE 7134 const XML_Char *expected = XCS("URI \x0e04"); 7135 #else 7136 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7137 #endif 7138 CharData storage; 7139 7140 CharData_Init(&storage); 7141 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7142 XML_SetUserData(g_parser, &storage); 7143 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7144 == XML_STATUS_ERROR) 7145 xml_failure(g_parser); 7146 CharData_CheckXMLChars(&storage, expected); 7147 } 7148 END_TEST 7149 7150 START_TEST(test_ns_utf16_doctype) { 7151 const char text[] = 7152 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n 7153 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7154 */ 7155 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 " 7156 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 " 7157 "\0]\0>\0\n" 7158 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */ 7159 "\0<\0f\0o\0o\0:\x0e\x04\0 " 7160 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>" 7161 "\0&\0b\0a\0r\0;" 7162 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>"; 7163 #ifdef XML_UNICODE 7164 const XML_Char *expected = XCS("URI \x0e04"); 7165 #else 7166 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7167 #endif 7168 CharData storage; 7169 7170 CharData_Init(&storage); 7171 XML_SetUserData(g_parser, &storage); 7172 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7173 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7174 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7175 == XML_STATUS_ERROR) 7176 xml_failure(g_parser); 7177 CharData_CheckXMLChars(&storage, expected); 7178 } 7179 END_TEST 7180 7181 START_TEST(test_ns_invalid_doctype) { 7182 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n" 7183 "<foo:!bad>&bar;</foo:!bad>"; 7184 7185 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7186 "Invalid character in document local name not faulted"); 7187 } 7188 END_TEST 7189 7190 START_TEST(test_ns_double_colon_doctype) { 7191 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n" 7192 "<foo:a:doc>&bar;</foo:a:doc>"; 7193 7194 expect_failure(text, XML_ERROR_SYNTAX, 7195 "Double colon in document name not faulted"); 7196 } 7197 END_TEST 7198 7199 /* Control variable; the number of times duff_allocator() will successfully 7200 * allocate */ 7201 #define ALLOC_ALWAYS_SUCCEED (-1) 7202 #define REALLOC_ALWAYS_SUCCEED (-1) 7203 7204 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED; 7205 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED; 7206 7207 /* Crocked allocator for allocation failure tests */ 7208 static void * 7209 duff_allocator(size_t size) { 7210 if (allocation_count == 0) 7211 return NULL; 7212 if (allocation_count != ALLOC_ALWAYS_SUCCEED) 7213 allocation_count--; 7214 return malloc(size); 7215 } 7216 7217 /* Crocked reallocator for allocation failure tests */ 7218 static void * 7219 duff_reallocator(void *ptr, size_t size) { 7220 if (reallocation_count == 0) 7221 return NULL; 7222 if (reallocation_count != REALLOC_ALWAYS_SUCCEED) 7223 reallocation_count--; 7224 return realloc(ptr, size); 7225 } 7226 7227 /* Test that a failure to allocate the parser structure fails gracefully */ 7228 START_TEST(test_misc_alloc_create_parser) { 7229 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7230 unsigned int i; 7231 const unsigned int max_alloc_count = 10; 7232 7233 /* Something this simple shouldn't need more than 10 allocations */ 7234 for (i = 0; i < max_alloc_count; i++) { 7235 allocation_count = i; 7236 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7237 if (g_parser != NULL) 7238 break; 7239 } 7240 if (i == 0) 7241 fail("Parser unexpectedly ignored failing allocator"); 7242 else if (i == max_alloc_count) 7243 fail("Parser not created with max allocation count"); 7244 } 7245 END_TEST 7246 7247 /* Test memory allocation failures for a parser with an encoding */ 7248 START_TEST(test_misc_alloc_create_parser_with_encoding) { 7249 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7250 unsigned int i; 7251 const unsigned int max_alloc_count = 10; 7252 7253 /* Try several levels of allocation */ 7254 for (i = 0; i < max_alloc_count; i++) { 7255 allocation_count = i; 7256 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL); 7257 if (g_parser != NULL) 7258 break; 7259 } 7260 if (i == 0) 7261 fail("Parser ignored failing allocator"); 7262 else if (i == max_alloc_count) 7263 fail("Parser not created with max allocation count"); 7264 } 7265 END_TEST 7266 7267 /* Test that freeing a NULL parser doesn't cause an explosion. 7268 * (Not actually tested anywhere else) 7269 */ 7270 START_TEST(test_misc_null_parser) { 7271 XML_ParserFree(NULL); 7272 } 7273 END_TEST 7274 7275 /* Test that XML_ErrorString rejects out-of-range codes */ 7276 START_TEST(test_misc_error_string) { 7277 if (XML_ErrorString((enum XML_Error) - 1) != NULL) 7278 fail("Negative error code not rejected"); 7279 if (XML_ErrorString((enum XML_Error)100) != NULL) 7280 fail("Large error code not rejected"); 7281 } 7282 END_TEST 7283 7284 /* Test the version information is consistent */ 7285 7286 /* Since we are working in XML_LChars (potentially 16-bits), we 7287 * can't use the standard C library functions for character 7288 * manipulation and have to roll our own. 7289 */ 7290 static int 7291 parse_version(const XML_LChar *version_text, 7292 XML_Expat_Version *version_struct) { 7293 if (! version_text) 7294 return XML_FALSE; 7295 7296 while (*version_text != 0x00) { 7297 if (*version_text >= ASCII_0 && *version_text <= ASCII_9) 7298 break; 7299 version_text++; 7300 } 7301 if (*version_text == 0x00) 7302 return XML_FALSE; 7303 7304 /* version_struct->major = strtoul(version_text, 10, &version_text) */ 7305 version_struct->major = 0; 7306 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7307 version_struct->major 7308 = 10 * version_struct->major + (*version_text++ - ASCII_0); 7309 } 7310 if (*version_text++ != ASCII_PERIOD) 7311 return XML_FALSE; 7312 7313 /* Now for the minor version number */ 7314 version_struct->minor = 0; 7315 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7316 version_struct->minor 7317 = 10 * version_struct->minor + (*version_text++ - ASCII_0); 7318 } 7319 if (*version_text++ != ASCII_PERIOD) 7320 return XML_FALSE; 7321 7322 /* Finally the micro version number */ 7323 version_struct->micro = 0; 7324 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7325 version_struct->micro 7326 = 10 * version_struct->micro + (*version_text++ - ASCII_0); 7327 } 7328 if (*version_text != 0x00) 7329 return XML_FALSE; 7330 return XML_TRUE; 7331 } 7332 7333 static int 7334 versions_equal(const XML_Expat_Version *first, 7335 const XML_Expat_Version *second) { 7336 return (first->major == second->major && first->minor == second->minor 7337 && first->micro == second->micro); 7338 } 7339 7340 START_TEST(test_misc_version) { 7341 XML_Expat_Version read_version = XML_ExpatVersionInfo(); 7342 /* Silence compiler warning with the following assignment */ 7343 XML_Expat_Version parsed_version = {0, 0, 0}; 7344 const XML_LChar *version_text = XML_ExpatVersion(); 7345 7346 if (version_text == NULL) 7347 fail("Could not obtain version text"); 7348 assert(version_text != NULL); 7349 if (! parse_version(version_text, &parsed_version)) 7350 fail("Unable to parse version text"); 7351 if (! versions_equal(&read_version, &parsed_version)) 7352 fail("Version mismatch"); 7353 7354 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) 7355 if (xcstrcmp(version_text, XCS("expat_2.4.3"))) /* needs bump on releases */ 7356 fail("XML_*_VERSION in expat.h out of sync?\n"); 7357 #else 7358 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T 7359 * then XML_LChar is defined as char, for some reason. 7360 */ 7361 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */ 7362 fail("XML_*_VERSION in expat.h out of sync?\n"); 7363 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */ 7364 } 7365 END_TEST 7366 7367 /* Test feature information */ 7368 START_TEST(test_misc_features) { 7369 const XML_Feature *features = XML_GetFeatureList(); 7370 7371 /* Prevent problems with double-freeing parsers */ 7372 g_parser = NULL; 7373 if (features == NULL) { 7374 fail("Failed to get feature information"); 7375 } else { 7376 /* Loop through the features checking what we can */ 7377 while (features->feature != XML_FEATURE_END) { 7378 switch (features->feature) { 7379 case XML_FEATURE_SIZEOF_XML_CHAR: 7380 if (features->value != sizeof(XML_Char)) 7381 fail("Incorrect size of XML_Char"); 7382 break; 7383 case XML_FEATURE_SIZEOF_XML_LCHAR: 7384 if (features->value != sizeof(XML_LChar)) 7385 fail("Incorrect size of XML_LChar"); 7386 break; 7387 default: 7388 break; 7389 } 7390 features++; 7391 } 7392 } 7393 } 7394 END_TEST 7395 7396 /* Regression test for GitHub Issue #17: memory leak parsing attribute 7397 * values with mixed bound and unbound namespaces. 7398 */ 7399 START_TEST(test_misc_attribute_leak) { 7400 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>"; 7401 XML_Memory_Handling_Suite memsuite 7402 = {tracking_malloc, tracking_realloc, tracking_free}; 7403 7404 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n")); 7405 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found"); 7406 XML_ParserFree(g_parser); 7407 /* Prevent the teardown trying to double free */ 7408 g_parser = NULL; 7409 7410 if (! tracking_report()) 7411 fail("Memory leak found"); 7412 } 7413 END_TEST 7414 7415 /* Test parser created for UTF-16LE is successful */ 7416 START_TEST(test_misc_utf16le) { 7417 const char text[] = 7418 /* <?xml version='1.0'?><q>Hi</q> */ 7419 "<\0?\0x\0m\0l\0 \0" 7420 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0" 7421 "<\0q\0>\0H\0i\0<\0/\0q\0>\0"; 7422 const XML_Char *expected = XCS("Hi"); 7423 CharData storage; 7424 7425 g_parser = XML_ParserCreate(XCS("UTF-16LE")); 7426 if (g_parser == NULL) 7427 fail("Parser not created"); 7428 7429 CharData_Init(&storage); 7430 XML_SetUserData(g_parser, &storage); 7431 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 7432 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7433 == XML_STATUS_ERROR) 7434 xml_failure(g_parser); 7435 CharData_CheckXMLChars(&storage, expected); 7436 } 7437 END_TEST 7438 7439 typedef struct { 7440 XML_Parser parser; 7441 int deep; 7442 } DataIssue240; 7443 7444 static void 7445 start_element_issue_240(void *userData, const XML_Char *name, 7446 const XML_Char **atts) { 7447 DataIssue240 *mydata = (DataIssue240 *)userData; 7448 UNUSED_P(name); 7449 UNUSED_P(atts); 7450 mydata->deep++; 7451 } 7452 7453 static void 7454 end_element_issue_240(void *userData, const XML_Char *name) { 7455 DataIssue240 *mydata = (DataIssue240 *)userData; 7456 7457 UNUSED_P(name); 7458 mydata->deep--; 7459 if (mydata->deep == 0) { 7460 XML_StopParser(mydata->parser, 0); 7461 } 7462 } 7463 7464 START_TEST(test_misc_stop_during_end_handler_issue_240_1) { 7465 XML_Parser parser; 7466 DataIssue240 *mydata; 7467 enum XML_Status result; 7468 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>"; 7469 7470 parser = XML_ParserCreate(NULL); 7471 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7472 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7473 mydata->parser = parser; 7474 mydata->deep = 0; 7475 XML_SetUserData(parser, mydata); 7476 7477 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1); 7478 XML_ParserFree(parser); 7479 free(mydata); 7480 if (result != XML_STATUS_ERROR) 7481 fail("Stopping the parser did not work as expected"); 7482 } 7483 END_TEST 7484 7485 START_TEST(test_misc_stop_during_end_handler_issue_240_2) { 7486 XML_Parser parser; 7487 DataIssue240 *mydata; 7488 enum XML_Status result; 7489 const char *const doc2 = "<doc><elem/></doc>"; 7490 7491 parser = XML_ParserCreate(NULL); 7492 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7493 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7494 mydata->parser = parser; 7495 mydata->deep = 0; 7496 XML_SetUserData(parser, mydata); 7497 7498 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1); 7499 XML_ParserFree(parser); 7500 free(mydata); 7501 if (result != XML_STATUS_ERROR) 7502 fail("Stopping the parser did not work as expected"); 7503 } 7504 END_TEST 7505 7506 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { 7507 const char *const inputOne = "<!DOCTYPE d [\n" 7508 "<!ENTITY % e ']><d/>'>\n" 7509 "\n" 7510 "%e;"; 7511 const char *const inputTwo = "<!DOCTYPE d [\n" 7512 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n" 7513 "\n" 7514 "%e2;"; 7515 const char *const inputThree = "<!DOCTYPE d [\n" 7516 "<!ENTITY % e ']><d'>\n" 7517 "\n" 7518 "%e;"; 7519 const char *const inputIssue317 = "<!DOCTYPE doc [\n" 7520 "<!ENTITY % foo ']>\n" 7521 "<doc>Hell<oc (#PCDATA)*>'>\n" 7522 "%foo;\n" 7523 "]>\n" 7524 "<doc>Hello, world</dVc>"; 7525 7526 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317}; 7527 size_t inputIndex = 0; 7528 7529 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) { 7530 XML_Parser parser; 7531 enum XML_Status parseResult; 7532 int setParamEntityResult; 7533 XML_Size lineNumber; 7534 XML_Size columnNumber; 7535 const char *const input = inputs[inputIndex]; 7536 7537 parser = XML_ParserCreate(NULL); 7538 setParamEntityResult 7539 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7540 if (setParamEntityResult != 1) 7541 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS."); 7542 7543 parseResult = XML_Parse(parser, input, (int)strlen(input), 0); 7544 if (parseResult != XML_STATUS_ERROR) { 7545 parseResult = XML_Parse(parser, "", 0, 1); 7546 if (parseResult != XML_STATUS_ERROR) { 7547 fail("Parsing was expected to fail but succeeded."); 7548 } 7549 } 7550 7551 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) 7552 fail("Error code does not match XML_ERROR_INVALID_TOKEN"); 7553 7554 lineNumber = XML_GetCurrentLineNumber(parser); 7555 if (lineNumber != 4) 7556 fail("XML_GetCurrentLineNumber does not work as expected."); 7557 7558 columnNumber = XML_GetCurrentColumnNumber(parser); 7559 if (columnNumber != 0) 7560 fail("XML_GetCurrentColumnNumber does not work as expected."); 7561 7562 XML_ParserFree(parser); 7563 } 7564 } 7565 END_TEST 7566 7567 static void 7568 alloc_setup(void) { 7569 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 7570 7571 /* Ensure the parser creation will go through */ 7572 allocation_count = ALLOC_ALWAYS_SUCCEED; 7573 reallocation_count = REALLOC_ALWAYS_SUCCEED; 7574 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7575 if (g_parser == NULL) 7576 fail("Parser not created"); 7577 } 7578 7579 static void 7580 alloc_teardown(void) { 7581 basic_teardown(); 7582 } 7583 7584 /* Test the effects of allocation failures on xml declaration processing */ 7585 START_TEST(test_alloc_parse_xdecl) { 7586 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7587 "<doc>Hello, world</doc>"; 7588 int i; 7589 const int max_alloc_count = 15; 7590 7591 for (i = 0; i < max_alloc_count; i++) { 7592 allocation_count = i; 7593 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7594 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7595 != XML_STATUS_ERROR) 7596 break; 7597 /* Resetting the parser is insufficient, because some memory 7598 * allocations are cached within the parser. Instead we use 7599 * the teardown and setup routines to ensure that we have the 7600 * right sort of parser back in our hands. 7601 */ 7602 alloc_teardown(); 7603 alloc_setup(); 7604 } 7605 if (i == 0) 7606 fail("Parse succeeded despite failing allocator"); 7607 if (i == max_alloc_count) 7608 fail("Parse failed with max allocations"); 7609 } 7610 END_TEST 7611 7612 /* As above, but with an encoding big enough to cause storing the 7613 * version information to expand the string pool being used. 7614 */ 7615 static int XMLCALL 7616 long_encoding_handler(void *userData, const XML_Char *encoding, 7617 XML_Encoding *info) { 7618 int i; 7619 7620 UNUSED_P(userData); 7621 UNUSED_P(encoding); 7622 for (i = 0; i < 256; i++) 7623 info->map[i] = i; 7624 info->data = NULL; 7625 info->convert = NULL; 7626 info->release = NULL; 7627 return XML_STATUS_OK; 7628 } 7629 7630 START_TEST(test_alloc_parse_xdecl_2) { 7631 const char *text 7632 = "<?xml version='1.0' encoding='" 7633 /* Each line is 64 characters */ 7634 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456" 7635 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7636 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7637 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7638 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7639 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7640 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7641 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7642 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7643 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7644 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7645 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7646 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7647 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7648 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7649 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN" 7650 "'?>" 7651 "<doc>Hello, world</doc>"; 7652 int i; 7653 const int max_alloc_count = 20; 7654 7655 for (i = 0; i < max_alloc_count; i++) { 7656 allocation_count = i; 7657 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7658 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL); 7659 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7660 != XML_STATUS_ERROR) 7661 break; 7662 /* See comment in test_alloc_parse_xdecl() */ 7663 alloc_teardown(); 7664 alloc_setup(); 7665 } 7666 if (i == 0) 7667 fail("Parse succeeded despite failing allocator"); 7668 if (i == max_alloc_count) 7669 fail("Parse failed with max allocations"); 7670 } 7671 END_TEST 7672 7673 /* Test the effects of allocation failures on a straightforward parse */ 7674 START_TEST(test_alloc_parse_pi) { 7675 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7676 "<?pi unknown?>\n" 7677 "<doc>" 7678 "Hello, world" 7679 "</doc>"; 7680 int i; 7681 const int max_alloc_count = 15; 7682 7683 for (i = 0; i < max_alloc_count; i++) { 7684 allocation_count = i; 7685 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7686 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7687 != XML_STATUS_ERROR) 7688 break; 7689 /* See comment in test_alloc_parse_xdecl() */ 7690 alloc_teardown(); 7691 alloc_setup(); 7692 } 7693 if (i == 0) 7694 fail("Parse succeeded despite failing allocator"); 7695 if (i == max_alloc_count) 7696 fail("Parse failed with max allocations"); 7697 } 7698 END_TEST 7699 7700 START_TEST(test_alloc_parse_pi_2) { 7701 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7702 "<doc>" 7703 "Hello, world" 7704 "<?pi unknown?>\n" 7705 "</doc>"; 7706 int i; 7707 const int max_alloc_count = 15; 7708 7709 for (i = 0; i < max_alloc_count; i++) { 7710 allocation_count = i; 7711 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7712 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7713 != XML_STATUS_ERROR) 7714 break; 7715 /* See comment in test_alloc_parse_xdecl() */ 7716 alloc_teardown(); 7717 alloc_setup(); 7718 } 7719 if (i == 0) 7720 fail("Parse succeeded despite failing allocator"); 7721 if (i == max_alloc_count) 7722 fail("Parse failed with max allocations"); 7723 } 7724 END_TEST 7725 7726 START_TEST(test_alloc_parse_pi_3) { 7727 const char *text 7728 = "<?" 7729 /* 64 characters per line */ 7730 "This processing instruction should be long enough to ensure that" 7731 "it triggers the growth of an internal string pool when the " 7732 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP" 7733 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7734 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7735 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7736 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7737 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7738 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7739 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7740 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7741 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7742 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7743 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7744 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7745 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7746 "Q?><doc/>"; 7747 int i; 7748 const int max_alloc_count = 20; 7749 7750 for (i = 0; i < max_alloc_count; i++) { 7751 allocation_count = i; 7752 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7753 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7754 != XML_STATUS_ERROR) 7755 break; 7756 /* See comment in test_alloc_parse_xdecl() */ 7757 alloc_teardown(); 7758 alloc_setup(); 7759 } 7760 if (i == 0) 7761 fail("Parse succeeded despite failing allocator"); 7762 if (i == max_alloc_count) 7763 fail("Parse failed with max allocations"); 7764 } 7765 END_TEST 7766 7767 START_TEST(test_alloc_parse_comment) { 7768 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7769 "<!-- Test parsing this comment -->" 7770 "<doc>Hi</doc>"; 7771 int i; 7772 const int max_alloc_count = 15; 7773 7774 for (i = 0; i < max_alloc_count; i++) { 7775 allocation_count = i; 7776 XML_SetCommentHandler(g_parser, dummy_comment_handler); 7777 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7778 != XML_STATUS_ERROR) 7779 break; 7780 /* See comment in test_alloc_parse_xdecl() */ 7781 alloc_teardown(); 7782 alloc_setup(); 7783 } 7784 if (i == 0) 7785 fail("Parse succeeded despite failing allocator"); 7786 if (i == max_alloc_count) 7787 fail("Parse failed with max allocations"); 7788 } 7789 END_TEST 7790 7791 START_TEST(test_alloc_parse_comment_2) { 7792 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7793 "<doc>" 7794 "Hello, world" 7795 "<!-- Parse this comment too -->" 7796 "</doc>"; 7797 int i; 7798 const int max_alloc_count = 15; 7799 7800 for (i = 0; i < max_alloc_count; i++) { 7801 allocation_count = i; 7802 XML_SetCommentHandler(g_parser, dummy_comment_handler); 7803 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7804 != XML_STATUS_ERROR) 7805 break; 7806 /* See comment in test_alloc_parse_xdecl() */ 7807 alloc_teardown(); 7808 alloc_setup(); 7809 } 7810 if (i == 0) 7811 fail("Parse succeeded despite failing allocator"); 7812 if (i == max_alloc_count) 7813 fail("Parse failed with max allocations"); 7814 } 7815 END_TEST 7816 7817 static int XMLCALL 7818 external_entity_duff_loader(XML_Parser parser, const XML_Char *context, 7819 const XML_Char *base, const XML_Char *systemId, 7820 const XML_Char *publicId) { 7821 XML_Parser new_parser; 7822 unsigned int i; 7823 const unsigned int max_alloc_count = 10; 7824 7825 UNUSED_P(base); 7826 UNUSED_P(systemId); 7827 UNUSED_P(publicId); 7828 /* Try a few different allocation levels */ 7829 for (i = 0; i < max_alloc_count; i++) { 7830 allocation_count = i; 7831 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 7832 if (new_parser != NULL) { 7833 XML_ParserFree(new_parser); 7834 break; 7835 } 7836 } 7837 if (i == 0) 7838 fail("External parser creation ignored failing allocator"); 7839 else if (i == max_alloc_count) 7840 fail("Extern parser not created with max allocation count"); 7841 7842 /* Make sure other random allocation doesn't now fail */ 7843 allocation_count = ALLOC_ALWAYS_SUCCEED; 7844 7845 /* Make sure the failure code path is executed too */ 7846 return XML_STATUS_ERROR; 7847 } 7848 7849 /* Test that external parser creation running out of memory is 7850 * correctly reported. Based on the external entity test cases. 7851 */ 7852 START_TEST(test_alloc_create_external_parser) { 7853 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 7854 "<!DOCTYPE doc SYSTEM 'foo'>\n" 7855 "<doc>&entity;</doc>"; 7856 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 7857 7858 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7859 XML_SetUserData(g_parser, foo_text); 7860 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader); 7861 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7862 != XML_STATUS_ERROR) { 7863 fail("External parser allocator returned success incorrectly"); 7864 } 7865 } 7866 END_TEST 7867 7868 /* More external parser memory allocation testing */ 7869 START_TEST(test_alloc_run_external_parser) { 7870 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 7871 "<!DOCTYPE doc SYSTEM 'foo'>\n" 7872 "<doc>&entity;</doc>"; 7873 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 7874 unsigned int i; 7875 const unsigned int max_alloc_count = 15; 7876 7877 for (i = 0; i < max_alloc_count; i++) { 7878 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7879 XML_SetUserData(g_parser, foo_text); 7880 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 7881 allocation_count = i; 7882 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7883 != XML_STATUS_ERROR) 7884 break; 7885 /* See comment in test_alloc_parse_xdecl() */ 7886 alloc_teardown(); 7887 alloc_setup(); 7888 } 7889 if (i == 0) 7890 fail("Parsing ignored failing allocator"); 7891 else if (i == max_alloc_count) 7892 fail("Parsing failed with allocation count 10"); 7893 } 7894 END_TEST 7895 7896 static int XMLCALL 7897 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context, 7898 const XML_Char *base, const XML_Char *systemId, 7899 const XML_Char *publicId) { 7900 intptr_t callno = (intptr_t)XML_GetUserData(parser); 7901 const char *text; 7902 XML_Parser new_parser; 7903 int i; 7904 const int max_alloc_count = 20; 7905 7906 UNUSED_P(base); 7907 UNUSED_P(systemId); 7908 UNUSED_P(publicId); 7909 if (callno == 0) { 7910 /* First time through, check how many calls to malloc occur */ 7911 text = ("<!ELEMENT doc (e+)>\n" 7912 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 7913 "<!ELEMENT e EMPTY>\n"); 7914 allocation_count = 10000; 7915 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 7916 if (new_parser == NULL) { 7917 fail("Unable to allocate first external parser"); 7918 return XML_STATUS_ERROR; 7919 } 7920 /* Stash the number of calls in the user data */ 7921 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count)); 7922 } else { 7923 text = ("<?xml version='1.0' encoding='us-ascii'?>" 7924 "<e/>"); 7925 /* Try at varying levels to exercise more code paths */ 7926 for (i = 0; i < max_alloc_count; i++) { 7927 allocation_count = callno + i; 7928 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 7929 if (new_parser != NULL) 7930 break; 7931 } 7932 if (i == 0) { 7933 fail("Second external parser unexpectedly created"); 7934 XML_ParserFree(new_parser); 7935 return XML_STATUS_ERROR; 7936 } else if (i == max_alloc_count) { 7937 fail("Second external parser not created"); 7938 return XML_STATUS_ERROR; 7939 } 7940 } 7941 7942 allocation_count = ALLOC_ALWAYS_SUCCEED; 7943 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE) 7944 == XML_STATUS_ERROR) { 7945 xml_failure(new_parser); 7946 return XML_STATUS_ERROR; 7947 } 7948 XML_ParserFree(new_parser); 7949 return XML_STATUS_OK; 7950 } 7951 7952 /* Test that running out of memory in dtdCopy is correctly reported. 7953 * Based on test_default_ns_from_ext_subset_and_ext_ge() 7954 */ 7955 START_TEST(test_alloc_dtd_copy_default_atts) { 7956 const char *text = "<?xml version='1.0'?>\n" 7957 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 7958 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 7959 "]>\n" 7960 "<doc xmlns='http://example.org/ns1'>\n" 7961 "&en;\n" 7962 "</doc>"; 7963 7964 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7965 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler); 7966 XML_SetUserData(g_parser, NULL); 7967 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7968 == XML_STATUS_ERROR) 7969 xml_failure(g_parser); 7970 } 7971 END_TEST 7972 7973 static int XMLCALL 7974 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context, 7975 const XML_Char *base, const XML_Char *systemId, 7976 const XML_Char *publicId) { 7977 intptr_t callno = (intptr_t)XML_GetUserData(parser); 7978 const char *text; 7979 XML_Parser new_parser; 7980 enum XML_Status rv; 7981 7982 UNUSED_P(base); 7983 UNUSED_P(systemId); 7984 UNUSED_P(publicId); 7985 if (callno == 0) { 7986 /* Try different allocation levels for whole exercise */ 7987 text = ("<!ELEMENT doc (e+)>\n" 7988 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 7989 "<!ELEMENT e EMPTY>\n"); 7990 XML_SetUserData(parser, (void *)(intptr_t)1); 7991 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 7992 if (new_parser == NULL) 7993 return XML_STATUS_ERROR; 7994 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 7995 } else { 7996 /* Just run through once */ 7997 text = ("<?xml version='1.0' encoding='us-ascii'?>" 7998 "<e/>"); 7999 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8000 if (new_parser == NULL) 8001 return XML_STATUS_ERROR; 8002 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8003 } 8004 XML_ParserFree(new_parser); 8005 if (rv == XML_STATUS_ERROR) 8006 return XML_STATUS_ERROR; 8007 return XML_STATUS_OK; 8008 } 8009 8010 /* Test more external entity allocation failure paths */ 8011 START_TEST(test_alloc_external_entity) { 8012 const char *text = "<?xml version='1.0'?>\n" 8013 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8014 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8015 "]>\n" 8016 "<doc xmlns='http://example.org/ns1'>\n" 8017 "&en;\n" 8018 "</doc>"; 8019 int i; 8020 const int alloc_test_max_repeats = 50; 8021 8022 for (i = 0; i < alloc_test_max_repeats; i++) { 8023 allocation_count = -1; 8024 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8025 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2); 8026 XML_SetUserData(g_parser, NULL); 8027 allocation_count = i; 8028 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8029 == XML_STATUS_OK) 8030 break; 8031 /* See comment in test_alloc_parse_xdecl() */ 8032 alloc_teardown(); 8033 alloc_setup(); 8034 } 8035 allocation_count = -1; 8036 if (i == 0) 8037 fail("External entity parsed despite duff allocator"); 8038 if (i == alloc_test_max_repeats) 8039 fail("External entity not parsed at max allocation count"); 8040 } 8041 END_TEST 8042 8043 /* Test more allocation failure paths */ 8044 static int XMLCALL 8045 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context, 8046 const XML_Char *base, 8047 const XML_Char *systemId, 8048 const XML_Char *publicId) { 8049 /* As for external_entity_loader() */ 8050 const char *text = "<?xml encoding='iso-8859-3'?>" 8051 "\xC3\xA9"; 8052 XML_Parser ext_parser; 8053 enum XML_Status status; 8054 8055 UNUSED_P(base); 8056 UNUSED_P(systemId); 8057 UNUSED_P(publicId); 8058 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8059 if (ext_parser == NULL) 8060 return XML_STATUS_ERROR; 8061 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) { 8062 XML_ParserFree(ext_parser); 8063 return XML_STATUS_ERROR; 8064 } 8065 status 8066 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8067 XML_ParserFree(ext_parser); 8068 if (status == XML_STATUS_ERROR) 8069 return XML_STATUS_ERROR; 8070 return XML_STATUS_OK; 8071 } 8072 8073 START_TEST(test_alloc_ext_entity_set_encoding) { 8074 const char *text = "<!DOCTYPE doc [\n" 8075 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8076 "]>\n" 8077 "<doc>&en;</doc>"; 8078 int i; 8079 const int max_allocation_count = 30; 8080 8081 for (i = 0; i < max_allocation_count; i++) { 8082 XML_SetExternalEntityRefHandler(g_parser, 8083 external_entity_alloc_set_encoding); 8084 allocation_count = i; 8085 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8086 == XML_STATUS_OK) 8087 break; 8088 allocation_count = -1; 8089 /* See comment in test_alloc_parse_xdecl() */ 8090 alloc_teardown(); 8091 alloc_setup(); 8092 } 8093 if (i == 0) 8094 fail("Encoding check succeeded despite failing allocator"); 8095 if (i == max_allocation_count) 8096 fail("Encoding failed at max allocation count"); 8097 } 8098 END_TEST 8099 8100 static int XMLCALL 8101 unknown_released_encoding_handler(void *data, const XML_Char *encoding, 8102 XML_Encoding *info) { 8103 UNUSED_P(data); 8104 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) { 8105 int i; 8106 8107 for (i = 0; i < 256; i++) 8108 info->map[i] = i; 8109 info->data = NULL; 8110 info->convert = NULL; 8111 info->release = dummy_release; 8112 return XML_STATUS_OK; 8113 } 8114 return XML_STATUS_ERROR; 8115 } 8116 8117 /* Test the effects of allocation failure in internal entities. 8118 * Based on test_unknown_encoding_internal_entity 8119 */ 8120 START_TEST(test_alloc_internal_entity) { 8121 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 8122 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 8123 "<test a='&foo;'/>"; 8124 unsigned int i; 8125 const unsigned int max_alloc_count = 20; 8126 8127 for (i = 0; i < max_alloc_count; i++) { 8128 allocation_count = i; 8129 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, 8130 NULL); 8131 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8132 != XML_STATUS_ERROR) 8133 break; 8134 /* See comment in test_alloc_parse_xdecl() */ 8135 alloc_teardown(); 8136 alloc_setup(); 8137 } 8138 if (i == 0) 8139 fail("Internal entity worked despite failing allocations"); 8140 else if (i == max_alloc_count) 8141 fail("Internal entity failed at max allocation count"); 8142 } 8143 END_TEST 8144 8145 /* Test the robustness against allocation failure of element handling 8146 * Based on test_dtd_default_handling(). 8147 */ 8148 START_TEST(test_alloc_dtd_default_handling) { 8149 const char *text = "<!DOCTYPE doc [\n" 8150 "<!ENTITY e SYSTEM 'http://example.org/e'>\n" 8151 "<!NOTATION n SYSTEM 'http://example.org/n'>\n" 8152 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n" 8153 "<!ELEMENT doc (#PCDATA)>\n" 8154 "<!ATTLIST doc a CDATA #IMPLIED>\n" 8155 "<?pi in dtd?>\n" 8156 "<!--comment in dtd-->\n" 8157 "]>\n" 8158 "<doc><![CDATA[text in doc]]></doc>"; 8159 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>"); 8160 CharData storage; 8161 int i; 8162 const int max_alloc_count = 25; 8163 8164 for (i = 0; i < max_alloc_count; i++) { 8165 allocation_count = i; 8166 dummy_handler_flags = 0; 8167 XML_SetDefaultHandler(g_parser, accumulate_characters); 8168 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 8169 dummy_end_doctype_handler); 8170 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8171 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8172 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 8173 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8174 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8175 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8176 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler, 8177 dummy_end_cdata_handler); 8178 XML_SetUnparsedEntityDeclHandler(g_parser, 8179 dummy_unparsed_entity_decl_handler); 8180 CharData_Init(&storage); 8181 XML_SetUserData(g_parser, &storage); 8182 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 8183 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8184 != XML_STATUS_ERROR) 8185 break; 8186 /* See comment in test_alloc_parse_xdecl() */ 8187 alloc_teardown(); 8188 alloc_setup(); 8189 } 8190 if (i == 0) 8191 fail("Default DTD parsed despite allocation failures"); 8192 if (i == max_alloc_count) 8193 fail("Default DTD not parsed with maximum alloc count"); 8194 CharData_CheckXMLChars(&storage, expected); 8195 if (dummy_handler_flags 8196 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG 8197 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG 8198 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG 8199 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG 8200 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG 8201 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG)) 8202 fail("Not all handlers were called"); 8203 } 8204 END_TEST 8205 8206 /* Test robustness of XML_SetEncoding() with a failing allocator */ 8207 START_TEST(test_alloc_explicit_encoding) { 8208 int i; 8209 const int max_alloc_count = 5; 8210 8211 for (i = 0; i < max_alloc_count; i++) { 8212 allocation_count = i; 8213 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK) 8214 break; 8215 } 8216 if (i == 0) 8217 fail("Encoding set despite failing allocator"); 8218 else if (i == max_alloc_count) 8219 fail("Encoding not set at max allocation count"); 8220 } 8221 END_TEST 8222 8223 /* Test robustness of XML_SetBase against a failing allocator */ 8224 START_TEST(test_alloc_set_base) { 8225 const XML_Char *new_base = XCS("/local/file/name.xml"); 8226 int i; 8227 const int max_alloc_count = 5; 8228 8229 for (i = 0; i < max_alloc_count; i++) { 8230 allocation_count = i; 8231 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK) 8232 break; 8233 } 8234 if (i == 0) 8235 fail("Base set despite failing allocator"); 8236 else if (i == max_alloc_count) 8237 fail("Base not set with max allocation count"); 8238 } 8239 END_TEST 8240 8241 /* Test buffer extension in the face of a duff reallocator */ 8242 START_TEST(test_alloc_realloc_buffer) { 8243 const char *text = get_buffer_test_text; 8244 void *buffer; 8245 int i; 8246 const int max_realloc_count = 10; 8247 8248 /* Get a smallish buffer */ 8249 for (i = 0; i < max_realloc_count; i++) { 8250 reallocation_count = i; 8251 buffer = XML_GetBuffer(g_parser, 1536); 8252 if (buffer == NULL) 8253 fail("1.5K buffer reallocation failed"); 8254 assert(buffer != NULL); 8255 memcpy(buffer, text, strlen(text)); 8256 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 8257 == XML_STATUS_OK) 8258 break; 8259 /* See comment in test_alloc_parse_xdecl() */ 8260 alloc_teardown(); 8261 alloc_setup(); 8262 } 8263 reallocation_count = -1; 8264 if (i == 0) 8265 fail("Parse succeeded with no reallocation"); 8266 else if (i == max_realloc_count) 8267 fail("Parse failed with max reallocation count"); 8268 } 8269 END_TEST 8270 8271 /* Same test for external entity parsers */ 8272 static int XMLCALL 8273 external_entity_reallocator(XML_Parser parser, const XML_Char *context, 8274 const XML_Char *base, const XML_Char *systemId, 8275 const XML_Char *publicId) { 8276 const char *text = get_buffer_test_text; 8277 XML_Parser ext_parser; 8278 void *buffer; 8279 enum XML_Status status; 8280 8281 UNUSED_P(base); 8282 UNUSED_P(systemId); 8283 UNUSED_P(publicId); 8284 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8285 if (ext_parser == NULL) 8286 fail("Could not create external entity parser"); 8287 8288 reallocation_count = (intptr_t)XML_GetUserData(parser); 8289 buffer = XML_GetBuffer(ext_parser, 1536); 8290 if (buffer == NULL) 8291 fail("Buffer allocation failed"); 8292 assert(buffer != NULL); 8293 memcpy(buffer, text, strlen(text)); 8294 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE); 8295 reallocation_count = -1; 8296 XML_ParserFree(ext_parser); 8297 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR; 8298 } 8299 8300 START_TEST(test_alloc_ext_entity_realloc_buffer) { 8301 const char *text = "<!DOCTYPE doc [\n" 8302 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8303 "]>\n" 8304 "<doc>&en;</doc>"; 8305 int i; 8306 const int max_realloc_count = 10; 8307 8308 for (i = 0; i < max_realloc_count; i++) { 8309 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator); 8310 XML_SetUserData(g_parser, (void *)(intptr_t)i); 8311 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8312 == XML_STATUS_OK) 8313 break; 8314 /* See comment in test_alloc_parse_xdecl() */ 8315 alloc_teardown(); 8316 alloc_setup(); 8317 } 8318 if (i == 0) 8319 fail("Succeeded with no reallocations"); 8320 if (i == max_realloc_count) 8321 fail("Failed with max reallocations"); 8322 } 8323 END_TEST 8324 8325 /* Test elements with many attributes are handled correctly */ 8326 START_TEST(test_alloc_realloc_many_attributes) { 8327 const char *text = "<!DOCTYPE doc [\n" 8328 "<!ATTLIST doc za CDATA 'default'>\n" 8329 "<!ATTLIST doc zb CDATA 'def2'>\n" 8330 "<!ATTLIST doc zc CDATA 'def3'>\n" 8331 "]>\n" 8332 "<doc a='1'" 8333 " b='2'" 8334 " c='3'" 8335 " d='4'" 8336 " e='5'" 8337 " f='6'" 8338 " g='7'" 8339 " h='8'" 8340 " i='9'" 8341 " j='10'" 8342 " k='11'" 8343 " l='12'" 8344 " m='13'" 8345 " n='14'" 8346 " p='15'" 8347 " q='16'" 8348 " r='17'" 8349 " s='18'>" 8350 "</doc>"; 8351 int i; 8352 const int max_realloc_count = 10; 8353 8354 for (i = 0; i < max_realloc_count; i++) { 8355 reallocation_count = i; 8356 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8357 != XML_STATUS_ERROR) 8358 break; 8359 /* See comment in test_alloc_parse_xdecl() */ 8360 alloc_teardown(); 8361 alloc_setup(); 8362 } 8363 if (i == 0) 8364 fail("Parse succeeded despite no reallocations"); 8365 if (i == max_realloc_count) 8366 fail("Parse failed at max reallocations"); 8367 } 8368 END_TEST 8369 8370 /* Test handling of a public entity with failing allocator */ 8371 START_TEST(test_alloc_public_entity_value) { 8372 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8373 "<doc></doc>\n"; 8374 char dtd_text[] 8375 = "<!ELEMENT doc EMPTY>\n" 8376 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n" 8377 "<!ENTITY % " 8378 /* Each line is 64 characters */ 8379 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8380 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8381 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8382 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8383 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8384 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8385 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8386 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8387 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8388 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8389 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8390 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8391 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8392 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8393 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8394 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8395 " '%e1;'>\n" 8396 "%e1;\n"; 8397 int i; 8398 const int max_alloc_count = 50; 8399 8400 for (i = 0; i < max_alloc_count; i++) { 8401 allocation_count = i; 8402 dummy_handler_flags = 0; 8403 XML_SetUserData(g_parser, dtd_text); 8404 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8405 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8406 /* Provoke a particular code path */ 8407 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8408 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8409 != XML_STATUS_ERROR) 8410 break; 8411 /* See comment in test_alloc_parse_xdecl() */ 8412 alloc_teardown(); 8413 alloc_setup(); 8414 } 8415 if (i == 0) 8416 fail("Parsing worked despite failing allocation"); 8417 if (i == max_alloc_count) 8418 fail("Parsing failed at max allocation count"); 8419 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG) 8420 fail("Entity declaration handler not called"); 8421 } 8422 END_TEST 8423 8424 START_TEST(test_alloc_realloc_subst_public_entity_value) { 8425 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8426 "<doc></doc>\n"; 8427 char dtd_text[] 8428 = "<!ELEMENT doc EMPTY>\n" 8429 "<!ENTITY % " 8430 /* Each line is 64 characters */ 8431 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8432 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8433 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8434 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8435 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8436 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8437 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8438 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8439 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8440 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8441 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8442 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8443 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8444 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8445 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8446 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8447 " PUBLIC 'foo' 'bar.ent'>\n" 8448 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8449 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8450 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8451 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8452 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8453 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8454 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8455 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8456 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8457 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8458 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8459 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8460 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8461 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8462 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8463 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;"; 8464 int i; 8465 const int max_realloc_count = 10; 8466 8467 for (i = 0; i < max_realloc_count; i++) { 8468 reallocation_count = i; 8469 XML_SetUserData(g_parser, dtd_text); 8470 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8471 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8472 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8473 != XML_STATUS_ERROR) 8474 break; 8475 /* See comment in test_alloc_parse_xdecl() */ 8476 alloc_teardown(); 8477 alloc_setup(); 8478 } 8479 if (i == 0) 8480 fail("Parsing worked despite failing reallocation"); 8481 if (i == max_realloc_count) 8482 fail("Parsing failed at max reallocation count"); 8483 } 8484 END_TEST 8485 8486 START_TEST(test_alloc_parse_public_doctype) { 8487 const char *text 8488 = "<?xml version='1.0' encoding='utf-8'?>\n" 8489 "<!DOCTYPE doc PUBLIC '" 8490 /* 64 characters per line */ 8491 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 8492 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8493 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8494 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8495 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8496 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8497 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8498 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8499 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8500 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8501 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8502 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8503 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8504 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8505 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8506 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8507 "' 'test'>\n" 8508 "<doc></doc>"; 8509 int i; 8510 const int max_alloc_count = 25; 8511 8512 for (i = 0; i < max_alloc_count; i++) { 8513 allocation_count = i; 8514 dummy_handler_flags = 0; 8515 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8516 dummy_end_doctype_decl_handler); 8517 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8518 != XML_STATUS_ERROR) 8519 break; 8520 /* See comment in test_alloc_parse_xdecl() */ 8521 alloc_teardown(); 8522 alloc_setup(); 8523 } 8524 if (i == 0) 8525 fail("Parse succeeded despite failing allocator"); 8526 if (i == max_alloc_count) 8527 fail("Parse failed at maximum allocation count"); 8528 if (dummy_handler_flags 8529 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG 8530 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG)) 8531 fail("Doctype handler functions not called"); 8532 } 8533 END_TEST 8534 8535 START_TEST(test_alloc_parse_public_doctype_long_name) { 8536 const char *text 8537 = "<?xml version='1.0' encoding='utf-8'?>\n" 8538 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '" 8539 /* 64 characters per line */ 8540 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8541 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8542 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8543 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8544 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8545 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8546 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8547 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8548 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8549 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8550 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8551 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8552 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8553 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8554 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8555 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8556 "'>\n" 8557 "<doc></doc>"; 8558 int i; 8559 const int max_alloc_count = 25; 8560 8561 for (i = 0; i < max_alloc_count; i++) { 8562 allocation_count = i; 8563 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8564 dummy_end_doctype_decl_handler); 8565 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8566 != XML_STATUS_ERROR) 8567 break; 8568 /* See comment in test_alloc_parse_xdecl() */ 8569 alloc_teardown(); 8570 alloc_setup(); 8571 } 8572 if (i == 0) 8573 fail("Parse succeeded despite failing allocator"); 8574 if (i == max_alloc_count) 8575 fail("Parse failed at maximum allocation count"); 8576 } 8577 END_TEST 8578 8579 static int XMLCALL 8580 external_entity_alloc(XML_Parser parser, const XML_Char *context, 8581 const XML_Char *base, const XML_Char *systemId, 8582 const XML_Char *publicId) { 8583 const char *text = (const char *)XML_GetUserData(parser); 8584 XML_Parser ext_parser; 8585 int parse_res; 8586 8587 UNUSED_P(base); 8588 UNUSED_P(systemId); 8589 UNUSED_P(publicId); 8590 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8591 if (ext_parser == NULL) 8592 return XML_STATUS_ERROR; 8593 parse_res 8594 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8595 XML_ParserFree(ext_parser); 8596 return parse_res; 8597 } 8598 8599 /* Test foreign DTD handling */ 8600 START_TEST(test_alloc_set_foreign_dtd) { 8601 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 8602 "<doc>&entity;</doc>"; 8603 char text2[] = "<!ELEMENT doc (#PCDATA)*>"; 8604 int i; 8605 const int max_alloc_count = 25; 8606 8607 for (i = 0; i < max_alloc_count; i++) { 8608 allocation_count = i; 8609 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8610 XML_SetUserData(g_parser, &text2); 8611 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8612 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 8613 fail("Could not set foreign DTD"); 8614 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE) 8615 != XML_STATUS_ERROR) 8616 break; 8617 /* See comment in test_alloc_parse_xdecl() */ 8618 alloc_teardown(); 8619 alloc_setup(); 8620 } 8621 if (i == 0) 8622 fail("Parse succeeded despite failing allocator"); 8623 if (i == max_alloc_count) 8624 fail("Parse failed at maximum allocation count"); 8625 } 8626 END_TEST 8627 8628 /* Test based on ibm/valid/P32/ibm32v04.xml */ 8629 START_TEST(test_alloc_attribute_enum_value) { 8630 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8631 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8632 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 8633 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n" 8634 "<!ELEMENT a EMPTY>\n" 8635 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>"; 8636 int i; 8637 const int max_alloc_count = 30; 8638 8639 for (i = 0; i < max_alloc_count; i++) { 8640 allocation_count = i; 8641 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8642 XML_SetUserData(g_parser, dtd_text); 8643 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8644 /* An attribute list handler provokes a different code path */ 8645 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8646 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8647 != XML_STATUS_ERROR) 8648 break; 8649 /* See comment in test_alloc_parse_xdecl() */ 8650 alloc_teardown(); 8651 alloc_setup(); 8652 } 8653 if (i == 0) 8654 fail("Parse succeeded despite failing allocator"); 8655 if (i == max_alloc_count) 8656 fail("Parse failed at maximum allocation count"); 8657 } 8658 END_TEST 8659 8660 /* Test attribute enums sufficient to overflow the string pool */ 8661 START_TEST(test_alloc_realloc_attribute_enum_value) { 8662 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8663 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8664 "<animal>This is a yellow tiger</animal>"; 8665 /* We wish to define a collection of attribute enums that will 8666 * cause the string pool storing them to have to expand. This 8667 * means more than 1024 bytes, including the parentheses and 8668 * separator bars. 8669 */ 8670 char dtd_text[] 8671 = "<!ELEMENT animal (#PCDATA)*>\n" 8672 "<!ATTLIST animal thing " 8673 "(default" 8674 /* Each line is 64 characters */ 8675 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8676 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8677 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8678 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8679 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8680 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8681 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8682 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8683 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8684 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8685 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8686 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8687 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8688 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8689 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8690 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)" 8691 " 'default'>"; 8692 int i; 8693 const int max_realloc_count = 10; 8694 8695 for (i = 0; i < max_realloc_count; i++) { 8696 reallocation_count = i; 8697 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8698 XML_SetUserData(g_parser, dtd_text); 8699 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8700 /* An attribute list handler provokes a different code path */ 8701 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8702 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8703 != XML_STATUS_ERROR) 8704 break; 8705 /* See comment in test_alloc_parse_xdecl() */ 8706 alloc_teardown(); 8707 alloc_setup(); 8708 } 8709 if (i == 0) 8710 fail("Parse succeeded despite failing reallocator"); 8711 if (i == max_realloc_count) 8712 fail("Parse failed at maximum reallocation count"); 8713 } 8714 END_TEST 8715 8716 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */ 8717 START_TEST(test_alloc_realloc_implied_attribute) { 8718 /* Forcing this particular code path is a balancing act. The 8719 * addition of the closing parenthesis and terminal NUL must be 8720 * what pushes the string of enums over the 1024-byte limit, 8721 * otherwise a different code path will pick up the realloc. 8722 */ 8723 const char *text 8724 = "<!DOCTYPE doc [\n" 8725 "<!ELEMENT doc EMPTY>\n" 8726 "<!ATTLIST doc a " 8727 /* Each line is 64 characters */ 8728 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8729 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8730 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8731 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8732 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8733 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8734 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8735 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8736 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8737 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8738 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8739 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8740 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8741 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8742 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8743 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 8744 " #IMPLIED>\n" 8745 "]><doc/>"; 8746 int i; 8747 const int max_realloc_count = 10; 8748 8749 for (i = 0; i < max_realloc_count; i++) { 8750 reallocation_count = i; 8751 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8752 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8753 != XML_STATUS_ERROR) 8754 break; 8755 /* See comment in test_alloc_parse_xdecl() */ 8756 alloc_teardown(); 8757 alloc_setup(); 8758 } 8759 if (i == 0) 8760 fail("Parse succeeded despite failing reallocator"); 8761 if (i == max_realloc_count) 8762 fail("Parse failed at maximum reallocation count"); 8763 } 8764 END_TEST 8765 8766 /* Test attribute enums in a defaulted attribute forcing pool growth */ 8767 START_TEST(test_alloc_realloc_default_attribute) { 8768 /* Forcing this particular code path is a balancing act. The 8769 * addition of the closing parenthesis and terminal NUL must be 8770 * what pushes the string of enums over the 1024-byte limit, 8771 * otherwise a different code path will pick up the realloc. 8772 */ 8773 const char *text 8774 = "<!DOCTYPE doc [\n" 8775 "<!ELEMENT doc EMPTY>\n" 8776 "<!ATTLIST doc a " 8777 /* Each line is 64 characters */ 8778 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8779 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8780 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8781 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8782 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8783 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8784 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8785 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8786 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8787 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8788 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8789 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8790 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8791 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8792 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8793 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 8794 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'" 8795 ">\n]><doc/>"; 8796 int i; 8797 const int max_realloc_count = 10; 8798 8799 for (i = 0; i < max_realloc_count; i++) { 8800 reallocation_count = i; 8801 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8802 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8803 != XML_STATUS_ERROR) 8804 break; 8805 /* See comment in test_alloc_parse_xdecl() */ 8806 alloc_teardown(); 8807 alloc_setup(); 8808 } 8809 if (i == 0) 8810 fail("Parse succeeded despite failing reallocator"); 8811 if (i == max_realloc_count) 8812 fail("Parse failed at maximum reallocation count"); 8813 } 8814 END_TEST 8815 8816 /* Test long notation name with dodgy allocator */ 8817 START_TEST(test_alloc_notation) { 8818 const char *text 8819 = "<!DOCTYPE doc [\n" 8820 "<!NOTATION " 8821 /* Each line is 64 characters */ 8822 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8823 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8824 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8825 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8826 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8827 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8828 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8829 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8830 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8831 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8832 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8833 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8834 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8835 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8836 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8837 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8838 " SYSTEM 'http://example.org/n'>\n" 8839 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA " 8840 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8841 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8842 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8843 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8844 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8845 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8846 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8847 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8848 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8849 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8850 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8851 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8852 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8853 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8854 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8855 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8856 ">\n" 8857 "<!ELEMENT doc EMPTY>\n" 8858 "]>\n<doc/>"; 8859 int i; 8860 const int max_alloc_count = 20; 8861 8862 for (i = 0; i < max_alloc_count; i++) { 8863 allocation_count = i; 8864 dummy_handler_flags = 0; 8865 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8866 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8867 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8868 != XML_STATUS_ERROR) 8869 break; 8870 /* See comment in test_alloc_parse_xdecl() */ 8871 alloc_teardown(); 8872 alloc_setup(); 8873 } 8874 if (i == 0) 8875 fail("Parse succeeded despite allocation failures"); 8876 if (i == max_alloc_count) 8877 fail("Parse failed at maximum allocation count"); 8878 if (dummy_handler_flags 8879 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG)) 8880 fail("Entity declaration handler not called"); 8881 } 8882 END_TEST 8883 8884 /* Test public notation with dodgy allocator */ 8885 START_TEST(test_alloc_public_notation) { 8886 const char *text 8887 = "<!DOCTYPE doc [\n" 8888 "<!NOTATION note PUBLIC '" 8889 /* 64 characters per line */ 8890 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 8891 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8892 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8893 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8894 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8895 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8896 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8897 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8898 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8899 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8900 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8901 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8902 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8903 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8904 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8905 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8906 "' 'foo'>\n" 8907 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 8908 "<!ELEMENT doc EMPTY>\n" 8909 "]>\n<doc/>"; 8910 int i; 8911 const int max_alloc_count = 20; 8912 8913 for (i = 0; i < max_alloc_count; i++) { 8914 allocation_count = i; 8915 dummy_handler_flags = 0; 8916 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8917 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8918 != XML_STATUS_ERROR) 8919 break; 8920 /* See comment in test_alloc_parse_xdecl() */ 8921 alloc_teardown(); 8922 alloc_setup(); 8923 } 8924 if (i == 0) 8925 fail("Parse succeeded despite allocation failures"); 8926 if (i == max_alloc_count) 8927 fail("Parse failed at maximum allocation count"); 8928 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 8929 fail("Notation handler not called"); 8930 } 8931 END_TEST 8932 8933 /* Test public notation with dodgy allocator */ 8934 START_TEST(test_alloc_system_notation) { 8935 const char *text 8936 = "<!DOCTYPE doc [\n" 8937 "<!NOTATION note SYSTEM '" 8938 /* 64 characters per line */ 8939 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 8940 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8941 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8942 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8943 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8944 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8945 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8946 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8947 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8948 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8949 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8950 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8951 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8952 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8953 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8954 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8955 "'>\n" 8956 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 8957 "<!ELEMENT doc EMPTY>\n" 8958 "]>\n<doc/>"; 8959 int i; 8960 const int max_alloc_count = 20; 8961 8962 for (i = 0; i < max_alloc_count; i++) { 8963 allocation_count = i; 8964 dummy_handler_flags = 0; 8965 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8966 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8967 != XML_STATUS_ERROR) 8968 break; 8969 /* See comment in test_alloc_parse_xdecl() */ 8970 alloc_teardown(); 8971 alloc_setup(); 8972 } 8973 if (i == 0) 8974 fail("Parse succeeded despite allocation failures"); 8975 if (i == max_alloc_count) 8976 fail("Parse failed at maximum allocation count"); 8977 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 8978 fail("Notation handler not called"); 8979 } 8980 END_TEST 8981 8982 START_TEST(test_alloc_nested_groups) { 8983 const char *text 8984 = "<!DOCTYPE doc [\n" 8985 "<!ELEMENT doc " 8986 /* Sixteen elements per line */ 8987 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 8988 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 8989 "))))))))))))))))))))))))))))))))>\n" 8990 "<!ELEMENT e EMPTY>" 8991 "]>\n" 8992 "<doc><e/></doc>"; 8993 CharData storage; 8994 int i; 8995 const int max_alloc_count = 20; 8996 8997 for (i = 0; i < max_alloc_count; i++) { 8998 allocation_count = i; 8999 CharData_Init(&storage); 9000 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9001 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9002 XML_SetUserData(g_parser, &storage); 9003 dummy_handler_flags = 0; 9004 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9005 != XML_STATUS_ERROR) 9006 break; 9007 /* See comment in test_alloc_parse_xdecl() */ 9008 alloc_teardown(); 9009 alloc_setup(); 9010 } 9011 9012 if (i == 0) 9013 fail("Parse succeeded despite failing reallocator"); 9014 if (i == max_alloc_count) 9015 fail("Parse failed at maximum reallocation count"); 9016 CharData_CheckXMLChars(&storage, XCS("doce")); 9017 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9018 fail("Element handler not fired"); 9019 } 9020 END_TEST 9021 9022 START_TEST(test_alloc_realloc_nested_groups) { 9023 const char *text 9024 = "<!DOCTYPE doc [\n" 9025 "<!ELEMENT doc " 9026 /* Sixteen elements per line */ 9027 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9028 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9029 "))))))))))))))))))))))))))))))))>\n" 9030 "<!ELEMENT e EMPTY>" 9031 "]>\n" 9032 "<doc><e/></doc>"; 9033 CharData storage; 9034 int i; 9035 const int max_realloc_count = 10; 9036 9037 for (i = 0; i < max_realloc_count; i++) { 9038 reallocation_count = i; 9039 CharData_Init(&storage); 9040 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9041 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9042 XML_SetUserData(g_parser, &storage); 9043 dummy_handler_flags = 0; 9044 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9045 != XML_STATUS_ERROR) 9046 break; 9047 /* See comment in test_alloc_parse_xdecl() */ 9048 alloc_teardown(); 9049 alloc_setup(); 9050 } 9051 9052 if (i == 0) 9053 fail("Parse succeeded despite failing reallocator"); 9054 if (i == max_realloc_count) 9055 fail("Parse failed at maximum reallocation count"); 9056 CharData_CheckXMLChars(&storage, XCS("doce")); 9057 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9058 fail("Element handler not fired"); 9059 } 9060 END_TEST 9061 9062 START_TEST(test_alloc_large_group) { 9063 const char *text = "<!DOCTYPE doc [\n" 9064 "<!ELEMENT doc (" 9065 "a1|a2|a3|a4|a5|a6|a7|a8|" 9066 "b1|b2|b3|b4|b5|b6|b7|b8|" 9067 "c1|c2|c3|c4|c5|c6|c7|c8|" 9068 "d1|d2|d3|d4|d5|d6|d7|d8|" 9069 "e1" 9070 ")+>\n" 9071 "]>\n" 9072 "<doc>\n" 9073 "<a1/>\n" 9074 "</doc>\n"; 9075 int i; 9076 const int max_alloc_count = 50; 9077 9078 for (i = 0; i < max_alloc_count; i++) { 9079 allocation_count = i; 9080 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9081 dummy_handler_flags = 0; 9082 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9083 != XML_STATUS_ERROR) 9084 break; 9085 /* See comment in test_alloc_parse_xdecl() */ 9086 alloc_teardown(); 9087 alloc_setup(); 9088 } 9089 if (i == 0) 9090 fail("Parse succeeded despite failing allocator"); 9091 if (i == max_alloc_count) 9092 fail("Parse failed at maximum allocation count"); 9093 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9094 fail("Element handler flag not raised"); 9095 } 9096 END_TEST 9097 9098 START_TEST(test_alloc_realloc_group_choice) { 9099 const char *text = "<!DOCTYPE doc [\n" 9100 "<!ELEMENT doc (" 9101 "a1|a2|a3|a4|a5|a6|a7|a8|" 9102 "b1|b2|b3|b4|b5|b6|b7|b8|" 9103 "c1|c2|c3|c4|c5|c6|c7|c8|" 9104 "d1|d2|d3|d4|d5|d6|d7|d8|" 9105 "e1" 9106 ")+>\n" 9107 "]>\n" 9108 "<doc>\n" 9109 "<a1/>\n" 9110 "<b2 attr='foo'>This is a foo</b2>\n" 9111 "<c3></c3>\n" 9112 "</doc>\n"; 9113 int i; 9114 const int max_realloc_count = 10; 9115 9116 for (i = 0; i < max_realloc_count; i++) { 9117 reallocation_count = i; 9118 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9119 dummy_handler_flags = 0; 9120 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9121 != XML_STATUS_ERROR) 9122 break; 9123 /* See comment in test_alloc_parse_xdecl() */ 9124 alloc_teardown(); 9125 alloc_setup(); 9126 } 9127 if (i == 0) 9128 fail("Parse succeeded despite failing reallocator"); 9129 if (i == max_realloc_count) 9130 fail("Parse failed at maximum reallocation count"); 9131 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9132 fail("Element handler flag not raised"); 9133 } 9134 END_TEST 9135 9136 START_TEST(test_alloc_pi_in_epilog) { 9137 const char *text = "<doc></doc>\n" 9138 "<?pi in epilog?>"; 9139 int i; 9140 const int max_alloc_count = 15; 9141 9142 for (i = 0; i < max_alloc_count; i++) { 9143 allocation_count = i; 9144 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 9145 dummy_handler_flags = 0; 9146 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9147 != XML_STATUS_ERROR) 9148 break; 9149 /* See comment in test_alloc_parse_xdecl() */ 9150 alloc_teardown(); 9151 alloc_setup(); 9152 } 9153 if (i == 0) 9154 fail("Parse completed despite failing allocator"); 9155 if (i == max_alloc_count) 9156 fail("Parse failed at maximum allocation count"); 9157 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG) 9158 fail("Processing instruction handler not invoked"); 9159 } 9160 END_TEST 9161 9162 START_TEST(test_alloc_comment_in_epilog) { 9163 const char *text = "<doc></doc>\n" 9164 "<!-- comment in epilog -->"; 9165 int i; 9166 const int max_alloc_count = 15; 9167 9168 for (i = 0; i < max_alloc_count; i++) { 9169 allocation_count = i; 9170 XML_SetCommentHandler(g_parser, dummy_comment_handler); 9171 dummy_handler_flags = 0; 9172 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9173 != XML_STATUS_ERROR) 9174 break; 9175 /* See comment in test_alloc_parse_xdecl() */ 9176 alloc_teardown(); 9177 alloc_setup(); 9178 } 9179 if (i == 0) 9180 fail("Parse completed despite failing allocator"); 9181 if (i == max_alloc_count) 9182 fail("Parse failed at maximum allocation count"); 9183 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG) 9184 fail("Processing instruction handler not invoked"); 9185 } 9186 END_TEST 9187 9188 START_TEST(test_alloc_realloc_long_attribute_value) { 9189 const char *text 9190 = "<!DOCTYPE doc [<!ENTITY foo '" 9191 /* Each line is 64 characters */ 9192 "This entity will be substituted as an attribute value, and is " 9193 "calculated to be exactly long enough that the terminating NUL " 9194 "that the library adds internally will trigger the string pool to" 9195 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9196 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9197 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9198 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9199 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9200 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9201 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9202 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9203 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9204 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9205 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9206 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9207 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9208 "'>]>\n" 9209 "<doc a='&foo;'></doc>"; 9210 int i; 9211 const int max_realloc_count = 10; 9212 9213 for (i = 0; i < max_realloc_count; i++) { 9214 reallocation_count = i; 9215 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9216 != XML_STATUS_ERROR) 9217 break; 9218 /* See comment in test_alloc_parse_xdecl() */ 9219 alloc_teardown(); 9220 alloc_setup(); 9221 } 9222 if (i == 0) 9223 fail("Parse succeeded despite failing reallocator"); 9224 if (i == max_realloc_count) 9225 fail("Parse failed at maximum reallocation count"); 9226 } 9227 END_TEST 9228 9229 START_TEST(test_alloc_attribute_whitespace) { 9230 const char *text = "<doc a=' '></doc>"; 9231 int i; 9232 const int max_alloc_count = 15; 9233 9234 for (i = 0; i < max_alloc_count; i++) { 9235 allocation_count = i; 9236 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9237 != XML_STATUS_ERROR) 9238 break; 9239 /* See comment in test_alloc_parse_xdecl() */ 9240 alloc_teardown(); 9241 alloc_setup(); 9242 } 9243 if (i == 0) 9244 fail("Parse succeeded despite failing allocator"); 9245 if (i == max_alloc_count) 9246 fail("Parse failed at maximum allocation count"); 9247 } 9248 END_TEST 9249 9250 START_TEST(test_alloc_attribute_predefined_entity) { 9251 const char *text = "<doc a='&'></doc>"; 9252 int i; 9253 const int max_alloc_count = 15; 9254 9255 for (i = 0; i < max_alloc_count; i++) { 9256 allocation_count = i; 9257 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9258 != XML_STATUS_ERROR) 9259 break; 9260 /* See comment in test_alloc_parse_xdecl() */ 9261 alloc_teardown(); 9262 alloc_setup(); 9263 } 9264 if (i == 0) 9265 fail("Parse succeeded despite failing allocator"); 9266 if (i == max_alloc_count) 9267 fail("Parse failed at maximum allocation count"); 9268 } 9269 END_TEST 9270 9271 /* Test that a character reference at the end of a suitably long 9272 * default value for an attribute can trigger pool growth, and recovers 9273 * if the allocator fails on it. 9274 */ 9275 START_TEST(test_alloc_long_attr_default_with_char_ref) { 9276 const char *text 9277 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '" 9278 /* 64 characters per line */ 9279 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9280 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9281 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9282 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9283 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9284 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9285 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9286 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9287 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9288 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9289 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9290 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9291 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9292 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9293 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9294 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI" 9295 "1'>]>\n" 9296 "<doc/>"; 9297 int i; 9298 const int max_alloc_count = 20; 9299 9300 for (i = 0; i < max_alloc_count; i++) { 9301 allocation_count = i; 9302 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9303 != XML_STATUS_ERROR) 9304 break; 9305 /* See comment in test_alloc_parse_xdecl() */ 9306 alloc_teardown(); 9307 alloc_setup(); 9308 } 9309 if (i == 0) 9310 fail("Parse succeeded despite failing allocator"); 9311 if (i == max_alloc_count) 9312 fail("Parse failed at maximum allocation count"); 9313 } 9314 END_TEST 9315 9316 /* Test that a long character reference substitution triggers a pool 9317 * expansion correctly for an attribute value. 9318 */ 9319 START_TEST(test_alloc_long_attr_value) { 9320 const char *text 9321 = "<!DOCTYPE test [<!ENTITY foo '\n" 9322 /* 64 characters per line */ 9323 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9324 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9325 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9326 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9327 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9328 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9329 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9330 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9331 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9332 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9333 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9334 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9335 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9336 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9337 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9338 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9339 "'>]>\n" 9340 "<test a='&foo;'/>"; 9341 int i; 9342 const int max_alloc_count = 25; 9343 9344 for (i = 0; i < max_alloc_count; i++) { 9345 allocation_count = i; 9346 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9347 != XML_STATUS_ERROR) 9348 break; 9349 /* See comment in test_alloc_parse_xdecl() */ 9350 alloc_teardown(); 9351 alloc_setup(); 9352 } 9353 if (i == 0) 9354 fail("Parse succeeded despite failing allocator"); 9355 if (i == max_alloc_count) 9356 fail("Parse failed at maximum allocation count"); 9357 } 9358 END_TEST 9359 9360 /* Test that an error in a nested parameter entity substitution is 9361 * handled correctly. It seems unlikely that the code path being 9362 * exercised can be reached purely by carefully crafted XML, but an 9363 * allocation error in the right place will definitely do it. 9364 */ 9365 START_TEST(test_alloc_nested_entities) { 9366 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 9367 "<doc />"; 9368 ExtFaults test_data 9369 = {"<!ENTITY % pe1 '" 9370 /* 64 characters per line */ 9371 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9372 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9373 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9374 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9375 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9376 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9377 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9378 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9379 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9380 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9381 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9382 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9383 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9384 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9385 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9386 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9387 "'>\n" 9388 "<!ENTITY % pe2 '%pe1;'>\n" 9389 "%pe2;", 9390 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY}; 9391 9392 /* Causes an allocation error in a nested storeEntityValue() */ 9393 allocation_count = 12; 9394 XML_SetUserData(g_parser, &test_data); 9395 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9396 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 9397 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 9398 "Entity allocation failure not noted"); 9399 } 9400 END_TEST 9401 9402 START_TEST(test_alloc_realloc_param_entity_newline) { 9403 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9404 "<doc/>"; 9405 char dtd_text[] 9406 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9407 /* 64 characters per line */ 9408 "This default value is carefully crafted so that the carriage " 9409 "return right at the end of the entity string causes an internal " 9410 "string pool to have to grow. This allows us to test the alloc " 9411 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9412 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9413 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9414 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9415 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9416 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9417 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9418 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9419 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9420 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9421 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9422 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9423 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE" 9424 "\">\n'>" 9425 "%pe;\n"; 9426 int i; 9427 const int max_realloc_count = 5; 9428 9429 for (i = 0; i < max_realloc_count; i++) { 9430 reallocation_count = i; 9431 XML_SetUserData(g_parser, dtd_text); 9432 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9433 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9434 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9435 != XML_STATUS_ERROR) 9436 break; 9437 /* See comment in test_alloc_parse_xdecl() */ 9438 alloc_teardown(); 9439 alloc_setup(); 9440 } 9441 if (i == 0) 9442 fail("Parse succeeded despite failing reallocator"); 9443 if (i == max_realloc_count) 9444 fail("Parse failed at maximum reallocation count"); 9445 } 9446 END_TEST 9447 9448 START_TEST(test_alloc_realloc_ce_extends_pe) { 9449 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9450 "<doc/>"; 9451 char dtd_text[] 9452 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9453 /* 64 characters per line */ 9454 "This default value is carefully crafted so that the character " 9455 "entity at the end causes an internal string pool to have to " 9456 "grow. This allows us to test the allocation failure path from " 9457 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9458 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9459 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9460 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9461 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9462 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9463 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9464 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9465 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9466 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9467 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9468 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9469 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ" 9470 "\">\n'>" 9471 "%pe;\n"; 9472 int i; 9473 const int max_realloc_count = 5; 9474 9475 for (i = 0; i < max_realloc_count; i++) { 9476 reallocation_count = i; 9477 XML_SetUserData(g_parser, dtd_text); 9478 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9479 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9480 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9481 != XML_STATUS_ERROR) 9482 break; 9483 /* See comment in test_alloc_parse_xdecl() */ 9484 alloc_teardown(); 9485 alloc_setup(); 9486 } 9487 if (i == 0) 9488 fail("Parse succeeded despite failing reallocator"); 9489 if (i == max_realloc_count) 9490 fail("Parse failed at maximum reallocation count"); 9491 } 9492 END_TEST 9493 9494 START_TEST(test_alloc_realloc_attributes) { 9495 const char *text = "<!DOCTYPE doc [\n" 9496 " <!ATTLIST doc\n" 9497 " a1 (a|b|c) 'a'\n" 9498 " a2 (foo|bar) #IMPLIED\n" 9499 " a3 NMTOKEN #IMPLIED\n" 9500 " a4 NMTOKENS #IMPLIED\n" 9501 " a5 ID #IMPLIED\n" 9502 " a6 IDREF #IMPLIED\n" 9503 " a7 IDREFS #IMPLIED\n" 9504 " a8 ENTITY #IMPLIED\n" 9505 " a9 ENTITIES #IMPLIED\n" 9506 " a10 CDATA #IMPLIED\n" 9507 " >]>\n" 9508 "<doc>wombat</doc>\n"; 9509 int i; 9510 const int max_realloc_count = 5; 9511 9512 for (i = 0; i < max_realloc_count; i++) { 9513 reallocation_count = i; 9514 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9515 != XML_STATUS_ERROR) 9516 break; 9517 /* See comment in test_alloc_parse_xdecl() */ 9518 alloc_teardown(); 9519 alloc_setup(); 9520 } 9521 9522 if (i == 0) 9523 fail("Parse succeeded despite failing reallocator"); 9524 if (i == max_realloc_count) 9525 fail("Parse failed at maximum reallocation count"); 9526 } 9527 END_TEST 9528 9529 START_TEST(test_alloc_long_doc_name) { 9530 const char *text = 9531 /* 64 characters per line */ 9532 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr" 9533 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9544 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9545 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9546 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9548 " a='1'/>"; 9549 int i; 9550 const int max_alloc_count = 20; 9551 9552 for (i = 0; i < max_alloc_count; i++) { 9553 allocation_count = i; 9554 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9555 != XML_STATUS_ERROR) 9556 break; 9557 /* See comment in test_alloc_parse_xdecl() */ 9558 alloc_teardown(); 9559 alloc_setup(); 9560 } 9561 if (i == 0) 9562 fail("Parsing worked despite failing reallocations"); 9563 else if (i == max_alloc_count) 9564 fail("Parsing failed even at max reallocation count"); 9565 } 9566 END_TEST 9567 9568 START_TEST(test_alloc_long_base) { 9569 const char *text = "<!DOCTYPE doc [\n" 9570 " <!ENTITY e SYSTEM 'foo'>\n" 9571 "]>\n" 9572 "<doc>&e;</doc>"; 9573 char entity_text[] = "Hello world"; 9574 const XML_Char *base = 9575 /* 64 characters per line */ 9576 /* clang-format off */ 9577 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t") 9578 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9579 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9580 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9581 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9582 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9583 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9584 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9585 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9586 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9587 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9588 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9589 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9590 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9591 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9592 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"); 9593 /* clang-format on */ 9594 int i; 9595 const int max_alloc_count = 25; 9596 9597 for (i = 0; i < max_alloc_count; i++) { 9598 allocation_count = i; 9599 XML_SetUserData(g_parser, entity_text); 9600 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9601 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9602 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) { 9603 XML_ParserReset(g_parser, NULL); 9604 continue; 9605 } 9606 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9607 != XML_STATUS_ERROR) 9608 break; 9609 /* See comment in test_alloc_parse_xdecl() */ 9610 alloc_teardown(); 9611 alloc_setup(); 9612 } 9613 if (i == 0) 9614 fail("Parsing worked despite failing allocations"); 9615 else if (i == max_alloc_count) 9616 fail("Parsing failed even at max allocation count"); 9617 } 9618 END_TEST 9619 9620 START_TEST(test_alloc_long_public_id) { 9621 const char *text 9622 = "<!DOCTYPE doc [\n" 9623 " <!ENTITY e PUBLIC '" 9624 /* 64 characters per line */ 9625 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec" 9626 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9627 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9628 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9629 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9630 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9631 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9632 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9633 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9634 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9635 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9636 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9637 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9638 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9639 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9640 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9641 "' 'bar'>\n" 9642 "]>\n" 9643 "<doc>&e;</doc>"; 9644 char entity_text[] = "Hello world"; 9645 int i; 9646 const int max_alloc_count = 40; 9647 9648 for (i = 0; i < max_alloc_count; i++) { 9649 allocation_count = i; 9650 XML_SetUserData(g_parser, entity_text); 9651 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9652 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9653 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9654 != XML_STATUS_ERROR) 9655 break; 9656 /* See comment in test_alloc_parse_xdecl() */ 9657 alloc_teardown(); 9658 alloc_setup(); 9659 } 9660 if (i == 0) 9661 fail("Parsing worked despite failing allocations"); 9662 else if (i == max_alloc_count) 9663 fail("Parsing failed even at max allocation count"); 9664 } 9665 END_TEST 9666 9667 START_TEST(test_alloc_long_entity_value) { 9668 const char *text 9669 = "<!DOCTYPE doc [\n" 9670 " <!ENTITY e1 '" 9671 /* 64 characters per line */ 9672 "Long entity value that should provoke a string pool to grow whil" 9673 "e setting up to parse the external entity below. xyz0123456789AB" 9674 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9675 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9676 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9677 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9678 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9679 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9680 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9681 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9682 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9683 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9684 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9685 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9686 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9687 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9688 "'>\n" 9689 " <!ENTITY e2 SYSTEM 'bar'>\n" 9690 "]>\n" 9691 "<doc>&e2;</doc>"; 9692 char entity_text[] = "Hello world"; 9693 int i; 9694 const int max_alloc_count = 40; 9695 9696 for (i = 0; i < max_alloc_count; i++) { 9697 allocation_count = i; 9698 XML_SetUserData(g_parser, entity_text); 9699 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9700 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9701 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9702 != XML_STATUS_ERROR) 9703 break; 9704 /* See comment in test_alloc_parse_xdecl() */ 9705 alloc_teardown(); 9706 alloc_setup(); 9707 } 9708 if (i == 0) 9709 fail("Parsing worked despite failing allocations"); 9710 else if (i == max_alloc_count) 9711 fail("Parsing failed even at max allocation count"); 9712 } 9713 END_TEST 9714 9715 START_TEST(test_alloc_long_notation) { 9716 const char *text 9717 = "<!DOCTYPE doc [\n" 9718 " <!NOTATION note SYSTEM '" 9719 /* 64 characters per line */ 9720 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 9721 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9723 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9724 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9725 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9726 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9727 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9728 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9729 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9730 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9731 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9732 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9733 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9734 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9735 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9736 "'>\n" 9737 " <!ENTITY e1 SYSTEM 'foo' NDATA " 9738 /* 64 characters per line */ 9739 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 9740 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9741 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9742 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9743 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9744 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9745 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9746 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9747 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9748 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9749 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9750 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9751 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9752 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9753 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9754 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9755 ">\n" 9756 " <!ENTITY e2 SYSTEM 'bar'>\n" 9757 "]>\n" 9758 "<doc>&e2;</doc>"; 9759 ExtOption options[] 9760 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}}; 9761 int i; 9762 const int max_alloc_count = 40; 9763 9764 for (i = 0; i < max_alloc_count; i++) { 9765 allocation_count = i; 9766 XML_SetUserData(g_parser, options); 9767 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9768 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 9769 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9770 != XML_STATUS_ERROR) 9771 break; 9772 9773 /* See comment in test_alloc_parse_xdecl() */ 9774 alloc_teardown(); 9775 alloc_setup(); 9776 } 9777 if (i == 0) 9778 fail("Parsing worked despite failing allocations"); 9779 else if (i == max_alloc_count) 9780 fail("Parsing failed even at max allocation count"); 9781 } 9782 END_TEST 9783 9784 static void 9785 nsalloc_setup(void) { 9786 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 9787 XML_Char ns_sep[2] = {' ', '\0'}; 9788 9789 /* Ensure the parser creation will go through */ 9790 allocation_count = ALLOC_ALWAYS_SUCCEED; 9791 reallocation_count = REALLOC_ALWAYS_SUCCEED; 9792 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep); 9793 if (g_parser == NULL) 9794 fail("Parser not created"); 9795 } 9796 9797 static void 9798 nsalloc_teardown(void) { 9799 basic_teardown(); 9800 } 9801 9802 /* Test the effects of allocation failure in simple namespace parsing. 9803 * Based on test_ns_default_with_empty_uri() 9804 */ 9805 START_TEST(test_nsalloc_xmlns) { 9806 const char *text = "<doc xmlns='http://example.org/'>\n" 9807 " <e xmlns=''/>\n" 9808 "</doc>"; 9809 unsigned int i; 9810 const unsigned int max_alloc_count = 30; 9811 9812 for (i = 0; i < max_alloc_count; i++) { 9813 allocation_count = i; 9814 /* Exercise more code paths with a default handler */ 9815 XML_SetDefaultHandler(g_parser, dummy_default_handler); 9816 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9817 != XML_STATUS_ERROR) 9818 break; 9819 /* Resetting the parser is insufficient, because some memory 9820 * allocations are cached within the parser. Instead we use 9821 * the teardown and setup routines to ensure that we have the 9822 * right sort of parser back in our hands. 9823 */ 9824 nsalloc_teardown(); 9825 nsalloc_setup(); 9826 } 9827 if (i == 0) 9828 fail("Parsing worked despite failing allocations"); 9829 else if (i == max_alloc_count) 9830 fail("Parsing failed even at maximum allocation count"); 9831 } 9832 END_TEST 9833 9834 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */ 9835 START_TEST(test_nsalloc_parse_buffer) { 9836 const char *text = "<doc>Hello</doc>"; 9837 void *buffer; 9838 9839 /* Try a parse before the start of the world */ 9840 /* (Exercises new code path) */ 9841 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 9842 fail("Pre-init XML_ParseBuffer not faulted"); 9843 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER) 9844 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 9845 9846 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */); 9847 if (buffer == NULL) 9848 fail("Could not acquire parse buffer"); 9849 9850 allocation_count = 0; 9851 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 9852 fail("Pre-init XML_ParseBuffer not faulted"); 9853 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY) 9854 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 9855 9856 /* Now with actual memory allocation */ 9857 allocation_count = ALLOC_ALWAYS_SUCCEED; 9858 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK) 9859 xml_failure(g_parser); 9860 9861 /* Check that resuming an unsuspended parser is faulted */ 9862 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 9863 fail("Resuming unsuspended parser not faulted"); 9864 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED) 9865 xml_failure(g_parser); 9866 9867 /* Get the parser into suspended state */ 9868 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 9869 resumable = XML_TRUE; 9870 buffer = XML_GetBuffer(g_parser, (int)strlen(text)); 9871 if (buffer == NULL) 9872 fail("Could not acquire parse buffer"); 9873 assert(buffer != NULL); 9874 memcpy(buffer, text, strlen(text)); 9875 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 9876 != XML_STATUS_SUSPENDED) 9877 xml_failure(g_parser); 9878 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 9879 xml_failure(g_parser); 9880 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 9881 != XML_STATUS_ERROR) 9882 fail("Suspended XML_ParseBuffer not faulted"); 9883 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 9884 xml_failure(g_parser); 9885 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 9886 fail("Suspended XML_GetBuffer not faulted"); 9887 9888 /* Get it going again and complete the world */ 9889 XML_SetCharacterDataHandler(g_parser, NULL); 9890 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 9891 xml_failure(g_parser); 9892 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 9893 != XML_STATUS_ERROR) 9894 fail("Post-finishing XML_ParseBuffer not faulted"); 9895 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED) 9896 xml_failure(g_parser); 9897 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 9898 fail("Post-finishing XML_GetBuffer not faulted"); 9899 } 9900 END_TEST 9901 9902 /* Check handling of long prefix names (pool growth) */ 9903 START_TEST(test_nsalloc_long_prefix) { 9904 const char *text 9905 = "<" 9906 /* 64 characters per line */ 9907 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9908 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9909 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9910 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9911 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9913 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9923 ":foo xmlns:" 9924 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9925 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9926 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9927 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9928 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9929 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9930 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9931 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9932 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9933 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9934 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9935 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9936 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9937 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9938 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9939 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9940 "='http://example.org/'>" 9941 "</" 9942 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9943 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9944 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9945 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9946 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9947 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9948 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9949 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9950 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9951 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9952 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9953 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9954 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9955 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9956 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9957 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9958 ":foo>"; 9959 int i; 9960 const int max_alloc_count = 40; 9961 9962 for (i = 0; i < max_alloc_count; i++) { 9963 allocation_count = i; 9964 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9965 != XML_STATUS_ERROR) 9966 break; 9967 /* See comment in test_nsalloc_xmlns() */ 9968 nsalloc_teardown(); 9969 nsalloc_setup(); 9970 } 9971 if (i == 0) 9972 fail("Parsing worked despite failing allocations"); 9973 else if (i == max_alloc_count) 9974 fail("Parsing failed even at max allocation count"); 9975 } 9976 END_TEST 9977 9978 /* Check handling of long uri names (pool growth) */ 9979 START_TEST(test_nsalloc_long_uri) { 9980 const char *text 9981 = "<foo:e xmlns:foo='http://example.org/" 9982 /* 64 characters per line */ 9983 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9984 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9985 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9986 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9987 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9988 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9989 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9990 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9991 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9992 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9993 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9994 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9995 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9996 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9997 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9998 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 9999 "' bar:a='12'\n" 10000 "xmlns:bar='http://example.org/" 10001 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10002 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10003 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10004 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10005 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10006 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10007 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10008 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10009 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10010 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10011 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10012 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10013 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10014 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10015 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10016 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10017 "'>" 10018 "</foo:e>"; 10019 int i; 10020 const int max_alloc_count = 40; 10021 10022 for (i = 0; i < max_alloc_count; i++) { 10023 allocation_count = i; 10024 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10025 != XML_STATUS_ERROR) 10026 break; 10027 /* See comment in test_nsalloc_xmlns() */ 10028 nsalloc_teardown(); 10029 nsalloc_setup(); 10030 } 10031 if (i == 0) 10032 fail("Parsing worked despite failing allocations"); 10033 else if (i == max_alloc_count) 10034 fail("Parsing failed even at max allocation count"); 10035 } 10036 END_TEST 10037 10038 /* Test handling of long attribute names with prefixes */ 10039 START_TEST(test_nsalloc_long_attr) { 10040 const char *text 10041 = "<foo:e xmlns:foo='http://example.org/' bar:" 10042 /* 64 characters per line */ 10043 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10044 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10045 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10046 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10047 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10048 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10049 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10050 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10051 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10052 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10053 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10054 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10055 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10056 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10057 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10058 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10059 "='12'\n" 10060 "xmlns:bar='http://example.org/'>" 10061 "</foo:e>"; 10062 int i; 10063 const int max_alloc_count = 40; 10064 10065 for (i = 0; i < max_alloc_count; i++) { 10066 allocation_count = i; 10067 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10068 != XML_STATUS_ERROR) 10069 break; 10070 /* See comment in test_nsalloc_xmlns() */ 10071 nsalloc_teardown(); 10072 nsalloc_setup(); 10073 } 10074 if (i == 0) 10075 fail("Parsing worked despite failing allocations"); 10076 else if (i == max_alloc_count) 10077 fail("Parsing failed even at max allocation count"); 10078 } 10079 END_TEST 10080 10081 /* Test handling of an attribute name with a long namespace prefix */ 10082 START_TEST(test_nsalloc_long_attr_prefix) { 10083 const char *text 10084 = "<foo:e xmlns:foo='http://example.org/' " 10085 /* 64 characters per line */ 10086 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10087 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10088 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10089 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10090 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10091 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10092 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10093 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10094 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10095 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10096 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10097 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10098 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10099 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10100 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10101 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10102 ":a='12'\n" 10103 "xmlns:" 10104 /* 64 characters per line */ 10105 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10106 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10107 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10108 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10109 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10110 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10111 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10112 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10113 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10114 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10115 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10116 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10117 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10118 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10119 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10120 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10121 "='http://example.org/'>" 10122 "</foo:e>"; 10123 const XML_Char *elemstr[] = { 10124 /* clang-format off */ 10125 XCS("http://example.org/ e foo"), 10126 XCS("http://example.org/ a ") 10127 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10128 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10129 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10130 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10131 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10132 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10133 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10134 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10135 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10136 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10137 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10138 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10139 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10140 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10141 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10142 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10143 /* clang-format on */ 10144 }; 10145 int i; 10146 const int max_alloc_count = 40; 10147 10148 for (i = 0; i < max_alloc_count; i++) { 10149 allocation_count = i; 10150 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10151 XML_SetUserData(g_parser, (void *)elemstr); 10152 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10153 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10154 != XML_STATUS_ERROR) 10155 break; 10156 /* See comment in test_nsalloc_xmlns() */ 10157 nsalloc_teardown(); 10158 nsalloc_setup(); 10159 } 10160 if (i == 0) 10161 fail("Parsing worked despite failing allocations"); 10162 else if (i == max_alloc_count) 10163 fail("Parsing failed even at max allocation count"); 10164 } 10165 END_TEST 10166 10167 /* Test attribute handling in the face of a dodgy reallocator */ 10168 START_TEST(test_nsalloc_realloc_attributes) { 10169 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 10170 " xmlns:bar='http://example.org/'>" 10171 "</foo:e>"; 10172 int i; 10173 const int max_realloc_count = 10; 10174 10175 for (i = 0; i < max_realloc_count; i++) { 10176 reallocation_count = i; 10177 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10178 != XML_STATUS_ERROR) 10179 break; 10180 /* See comment in test_nsalloc_xmlns() */ 10181 nsalloc_teardown(); 10182 nsalloc_setup(); 10183 } 10184 if (i == 0) 10185 fail("Parsing worked despite failing reallocations"); 10186 else if (i == max_realloc_count) 10187 fail("Parsing failed at max reallocation count"); 10188 } 10189 END_TEST 10190 10191 /* Test long element names with namespaces under a failing allocator */ 10192 START_TEST(test_nsalloc_long_element) { 10193 const char *text 10194 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 10195 " xmlns:foo='http://example.org/' bar:a='12'\n" 10196 " xmlns:bar='http://example.org/'>" 10197 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 10198 const XML_Char *elemstr[] 10199 = {XCS("http://example.org/") 10200 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 10201 XCS("http://example.org/ a bar")}; 10202 int i; 10203 const int max_alloc_count = 30; 10204 10205 for (i = 0; i < max_alloc_count; i++) { 10206 allocation_count = i; 10207 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10208 XML_SetUserData(g_parser, (void *)elemstr); 10209 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10210 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10211 != XML_STATUS_ERROR) 10212 break; 10213 /* See comment in test_nsalloc_xmlns() */ 10214 nsalloc_teardown(); 10215 nsalloc_setup(); 10216 } 10217 if (i == 0) 10218 fail("Parsing worked despite failing reallocations"); 10219 else if (i == max_alloc_count) 10220 fail("Parsing failed at max reallocation count"); 10221 } 10222 END_TEST 10223 10224 /* Test the effects of reallocation failure when reassigning a 10225 * binding. 10226 * 10227 * XML_ParserReset does not free the BINDING structures used by a 10228 * parser, but instead adds them to an internal free list to be reused 10229 * as necessary. Likewise the URI buffers allocated for the binding 10230 * aren't freed, but kept attached to their existing binding. If the 10231 * new binding has a longer URI, it will need reallocation. This test 10232 * provokes that reallocation, and tests the control path if it fails. 10233 */ 10234 START_TEST(test_nsalloc_realloc_binding_uri) { 10235 const char *first = "<doc xmlns='http://example.org/'>\n" 10236 " <e xmlns='' />\n" 10237 "</doc>"; 10238 const char *second 10239 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n" 10240 " <e xmlns='' />\n" 10241 "</doc>"; 10242 unsigned i; 10243 const unsigned max_realloc_count = 10; 10244 10245 /* First, do a full parse that will leave bindings around */ 10246 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE) 10247 == XML_STATUS_ERROR) 10248 xml_failure(g_parser); 10249 10250 /* Now repeat with a longer URI and a duff reallocator */ 10251 for (i = 0; i < max_realloc_count; i++) { 10252 XML_ParserReset(g_parser, NULL); 10253 reallocation_count = i; 10254 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE) 10255 != XML_STATUS_ERROR) 10256 break; 10257 } 10258 if (i == 0) 10259 fail("Parsing worked despite failing reallocation"); 10260 else if (i == max_realloc_count) 10261 fail("Parsing failed at max reallocation count"); 10262 } 10263 END_TEST 10264 10265 /* Check handling of long prefix names (pool growth) */ 10266 START_TEST(test_nsalloc_realloc_long_prefix) { 10267 const char *text 10268 = "<" 10269 /* 64 characters per line */ 10270 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10271 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10272 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10273 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10274 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10275 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10276 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10277 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10278 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10279 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10280 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10281 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10282 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10283 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10285 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10286 ":foo xmlns:" 10287 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10288 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10289 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10290 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10291 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10292 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10293 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10294 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10295 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10296 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10297 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10298 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10299 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10300 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10301 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10302 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10303 "='http://example.org/'>" 10304 "</" 10305 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10306 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10307 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10308 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10309 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10310 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10311 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10312 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10313 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10314 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10315 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10316 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10317 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10318 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10319 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10320 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10321 ":foo>"; 10322 int i; 10323 const int max_realloc_count = 12; 10324 10325 for (i = 0; i < max_realloc_count; i++) { 10326 reallocation_count = i; 10327 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10328 != XML_STATUS_ERROR) 10329 break; 10330 /* See comment in test_nsalloc_xmlns() */ 10331 nsalloc_teardown(); 10332 nsalloc_setup(); 10333 } 10334 if (i == 0) 10335 fail("Parsing worked despite failing reallocations"); 10336 else if (i == max_realloc_count) 10337 fail("Parsing failed even at max reallocation count"); 10338 } 10339 END_TEST 10340 10341 /* Check handling of even long prefix names (different code path) */ 10342 START_TEST(test_nsalloc_realloc_longer_prefix) { 10343 const char *text 10344 = "<" 10345 /* 64 characters per line */ 10346 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10347 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10348 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10349 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10350 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10351 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10352 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10354 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10355 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10356 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10357 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10358 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10359 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10360 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10361 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10362 "Q:foo xmlns:" 10363 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10364 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10365 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10366 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10367 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10368 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10369 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10370 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10371 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10372 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10373 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10374 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10375 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10376 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10377 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10378 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10379 "Q='http://example.org/'>" 10380 "</" 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 "Q:foo>"; 10398 int i; 10399 const int max_realloc_count = 12; 10400 10401 for (i = 0; i < max_realloc_count; i++) { 10402 reallocation_count = i; 10403 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10404 != XML_STATUS_ERROR) 10405 break; 10406 /* See comment in test_nsalloc_xmlns() */ 10407 nsalloc_teardown(); 10408 nsalloc_setup(); 10409 } 10410 if (i == 0) 10411 fail("Parsing worked despite failing reallocations"); 10412 else if (i == max_realloc_count) 10413 fail("Parsing failed even at max reallocation count"); 10414 } 10415 END_TEST 10416 10417 START_TEST(test_nsalloc_long_namespace) { 10418 const char *text1 10419 = "<" 10420 /* 64 characters per line */ 10421 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10422 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10423 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10424 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10425 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10426 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10427 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10428 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10429 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10430 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10431 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10432 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10433 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10434 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10435 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10436 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10437 ":e xmlns:" 10438 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10439 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10440 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10441 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10442 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10443 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10444 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10445 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10446 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10447 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10448 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10449 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10450 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10451 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10452 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10453 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10454 "='http://example.org/'>\n"; 10455 const char *text2 10456 = "<" 10457 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10458 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10459 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10460 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10461 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10462 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10463 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10464 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10465 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10466 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10467 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10468 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10469 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10470 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10471 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10472 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10473 ":f " 10474 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10475 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10476 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10477 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10478 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10479 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10480 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10481 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10482 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10483 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10484 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10485 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10486 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10487 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10488 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10489 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10490 ":attr='foo'/>\n" 10491 "</" 10492 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10493 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10494 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10495 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10496 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10497 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10498 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10499 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10500 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10501 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10502 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10503 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10504 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10505 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10506 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10507 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10508 ":e>"; 10509 int i; 10510 const int max_alloc_count = 40; 10511 10512 for (i = 0; i < max_alloc_count; i++) { 10513 allocation_count = i; 10514 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 10515 != XML_STATUS_ERROR 10516 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 10517 XML_TRUE) 10518 != XML_STATUS_ERROR) 10519 break; 10520 /* See comment in test_nsalloc_xmlns() */ 10521 nsalloc_teardown(); 10522 nsalloc_setup(); 10523 } 10524 if (i == 0) 10525 fail("Parsing worked despite failing allocations"); 10526 else if (i == max_alloc_count) 10527 fail("Parsing failed even at max allocation count"); 10528 } 10529 END_TEST 10530 10531 /* Using a slightly shorter namespace name provokes allocations in 10532 * slightly different places in the code. 10533 */ 10534 START_TEST(test_nsalloc_less_long_namespace) { 10535 const char *text 10536 = "<" 10537 /* 64 characters per line */ 10538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10544 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10545 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10546 ":e xmlns:" 10547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10548 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10549 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10550 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10551 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10552 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10553 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10554 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10555 "='http://example.org/'>\n" 10556 "<" 10557 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10558 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10559 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10560 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10561 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10562 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10563 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10564 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10565 ":f " 10566 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10567 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10568 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10569 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10570 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10571 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10572 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10573 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10574 ":att='foo'/>\n" 10575 "</" 10576 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10577 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10578 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10579 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10580 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10581 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10582 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10583 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10584 ":e>"; 10585 int i; 10586 const int max_alloc_count = 40; 10587 10588 for (i = 0; i < max_alloc_count; i++) { 10589 allocation_count = i; 10590 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10591 != XML_STATUS_ERROR) 10592 break; 10593 /* See comment in test_nsalloc_xmlns() */ 10594 nsalloc_teardown(); 10595 nsalloc_setup(); 10596 } 10597 if (i == 0) 10598 fail("Parsing worked despite failing allocations"); 10599 else if (i == max_alloc_count) 10600 fail("Parsing failed even at max allocation count"); 10601 } 10602 END_TEST 10603 10604 START_TEST(test_nsalloc_long_context) { 10605 const char *text 10606 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10607 " <!ATTLIST doc baz ID #REQUIRED>\n" 10608 " <!ENTITY en SYSTEM 'bar'>\n" 10609 "]>\n" 10610 "<doc xmlns='http://example.org/" 10611 /* 64 characters per line */ 10612 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10613 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10614 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10615 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10616 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10617 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10618 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10619 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10620 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10621 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10622 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10623 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10624 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10625 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10626 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10627 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 10628 "' baz='2'>\n" 10629 "&en;" 10630 "</doc>"; 10631 ExtOption options[] = { 10632 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10633 int i; 10634 const int max_alloc_count = 70; 10635 10636 for (i = 0; i < max_alloc_count; i++) { 10637 allocation_count = i; 10638 XML_SetUserData(g_parser, options); 10639 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10640 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10641 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10642 != XML_STATUS_ERROR) 10643 break; 10644 10645 /* See comment in test_nsalloc_xmlns() */ 10646 nsalloc_teardown(); 10647 nsalloc_setup(); 10648 } 10649 if (i == 0) 10650 fail("Parsing worked despite failing allocations"); 10651 else if (i == max_alloc_count) 10652 fail("Parsing failed even at max allocation count"); 10653 } 10654 END_TEST 10655 10656 /* This function is void; it will throw a fail() on error, so if it 10657 * returns normally it must have succeeded. 10658 */ 10659 static void 10660 context_realloc_test(const char *text) { 10661 ExtOption options[] = { 10662 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10663 int i; 10664 const int max_realloc_count = 6; 10665 10666 for (i = 0; i < max_realloc_count; i++) { 10667 reallocation_count = i; 10668 XML_SetUserData(g_parser, options); 10669 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10670 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10671 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10672 != XML_STATUS_ERROR) 10673 break; 10674 /* See comment in test_nsalloc_xmlns() */ 10675 nsalloc_teardown(); 10676 nsalloc_setup(); 10677 } 10678 if (i == 0) 10679 fail("Parsing worked despite failing reallocations"); 10680 else if (i == max_realloc_count) 10681 fail("Parsing failed even at max reallocation count"); 10682 } 10683 10684 START_TEST(test_nsalloc_realloc_long_context) { 10685 const char *text 10686 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10687 " <!ENTITY en SYSTEM 'bar'>\n" 10688 "]>\n" 10689 "<doc xmlns='http://example.org/" 10690 /* 64 characters per line */ 10691 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10692 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10693 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10694 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10695 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10696 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10697 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10698 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10699 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10700 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10701 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10702 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10703 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10704 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10705 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10706 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 10707 "'>\n" 10708 "&en;" 10709 "</doc>"; 10710 10711 context_realloc_test(text); 10712 } 10713 END_TEST 10714 10715 START_TEST(test_nsalloc_realloc_long_context_2) { 10716 const char *text 10717 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10718 " <!ENTITY en SYSTEM 'bar'>\n" 10719 "]>\n" 10720 "<doc xmlns='http://example.org/" 10721 /* 64 characters per line */ 10722 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10723 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10724 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10725 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10726 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10727 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10728 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10729 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10730 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10731 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10732 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10733 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10734 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10735 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10736 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10737 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK" 10738 "'>\n" 10739 "&en;" 10740 "</doc>"; 10741 10742 context_realloc_test(text); 10743 } 10744 END_TEST 10745 10746 START_TEST(test_nsalloc_realloc_long_context_3) { 10747 const char *text 10748 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10749 " <!ENTITY en SYSTEM 'bar'>\n" 10750 "]>\n" 10751 "<doc xmlns='http://example.org/" 10752 /* 64 characters per line */ 10753 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10754 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10755 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10756 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10757 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10758 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10759 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10760 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10761 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10762 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10763 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10764 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10765 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10766 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10767 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10768 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH" 10769 "'>\n" 10770 "&en;" 10771 "</doc>"; 10772 10773 context_realloc_test(text); 10774 } 10775 END_TEST 10776 10777 START_TEST(test_nsalloc_realloc_long_context_4) { 10778 const char *text 10779 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10780 " <!ENTITY en SYSTEM 'bar'>\n" 10781 "]>\n" 10782 "<doc xmlns='http://example.org/" 10783 /* 64 characters per line */ 10784 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10785 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10786 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10787 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10788 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10789 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10790 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10791 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10792 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10793 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10794 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10795 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10796 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10797 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10798 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10799 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO" 10800 "'>\n" 10801 "&en;" 10802 "</doc>"; 10803 10804 context_realloc_test(text); 10805 } 10806 END_TEST 10807 10808 START_TEST(test_nsalloc_realloc_long_context_5) { 10809 const char *text 10810 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10811 " <!ENTITY en SYSTEM 'bar'>\n" 10812 "]>\n" 10813 "<doc xmlns='http://example.org/" 10814 /* 64 characters per line */ 10815 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10816 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10817 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10818 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10819 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10820 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10821 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10822 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10823 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10824 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10825 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10826 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10827 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10828 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10829 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10830 "ABC" 10831 "'>\n" 10832 "&en;" 10833 "</doc>"; 10834 10835 context_realloc_test(text); 10836 } 10837 END_TEST 10838 10839 START_TEST(test_nsalloc_realloc_long_context_6) { 10840 const char *text 10841 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10842 " <!ENTITY en SYSTEM 'bar'>\n" 10843 "]>\n" 10844 "<doc xmlns='http://example.org/" 10845 /* 64 characters per line */ 10846 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10847 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10848 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10849 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10850 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10851 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10852 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10853 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10854 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10855 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10856 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10857 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10858 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10859 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10860 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 10861 "'>\n" 10862 "&en;" 10863 "</doc>"; 10864 10865 context_realloc_test(text); 10866 } 10867 END_TEST 10868 10869 START_TEST(test_nsalloc_realloc_long_context_7) { 10870 const char *text 10871 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10872 " <!ENTITY en SYSTEM 'bar'>\n" 10873 "]>\n" 10874 "<doc xmlns='http://example.org/" 10875 /* 64 characters per line */ 10876 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10877 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10878 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10879 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10880 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10881 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10882 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10883 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10884 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10885 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10886 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10887 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10888 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10889 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10890 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10891 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM" 10892 "'>\n" 10893 "&en;" 10894 "</doc>"; 10895 10896 context_realloc_test(text); 10897 } 10898 END_TEST 10899 10900 START_TEST(test_nsalloc_realloc_long_ge_name) { 10901 const char *text 10902 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10903 " <!ENTITY " 10904 /* 64 characters per line */ 10905 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10906 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10907 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10908 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10909 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10910 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10911 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10912 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10913 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10914 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10915 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10916 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10917 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10918 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10919 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10920 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10921 " SYSTEM 'bar'>\n" 10922 "]>\n" 10923 "<doc xmlns='http://example.org/baz'>\n" 10924 "&" 10925 /* 64 characters per line */ 10926 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10927 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10928 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10929 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10930 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10931 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10932 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10933 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10934 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10935 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10936 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10937 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10938 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10939 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10940 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10941 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10942 ";" 10943 "</doc>"; 10944 ExtOption options[] = { 10945 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}}; 10946 int i; 10947 const int max_realloc_count = 10; 10948 10949 for (i = 0; i < max_realloc_count; i++) { 10950 reallocation_count = i; 10951 XML_SetUserData(g_parser, options); 10952 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10953 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10954 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10955 != XML_STATUS_ERROR) 10956 break; 10957 /* See comment in test_nsalloc_xmlns() */ 10958 nsalloc_teardown(); 10959 nsalloc_setup(); 10960 } 10961 if (i == 0) 10962 fail("Parsing worked despite failing reallocations"); 10963 else if (i == max_realloc_count) 10964 fail("Parsing failed even at max reallocation count"); 10965 } 10966 END_TEST 10967 10968 /* Test that when a namespace is passed through the context mechanism 10969 * to an external entity parser, the parsers handle reallocation 10970 * failures correctly. The prefix is exactly the right length to 10971 * provoke particular uncommon code paths. 10972 */ 10973 START_TEST(test_nsalloc_realloc_long_context_in_dtd) { 10974 const char *text1 10975 = "<!DOCTYPE " 10976 /* 64 characters per line */ 10977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10982 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10983 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10984 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10985 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10986 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10987 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10988 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10989 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10990 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10991 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10992 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10993 ":doc [\n" 10994 " <!ENTITY First SYSTEM 'foo/First'>\n" 10995 "]>\n" 10996 "<" 10997 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10998 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 10999 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11000 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11001 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11002 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11003 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11004 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11005 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11006 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11007 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11008 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11009 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11010 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11011 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11012 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11013 ":doc xmlns:" 11014 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11015 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11016 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11017 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11018 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11019 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11020 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11021 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11022 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11023 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11024 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11025 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11026 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11027 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11028 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11029 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11030 "='foo/Second'>&First;"; 11031 const char *text2 11032 = "</" 11033 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11034 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11035 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11036 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11037 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11038 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11039 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11040 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11041 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11042 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11043 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11044 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11045 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11046 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11047 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11048 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11049 ":doc>"; 11050 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}}; 11051 int i; 11052 const int max_realloc_count = 20; 11053 11054 for (i = 0; i < max_realloc_count; i++) { 11055 reallocation_count = i; 11056 XML_SetUserData(g_parser, options); 11057 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11058 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11059 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 11060 != XML_STATUS_ERROR 11061 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 11062 XML_TRUE) 11063 != XML_STATUS_ERROR) 11064 break; 11065 /* See comment in test_nsalloc_xmlns() */ 11066 nsalloc_teardown(); 11067 nsalloc_setup(); 11068 } 11069 if (i == 0) 11070 fail("Parsing worked despite failing reallocations"); 11071 else if (i == max_realloc_count) 11072 fail("Parsing failed even at max reallocation count"); 11073 } 11074 END_TEST 11075 11076 START_TEST(test_nsalloc_long_default_in_ext) { 11077 const char *text 11078 = "<!DOCTYPE doc [\n" 11079 " <!ATTLIST e a1 CDATA '" 11080 /* 64 characters per line */ 11081 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11082 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11083 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11084 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11085 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11086 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11087 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11088 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11089 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11090 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11091 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11092 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11093 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11094 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11095 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11096 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11097 "'>\n" 11098 " <!ENTITY x SYSTEM 'foo'>\n" 11099 "]>\n" 11100 "<doc>&x;</doc>"; 11101 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}}; 11102 int i; 11103 const int max_alloc_count = 50; 11104 11105 for (i = 0; i < max_alloc_count; i++) { 11106 allocation_count = i; 11107 XML_SetUserData(g_parser, options); 11108 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11109 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11110 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11111 != XML_STATUS_ERROR) 11112 break; 11113 11114 /* See comment in test_nsalloc_xmlns() */ 11115 nsalloc_teardown(); 11116 nsalloc_setup(); 11117 } 11118 if (i == 0) 11119 fail("Parsing worked despite failing allocations"); 11120 else if (i == max_alloc_count) 11121 fail("Parsing failed even at max allocation count"); 11122 } 11123 END_TEST 11124 11125 START_TEST(test_nsalloc_long_systemid_in_ext) { 11126 const char *text 11127 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11128 " <!ENTITY en SYSTEM '" 11129 /* 64 characters per line */ 11130 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11131 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11132 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11133 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11134 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11135 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11136 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11137 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11138 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11139 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11140 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11141 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11142 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11143 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11144 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11145 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11146 "'>\n" 11147 "]>\n" 11148 "<doc>&en;</doc>"; 11149 ExtOption options[] = { 11150 {XCS("foo"), "<!ELEMENT e EMPTY>"}, 11151 {/* clang-format off */ 11152 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11153 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11154 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11155 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11156 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11157 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11158 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11159 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11160 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11161 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11162 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11163 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11164 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11165 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11166 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11167 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"), 11168 /* clang-format on */ 11169 "<e/>"}, 11170 {NULL, NULL}}; 11171 int i; 11172 const int max_alloc_count = 55; 11173 11174 for (i = 0; i < max_alloc_count; i++) { 11175 allocation_count = i; 11176 XML_SetUserData(g_parser, options); 11177 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11178 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11179 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11180 != XML_STATUS_ERROR) 11181 break; 11182 11183 /* See comment in test_nsalloc_xmlns() */ 11184 nsalloc_teardown(); 11185 nsalloc_setup(); 11186 } 11187 if (i == 0) 11188 fail("Parsing worked despite failing allocations"); 11189 else if (i == max_alloc_count) 11190 fail("Parsing failed even at max allocation count"); 11191 } 11192 END_TEST 11193 11194 /* Test the effects of allocation failure on parsing an element in a 11195 * namespace. Based on test_nsalloc_long_context. 11196 */ 11197 START_TEST(test_nsalloc_prefixed_element) { 11198 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n" 11199 " <!ATTLIST pfx:element baz ID #REQUIRED>\n" 11200 " <!ENTITY en SYSTEM 'bar'>\n" 11201 "]>\n" 11202 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n" 11203 "&en;" 11204 "</pfx:element>"; 11205 ExtOption options[] = { 11206 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 11207 int i; 11208 const int max_alloc_count = 70; 11209 11210 for (i = 0; i < max_alloc_count; i++) { 11211 allocation_count = i; 11212 XML_SetUserData(g_parser, options); 11213 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11214 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11215 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11216 != XML_STATUS_ERROR) 11217 break; 11218 11219 /* See comment in test_nsalloc_xmlns() */ 11220 nsalloc_teardown(); 11221 nsalloc_setup(); 11222 } 11223 if (i == 0) 11224 fail("Success despite failing allocator"); 11225 else if (i == max_alloc_count) 11226 fail("Failed even at full allocation count"); 11227 } 11228 END_TEST 11229 11230 #if defined(XML_DTD) 11231 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int); 11232 11233 struct AccountingTestCase { 11234 const char *primaryText; 11235 const char *firstExternalText; /* often NULL */ 11236 const char *secondExternalText; /* often NULL */ 11237 const unsigned long long expectedCountBytesIndirectExtra; 11238 XML_Bool singleBytesWanted; 11239 }; 11240 11241 static int 11242 accounting_external_entity_ref_handler(XML_Parser parser, 11243 const XML_Char *context, 11244 const XML_Char *base, 11245 const XML_Char *systemId, 11246 const XML_Char *publicId) { 11247 UNUSED_P(context); 11248 UNUSED_P(base); 11249 UNUSED_P(publicId); 11250 11251 const struct AccountingTestCase *const testCase 11252 = (const struct AccountingTestCase *)XML_GetUserData(parser); 11253 11254 const char *externalText = NULL; 11255 if (xcstrcmp(systemId, XCS("first.ent")) == 0) { 11256 externalText = testCase->firstExternalText; 11257 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) { 11258 externalText = testCase->secondExternalText; 11259 } else { 11260 assert(! "systemId is neither \"first.ent\" nor \"second.ent\""); 11261 } 11262 assert(externalText); 11263 11264 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 11265 assert(entParser); 11266 11267 const XmlParseFunction xmlParseFunction 11268 = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11269 11270 const enum XML_Status status = xmlParseFunction( 11271 entParser, externalText, (int)strlen(externalText), XML_TRUE); 11272 11273 XML_ParserFree(entParser); 11274 return status; 11275 } 11276 11277 START_TEST(test_accounting_precision) { 11278 const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */ 11279 struct AccountingTestCase cases[] = { 11280 {"<e/>", NULL, NULL, 0, 0}, 11281 {"<e></e>", NULL, NULL, 0, 0}, 11282 11283 /* Attributes */ 11284 {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later}, 11285 {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0}, 11286 {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0, 11287 filled_later}, 11288 {"<e k=\"&'><"\" />", NULL, NULL, 11289 sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later}, 11290 {"<e1 xmlns='https://example.org/'>\n" 11291 " <e2 xmlns=''/>\n" 11292 "</e1>", 11293 NULL, NULL, 0, filled_later}, 11294 11295 /* Text */ 11296 {"<e>text</e>", NULL, NULL, 0, filled_later}, 11297 {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later}, 11298 {"<e>&'><"</e>", NULL, NULL, 11299 sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later}, 11300 {"<e>A)</e>", NULL, NULL, 0, filled_later}, 11301 11302 /* Prolog */ 11303 {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later}, 11304 11305 /* Whitespace */ 11306 {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later}, 11307 {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later}, 11308 {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later}, 11309 11310 /* Comments */ 11311 {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later}, 11312 11313 /* Processing instructions */ 11314 {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>", 11315 NULL, NULL, 0, filled_later}, 11316 {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>", 11317 "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>", 11318 0, filled_later}, 11319 11320 /* CDATA */ 11321 {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later}, 11322 /* The following is the essence of this OSS-Fuzz finding: 11323 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302 11324 https://oss-fuzz.com/testcase-detail/4860575394955264 11325 */ 11326 {"<!DOCTYPE r [\n" 11327 "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n" 11328 "]>\n" 11329 "<r>&e;</r>\n", 11330 NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"), 11331 filled_later}, 11332 11333 /* Conditional sections */ 11334 {"<!DOCTYPE r [\n" 11335 "<!ENTITY % draft 'INCLUDE'>\n" 11336 "<!ENTITY % final 'IGNORE'>\n" 11337 "<!ENTITY % import SYSTEM \"first.ent\">\n" 11338 "%import;\n" 11339 "]>\n" 11340 "<r/>\n", 11341 "<![%draft;[<!--1-->]]>\n" 11342 "<![%final;[<!--22-->]]>", 11343 NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")), 11344 filled_later}, 11345 11346 /* General entities */ 11347 {"<!DOCTYPE root [\n" 11348 "<!ENTITY nine \"123456789\">\n" 11349 "]>\n" 11350 "<root>&nine;</root>", 11351 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11352 {"<!DOCTYPE root [\n" 11353 "<!ENTITY nine \"123456789\">\n" 11354 "]>\n" 11355 "<root k1=\"&nine;\"/>", 11356 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11357 {"<!DOCTYPE root [\n" 11358 "<!ENTITY nine \"123456789\">\n" 11359 "<!ENTITY nine2 \"&nine;&nine;\">\n" 11360 "]>\n" 11361 "<root>&nine2;&nine2;&nine2;</root>", 11362 NULL, NULL, 11363 sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */ 11364 * (strlen("&nine;") + strlen("123456789")), 11365 filled_later}, 11366 {"<!DOCTYPE r [\n" 11367 " <!ENTITY five SYSTEM 'first.ent'>\n" 11368 "]>\n" 11369 "<r>&five;</r>", 11370 "12345", NULL, 0, filled_later}, 11371 11372 /* Parameter entities */ 11373 {"<!DOCTYPE r [\n" 11374 "<!ENTITY % comment \"<!---->\">\n" 11375 "%comment;\n" 11376 "]>\n" 11377 "<r/>", 11378 NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later}, 11379 {"<!DOCTYPE r [\n" 11380 "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n" 11381 "%ninedef;\n" 11382 "]>\n" 11383 "<r>&nine;</r>", 11384 NULL, NULL, 11385 sizeof(XML_Char) 11386 * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")), 11387 filled_later}, 11388 {"<!DOCTYPE r [\n" 11389 "<!ENTITY % comment \"<!--1-->\">\n" 11390 "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n" 11391 "%comment2;\n" 11392 "]>\n" 11393 "<r/>\n", 11394 NULL, NULL, 11395 sizeof(XML_Char) 11396 * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")), 11397 filled_later}, 11398 {"<!DOCTYPE r [\n" 11399 " <!ENTITY % five \"12345\">\n" 11400 " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n" 11401 " %five2def;\n" 11402 "]>\n" 11403 "<r>&five2;</r>", 11404 NULL, NULL, /* from "%five2def;": */ 11405 sizeof(XML_Char) 11406 * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">") 11407 + 2 /* calls to "%five;" */ * strlen("12345") 11408 + /* from "&five2;": */ strlen("[12345][12345]]]]")), 11409 filled_later}, 11410 {"<!DOCTYPE r SYSTEM \"first.ent\">\n" 11411 "<r/>", 11412 "<!ENTITY % comment '<!--1-->'>\n" 11413 "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n" 11414 "%comment2;", 11415 NULL, 11416 sizeof(XML_Char) 11417 * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->") 11418 + 2 /* calls to "%comment;" */ * strlen("<!---->")), 11419 filled_later}, 11420 {"<!DOCTYPE r SYSTEM 'first.ent'>\n" 11421 "<r/>", 11422 "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n" 11423 "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n" 11424 "%e2;\n", 11425 "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"), 11426 filled_later}, 11427 { 11428 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11429 "<r/>", 11430 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11431 "<!ENTITY % e2 '%e1;'>", 11432 "<?xml version='1.0' encoding='utf-8'?>\n" 11433 "hello\n" 11434 "xml" /* without trailing newline! */, 11435 0, 11436 filled_later, 11437 }, 11438 { 11439 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11440 "<r/>", 11441 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11442 "<!ENTITY % e2 '%e1;'>", 11443 "<?xml version='1.0' encoding='utf-8'?>\n" 11444 "hello\n" 11445 "xml\n" /* with trailing newline! */, 11446 0, 11447 filled_later, 11448 }, 11449 {"<!DOCTYPE doc SYSTEM 'first.ent'>\n" 11450 "<doc></doc>\n", 11451 "<!ELEMENT doc EMPTY>\n" 11452 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11453 "<!ENTITY % e2 '%e1;'>\n" 11454 "%e1;\n", 11455 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */, 11456 strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later}, 11457 {"<!DOCTYPE r [\n" 11458 " <!ENTITY five SYSTEM 'first.ent'>\n" 11459 "]>\n" 11460 "<r>&five;</r>", 11461 "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later}, 11462 }; 11463 11464 const size_t countCases = sizeof(cases) / sizeof(cases[0]); 11465 size_t u = 0; 11466 for (; u < countCases; u++) { 11467 size_t v = 0; 11468 for (; v < 2; v++) { 11469 const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE; 11470 const unsigned long long expectedCountBytesDirect 11471 = strlen(cases[u].primaryText); 11472 const unsigned long long expectedCountBytesIndirect 11473 = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText) 11474 : 0) 11475 + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText) 11476 : 0) 11477 + cases[u].expectedCountBytesIndirectExtra; 11478 11479 XML_Parser parser = XML_ParserCreate(NULL); 11480 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11481 if (cases[u].firstExternalText) { 11482 XML_SetExternalEntityRefHandler(parser, 11483 accounting_external_entity_ref_handler); 11484 XML_SetUserData(parser, (void *)&cases[u]); 11485 cases[u].singleBytesWanted = singleBytesWanted; 11486 } 11487 11488 const XmlParseFunction xmlParseFunction 11489 = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11490 11491 enum XML_Status status 11492 = xmlParseFunction(parser, cases[u].primaryText, 11493 (int)strlen(cases[u].primaryText), XML_TRUE); 11494 if (status != XML_STATUS_OK) { 11495 _xml_failure(parser, __FILE__, __LINE__); 11496 } 11497 11498 const unsigned long long actualCountBytesDirect 11499 = testingAccountingGetCountBytesDirect(parser); 11500 const unsigned long long actualCountBytesIndirect 11501 = testingAccountingGetCountBytesIndirect(parser); 11502 11503 XML_ParserFree(parser); 11504 11505 if (actualCountBytesDirect != expectedCountBytesDirect) { 11506 fprintf( 11507 stderr, 11508 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11509 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11510 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11511 expectedCountBytesDirect, actualCountBytesDirect); 11512 fail("Count of direct bytes is off"); 11513 } 11514 11515 if (actualCountBytesIndirect != expectedCountBytesIndirect) { 11516 fprintf( 11517 stderr, 11518 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11519 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11520 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11521 expectedCountBytesIndirect, actualCountBytesIndirect); 11522 fail("Count of indirect bytes is off"); 11523 } 11524 } 11525 } 11526 } 11527 END_TEST 11528 11529 START_TEST(test_billion_laughs_attack_protection_api) { 11530 XML_Parser parserWithoutParent = XML_ParserCreate(NULL); 11531 XML_Parser parserWithParent 11532 = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL); 11533 if (parserWithoutParent == NULL) 11534 fail("parserWithoutParent is NULL"); 11535 if (parserWithParent == NULL) 11536 fail("parserWithParent is NULL"); 11537 11538 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases 11539 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f) 11540 == XML_TRUE) 11541 fail("Call with NULL parser is NOT supposed to succeed"); 11542 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent, 11543 123.0f) 11544 == XML_TRUE) 11545 fail("Call with non-root parser is NOT supposed to succeed"); 11546 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11547 parserWithoutParent, NAN) 11548 == XML_TRUE) 11549 fail("Call with NaN limit is NOT supposed to succeed"); 11550 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11551 parserWithoutParent, -1.0f) 11552 == XML_TRUE) 11553 fail("Call with negative limit is NOT supposed to succeed"); 11554 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11555 parserWithoutParent, 0.9f) 11556 == XML_TRUE) 11557 fail("Call with positive limit <1.0 is NOT supposed to succeed"); 11558 11559 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases 11560 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11561 parserWithoutParent, 1.0f) 11562 == XML_FALSE) 11563 fail("Call with positive limit >=1.0 is supposed to succeed"); 11564 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11565 parserWithoutParent, 123456.789f) 11566 == XML_FALSE) 11567 fail("Call with positive limit >=1.0 is supposed to succeed"); 11568 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11569 parserWithoutParent, INFINITY) 11570 == XML_FALSE) 11571 fail("Call with positive limit >=1.0 is supposed to succeed"); 11572 11573 // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases 11574 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123) 11575 == XML_TRUE) 11576 fail("Call with NULL parser is NOT supposed to succeed"); 11577 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent, 11578 123) 11579 == XML_TRUE) 11580 fail("Call with non-root parser is NOT supposed to succeed"); 11581 11582 // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases 11583 if (XML_SetBillionLaughsAttackProtectionActivationThreshold( 11584 parserWithoutParent, 123) 11585 == XML_FALSE) 11586 fail("Call with non-NULL parentless parser is supposed to succeed"); 11587 11588 XML_ParserFree(parserWithParent); 11589 XML_ParserFree(parserWithoutParent); 11590 } 11591 END_TEST 11592 11593 START_TEST(test_helper_unsigned_char_to_printable) { 11594 // Smoke test 11595 unsigned char uc = 0; 11596 for (; uc < (unsigned char)-1; uc++) { 11597 const char *const printable = unsignedCharToPrintable(uc); 11598 if (printable == NULL) 11599 fail("unsignedCharToPrintable returned NULL"); 11600 if (strlen(printable) < (size_t)1) 11601 fail("unsignedCharToPrintable returned empty string"); 11602 } 11603 11604 // Two concrete samples 11605 if (strcmp(unsignedCharToPrintable('A'), "A") != 0) 11606 fail("unsignedCharToPrintable result mistaken"); 11607 if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0) 11608 fail("unsignedCharToPrintable result mistaken"); 11609 } 11610 END_TEST 11611 #endif // defined(XML_DTD) 11612 11613 static Suite * 11614 make_suite(void) { 11615 Suite *s = suite_create("basic"); 11616 TCase *tc_basic = tcase_create("basic tests"); 11617 TCase *tc_namespace = tcase_create("XML namespaces"); 11618 TCase *tc_misc = tcase_create("miscellaneous tests"); 11619 TCase *tc_alloc = tcase_create("allocation tests"); 11620 TCase *tc_nsalloc = tcase_create("namespace allocation tests"); 11621 #if defined(XML_DTD) 11622 TCase *tc_accounting = tcase_create("accounting tests"); 11623 #endif 11624 11625 suite_add_tcase(s, tc_basic); 11626 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown); 11627 tcase_add_test(tc_basic, test_nul_byte); 11628 tcase_add_test(tc_basic, test_u0000_char); 11629 tcase_add_test(tc_basic, test_siphash_self); 11630 tcase_add_test(tc_basic, test_siphash_spec); 11631 tcase_add_test(tc_basic, test_bom_utf8); 11632 tcase_add_test(tc_basic, test_bom_utf16_be); 11633 tcase_add_test(tc_basic, test_bom_utf16_le); 11634 tcase_add_test(tc_basic, test_nobom_utf16_le); 11635 tcase_add_test(tc_basic, test_illegal_utf8); 11636 tcase_add_test(tc_basic, test_utf8_auto_align); 11637 tcase_add_test(tc_basic, test_utf16); 11638 tcase_add_test(tc_basic, test_utf16_le_epilog_newline); 11639 tcase_add_test(tc_basic, test_not_utf16); 11640 tcase_add_test(tc_basic, test_bad_encoding); 11641 tcase_add_test(tc_basic, test_latin1_umlauts); 11642 tcase_add_test(tc_basic, test_long_utf8_character); 11643 tcase_add_test(tc_basic, test_long_latin1_attribute); 11644 tcase_add_test(tc_basic, test_long_ascii_attribute); 11645 /* Regression test for SF bug #491986. */ 11646 tcase_add_test(tc_basic, test_danish_latin1); 11647 /* Regression test for SF bug #514281. */ 11648 tcase_add_test(tc_basic, test_french_charref_hexidecimal); 11649 tcase_add_test(tc_basic, test_french_charref_decimal); 11650 tcase_add_test(tc_basic, test_french_latin1); 11651 tcase_add_test(tc_basic, test_french_utf8); 11652 tcase_add_test(tc_basic, test_utf8_false_rejection); 11653 tcase_add_test(tc_basic, test_line_number_after_parse); 11654 tcase_add_test(tc_basic, test_column_number_after_parse); 11655 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers); 11656 tcase_add_test(tc_basic, test_line_number_after_error); 11657 tcase_add_test(tc_basic, test_column_number_after_error); 11658 tcase_add_test(tc_basic, test_really_long_lines); 11659 tcase_add_test(tc_basic, test_really_long_encoded_lines); 11660 tcase_add_test(tc_basic, test_end_element_events); 11661 tcase_add_test(tc_basic, test_attr_whitespace_normalization); 11662 tcase_add_test(tc_basic, test_xmldecl_misplaced); 11663 tcase_add_test(tc_basic, test_xmldecl_invalid); 11664 tcase_add_test(tc_basic, test_xmldecl_missing_attr); 11665 tcase_add_test(tc_basic, test_xmldecl_missing_value); 11666 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity); 11667 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity); 11668 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset); 11669 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset); 11670 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone); 11671 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset); 11672 tcase_add_test(tc_basic, test_not_standalone_handler_reject); 11673 tcase_add_test(tc_basic, test_not_standalone_handler_accept); 11674 tcase_add_test(tc_basic, 11675 test_wfc_undeclared_entity_with_external_subset_standalone); 11676 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone); 11677 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs); 11678 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding); 11679 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler); 11680 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom); 11681 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding); 11682 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2); 11683 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse); 11684 tcase_add_test__ifdef_xml_dtd(tc_basic, 11685 test_ext_entity_invalid_suspended_parse); 11686 tcase_add_test(tc_basic, test_dtd_default_handling); 11687 tcase_add_test(tc_basic, test_dtd_attr_handling); 11688 tcase_add_test(tc_basic, test_empty_ns_without_namespaces); 11689 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces); 11690 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls); 11691 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls); 11692 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls); 11693 tcase_add_test(tc_basic, test_good_cdata_ascii); 11694 tcase_add_test(tc_basic, test_good_cdata_utf16); 11695 tcase_add_test(tc_basic, test_good_cdata_utf16_le); 11696 tcase_add_test(tc_basic, test_long_cdata_utf16); 11697 tcase_add_test(tc_basic, test_multichar_cdata_utf16); 11698 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair); 11699 tcase_add_test(tc_basic, test_bad_cdata); 11700 tcase_add_test(tc_basic, test_bad_cdata_utf16); 11701 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls); 11702 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls); 11703 tcase_add_test(tc_basic, test_memory_allocation); 11704 tcase_add_test(tc_basic, test_default_current); 11705 tcase_add_test(tc_basic, test_dtd_elements); 11706 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd); 11707 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone); 11708 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd); 11709 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype); 11710 tcase_add_test__ifdef_xml_dtd(tc_basic, 11711 test_foreign_dtd_without_external_subset); 11712 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd); 11713 tcase_add_test(tc_basic, test_set_base); 11714 tcase_add_test(tc_basic, test_attributes); 11715 tcase_add_test(tc_basic, test_reset_in_entity); 11716 tcase_add_test(tc_basic, test_resume_invalid_parse); 11717 tcase_add_test(tc_basic, test_resume_resuspended); 11718 tcase_add_test(tc_basic, test_cdata_default); 11719 tcase_add_test(tc_basic, test_subordinate_reset); 11720 tcase_add_test(tc_basic, test_subordinate_suspend); 11721 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend); 11722 tcase_add_test(tc_basic, test_subordinate_xdecl_abort); 11723 tcase_add_test(tc_basic, test_explicit_encoding); 11724 tcase_add_test(tc_basic, test_trailing_cr); 11725 tcase_add_test(tc_basic, test_ext_entity_trailing_cr); 11726 tcase_add_test(tc_basic, test_trailing_rsqb); 11727 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb); 11728 tcase_add_test(tc_basic, test_ext_entity_good_cdata); 11729 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters); 11730 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter); 11731 tcase_add_test(tc_basic, test_empty_parse); 11732 tcase_add_test(tc_basic, test_get_buffer_1); 11733 tcase_add_test(tc_basic, test_get_buffer_2); 11734 tcase_add_test(tc_basic, test_byte_info_at_end); 11735 tcase_add_test(tc_basic, test_byte_info_at_error); 11736 tcase_add_test(tc_basic, test_byte_info_at_cdata); 11737 tcase_add_test(tc_basic, test_predefined_entities); 11738 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd); 11739 tcase_add_test(tc_basic, test_not_predefined_entities); 11740 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section); 11741 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16); 11742 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be); 11743 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section); 11744 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values); 11745 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone); 11746 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort); 11747 tcase_add_test(tc_basic, test_bad_public_doctype); 11748 tcase_add_test(tc_basic, test_attribute_enum_value); 11749 tcase_add_test(tc_basic, test_predefined_entity_redefinition); 11750 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing); 11751 tcase_add_test(tc_basic, test_public_notation_no_sysid); 11752 tcase_add_test(tc_basic, test_nested_groups); 11753 tcase_add_test(tc_basic, test_group_choice); 11754 tcase_add_test(tc_basic, test_standalone_parameter_entity); 11755 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity); 11756 tcase_add_test__ifdef_xml_dtd(tc_basic, 11757 test_recursive_external_parameter_entity); 11758 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd); 11759 tcase_add_test(tc_basic, test_suspend_xdecl); 11760 tcase_add_test(tc_basic, test_abort_epilog); 11761 tcase_add_test(tc_basic, test_abort_epilog_2); 11762 tcase_add_test(tc_basic, test_suspend_epilog); 11763 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag); 11764 tcase_add_test(tc_basic, test_unfinished_epilog); 11765 tcase_add_test(tc_basic, test_partial_char_in_epilog); 11766 tcase_add_test(tc_basic, test_hash_collision); 11767 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity); 11768 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error); 11769 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity); 11770 tcase_add_test(tc_basic, test_restart_on_error); 11771 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value); 11772 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value); 11773 tcase_add_test(tc_basic, test_trailing_cr_in_att_value); 11774 tcase_add_test(tc_basic, test_standalone_internal_entity); 11775 tcase_add_test(tc_basic, test_skipped_external_entity); 11776 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity); 11777 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity); 11778 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr); 11779 tcase_add_test(tc_basic, test_invalid_character_entity); 11780 tcase_add_test(tc_basic, test_invalid_character_entity_2); 11781 tcase_add_test(tc_basic, test_invalid_character_entity_3); 11782 tcase_add_test(tc_basic, test_invalid_character_entity_4); 11783 tcase_add_test(tc_basic, test_pi_handled_in_default); 11784 tcase_add_test(tc_basic, test_comment_handled_in_default); 11785 tcase_add_test(tc_basic, test_pi_yml); 11786 tcase_add_test(tc_basic, test_pi_xnl); 11787 tcase_add_test(tc_basic, test_pi_xmm); 11788 tcase_add_test(tc_basic, test_utf16_pi); 11789 tcase_add_test(tc_basic, test_utf16_be_pi); 11790 tcase_add_test(tc_basic, test_utf16_be_comment); 11791 tcase_add_test(tc_basic, test_utf16_le_comment); 11792 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn); 11793 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn); 11794 tcase_add_test(tc_basic, test_unknown_encoding_success); 11795 tcase_add_test(tc_basic, test_unknown_encoding_bad_name); 11796 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2); 11797 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1); 11798 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2); 11799 tcase_add_test(tc_basic, test_invalid_unknown_encoding); 11800 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok); 11801 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail); 11802 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length); 11803 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit); 11804 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate); 11805 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high); 11806 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value); 11807 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom); 11808 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom); 11809 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2); 11810 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2); 11811 tcase_add_test(tc_basic, test_ext_entity_utf16_be); 11812 tcase_add_test(tc_basic, test_ext_entity_utf16_le); 11813 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown); 11814 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom); 11815 tcase_add_test(tc_basic, test_utf8_in_cdata_section); 11816 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2); 11817 tcase_add_test(tc_basic, test_trailing_spaces_in_elements); 11818 tcase_add_test(tc_basic, test_utf16_attribute); 11819 tcase_add_test(tc_basic, test_utf16_second_attr); 11820 tcase_add_test(tc_basic, test_attr_after_solidus); 11821 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe); 11822 tcase_add_test(tc_basic, test_bad_attr_desc_keyword); 11823 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16); 11824 tcase_add_test(tc_basic, test_bad_doctype); 11825 tcase_add_test(tc_basic, test_bad_doctype_utf16); 11826 tcase_add_test(tc_basic, test_bad_doctype_plus); 11827 tcase_add_test(tc_basic, test_bad_doctype_star); 11828 tcase_add_test(tc_basic, test_bad_doctype_query); 11829 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore); 11830 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr); 11831 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr); 11832 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be); 11833 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le); 11834 tcase_add_test(tc_basic, test_short_doctype); 11835 tcase_add_test(tc_basic, test_short_doctype_2); 11836 tcase_add_test(tc_basic, test_short_doctype_3); 11837 tcase_add_test(tc_basic, test_long_doctype); 11838 tcase_add_test(tc_basic, test_bad_entity); 11839 tcase_add_test(tc_basic, test_bad_entity_2); 11840 tcase_add_test(tc_basic, test_bad_entity_3); 11841 tcase_add_test(tc_basic, test_bad_entity_4); 11842 tcase_add_test(tc_basic, test_bad_notation); 11843 tcase_add_test(tc_basic, test_default_doctype_handler); 11844 tcase_add_test(tc_basic, test_empty_element_abort); 11845 11846 suite_add_tcase(s, tc_namespace); 11847 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown); 11848 tcase_add_test(tc_namespace, test_return_ns_triplet); 11849 tcase_add_test(tc_namespace, test_ns_tagname_overwrite); 11850 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet); 11851 tcase_add_test(tc_namespace, test_start_ns_clears_start_element); 11852 tcase_add_test__ifdef_xml_dtd(tc_namespace, 11853 test_default_ns_from_ext_subset_and_ext_ge); 11854 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1); 11855 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2); 11856 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3); 11857 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4); 11858 tcase_add_test(tc_namespace, test_ns_unbound_prefix); 11859 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri); 11860 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes); 11861 tcase_add_test(tc_namespace, test_ns_duplicate_hashes); 11862 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute); 11863 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element); 11864 tcase_add_test(tc_namespace, test_ns_parser_reset); 11865 tcase_add_test(tc_namespace, test_ns_long_element); 11866 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts); 11867 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer); 11868 tcase_add_test(tc_namespace, test_ns_reserved_attributes); 11869 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2); 11870 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix); 11871 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success); 11872 tcase_add_test(tc_namespace, test_ns_double_colon); 11873 tcase_add_test(tc_namespace, test_ns_double_colon_element); 11874 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname); 11875 tcase_add_test(tc_namespace, test_ns_bad_element_leafname); 11876 tcase_add_test(tc_namespace, test_ns_utf16_leafname); 11877 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname); 11878 tcase_add_test(tc_namespace, test_ns_utf16_doctype); 11879 tcase_add_test(tc_namespace, test_ns_invalid_doctype); 11880 tcase_add_test(tc_namespace, test_ns_double_colon_doctype); 11881 11882 suite_add_tcase(s, tc_misc); 11883 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); 11884 tcase_add_test(tc_misc, test_misc_alloc_create_parser); 11885 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding); 11886 tcase_add_test(tc_misc, test_misc_null_parser); 11887 tcase_add_test(tc_misc, test_misc_error_string); 11888 tcase_add_test(tc_misc, test_misc_version); 11889 tcase_add_test(tc_misc, test_misc_features); 11890 tcase_add_test(tc_misc, test_misc_attribute_leak); 11891 tcase_add_test(tc_misc, test_misc_utf16le); 11892 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1); 11893 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2); 11894 tcase_add_test__ifdef_xml_dtd( 11895 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317); 11896 11897 suite_add_tcase(s, tc_alloc); 11898 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); 11899 tcase_add_test(tc_alloc, test_alloc_parse_xdecl); 11900 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2); 11901 tcase_add_test(tc_alloc, test_alloc_parse_pi); 11902 tcase_add_test(tc_alloc, test_alloc_parse_pi_2); 11903 tcase_add_test(tc_alloc, test_alloc_parse_pi_3); 11904 tcase_add_test(tc_alloc, test_alloc_parse_comment); 11905 tcase_add_test(tc_alloc, test_alloc_parse_comment_2); 11906 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser); 11907 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser); 11908 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts); 11909 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity); 11910 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding); 11911 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity); 11912 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling); 11913 tcase_add_test(tc_alloc, test_alloc_explicit_encoding); 11914 tcase_add_test(tc_alloc, test_alloc_set_base); 11915 tcase_add_test(tc_alloc, test_alloc_realloc_buffer); 11916 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer); 11917 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes); 11918 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value); 11919 tcase_add_test__ifdef_xml_dtd(tc_alloc, 11920 test_alloc_realloc_subst_public_entity_value); 11921 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype); 11922 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name); 11923 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd); 11924 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value); 11925 tcase_add_test__ifdef_xml_dtd(tc_alloc, 11926 test_alloc_realloc_attribute_enum_value); 11927 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute); 11928 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute); 11929 tcase_add_test(tc_alloc, test_alloc_notation); 11930 tcase_add_test(tc_alloc, test_alloc_public_notation); 11931 tcase_add_test(tc_alloc, test_alloc_system_notation); 11932 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups); 11933 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups); 11934 tcase_add_test(tc_alloc, test_alloc_large_group); 11935 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice); 11936 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog); 11937 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog); 11938 tcase_add_test__ifdef_xml_dtd(tc_alloc, 11939 test_alloc_realloc_long_attribute_value); 11940 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace); 11941 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity); 11942 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref); 11943 tcase_add_test(tc_alloc, test_alloc_long_attr_value); 11944 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities); 11945 tcase_add_test__ifdef_xml_dtd(tc_alloc, 11946 test_alloc_realloc_param_entity_newline); 11947 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe); 11948 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes); 11949 tcase_add_test(tc_alloc, test_alloc_long_doc_name); 11950 tcase_add_test(tc_alloc, test_alloc_long_base); 11951 tcase_add_test(tc_alloc, test_alloc_long_public_id); 11952 tcase_add_test(tc_alloc, test_alloc_long_entity_value); 11953 tcase_add_test(tc_alloc, test_alloc_long_notation); 11954 11955 suite_add_tcase(s, tc_nsalloc); 11956 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown); 11957 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns); 11958 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer); 11959 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix); 11960 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri); 11961 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr); 11962 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix); 11963 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes); 11964 tcase_add_test(tc_nsalloc, test_nsalloc_long_element); 11965 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri); 11966 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix); 11967 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix); 11968 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace); 11969 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace); 11970 tcase_add_test(tc_nsalloc, test_nsalloc_long_context); 11971 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context); 11972 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2); 11973 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3); 11974 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4); 11975 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5); 11976 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6); 11977 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7); 11978 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name); 11979 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd); 11980 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext); 11981 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext); 11982 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element); 11983 11984 #if defined(XML_DTD) 11985 suite_add_tcase(s, tc_accounting); 11986 tcase_add_test(tc_accounting, test_accounting_precision); 11987 tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); 11988 tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); 11989 #endif 11990 11991 return s; 11992 } 11993 11994 int 11995 main(int argc, char *argv[]) { 11996 int i, nf; 11997 int verbosity = CK_NORMAL; 11998 Suite *s = make_suite(); 11999 SRunner *sr = srunner_create(s); 12000 12001 /* run the tests for internal helper functions */ 12002 testhelper_is_whitespace_normalized(); 12003 12004 for (i = 1; i < argc; ++i) { 12005 char *opt = argv[i]; 12006 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0) 12007 verbosity = CK_VERBOSE; 12008 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0) 12009 verbosity = CK_SILENT; 12010 else { 12011 fprintf(stderr, "runtests: unknown option '%s'\n", opt); 12012 return 2; 12013 } 12014 } 12015 if (verbosity != CK_SILENT) 12016 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion()); 12017 srunner_run_all(sr, verbosity); 12018 nf = srunner_ntests_failed(sr); 12019 srunner_free(sr); 12020 12021 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 12022 } 12023