1 /* Run the Expat test suite 2 __ __ _ 3 ___\ \/ /_ __ __ _| |_ 4 / _ \\ /| '_ \ / _` | __| 5 | __// \| |_) | (_| | |_ 6 \___/_/\_\ .__/ \__,_|\__| 7 |_| XML parser 8 9 Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> 10 Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> 11 Copyright (c) 2005-2007 Steven Solie <steven@solie.ca> 12 Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> 13 Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org> 14 Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk> 15 Copyright (c) 2017 Joe Orton <jorton@redhat.com> 16 Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> 17 Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it> 18 Copyright (c) 2019 David Loffredo <loffredo@steptools.com> 19 Copyright (c) 2020 Tim Gates <tim.gates@iress.com> 20 Copyright (c) 2021 Dong-hee Na <donghee.na@python.org> 21 Licensed under the MIT license: 22 23 Permission is hereby granted, free of charge, to any person obtaining 24 a copy of this software and associated documentation files (the 25 "Software"), to deal in the Software without restriction, including 26 without limitation the rights to use, copy, modify, merge, publish, 27 distribute, sublicense, and/or sell copies of the Software, and to permit 28 persons to whom the Software is furnished to do so, subject to the 29 following conditions: 30 31 The above copyright notice and this permission notice shall be included 32 in all copies or substantial portions of the Software. 33 34 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 35 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 36 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 37 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 38 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 39 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 40 USE OR OTHER DEALINGS IN THE SOFTWARE. 41 */ 42 43 #include <expat_config.h> 44 45 #if defined(NDEBUG) 46 # undef NDEBUG /* because test suite relies on assert(...) at the moment */ 47 #endif 48 49 #include <assert.h> 50 #include <stdlib.h> 51 #include <stdio.h> 52 #include <string.h> 53 #include <stddef.h> /* ptrdiff_t */ 54 #include <ctype.h> 55 #include <limits.h> 56 #include <stdint.h> /* intptr_t uint64_t */ 57 #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 static void XMLCALL 2668 element_decl_check_model(void *userData, const XML_Char *name, 2669 XML_Content *model) { 2670 UNUSED_P(userData); 2671 uint32_t errorFlags = 0; 2672 2673 /* Expected model array structure is this: 2674 * [0] (type 6, quant 0) 2675 * [1] (type 5, quant 0) 2676 * [3] (type 4, quant 0, name "bar") 2677 * [4] (type 4, quant 0, name "foo") 2678 * [5] (type 4, quant 3, name "xyz") 2679 * [2] (type 4, quant 2, name "zebra") 2680 */ 2681 errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0)); 2682 errorFlags |= ((model != NULL) ? 0 : (1u << 1)); 2683 2684 errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2)); 2685 errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3)); 2686 errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4)); 2687 errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5)); 2688 errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6)); 2689 2690 errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7)); 2691 errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8)); 2692 errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9)); 2693 errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10)); 2694 errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11)); 2695 2696 errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12)); 2697 errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13)); 2698 errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14)); 2699 errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15)); 2700 errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16)); 2701 2702 errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17)); 2703 errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18)); 2704 errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19)); 2705 errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20)); 2706 errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21)); 2707 2708 errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22)); 2709 errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23)); 2710 errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24)); 2711 errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25)); 2712 errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26)); 2713 2714 errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27)); 2715 errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28)); 2716 errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29)); 2717 errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30)); 2718 errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31)); 2719 2720 XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags); 2721 XML_FreeContentModel(g_parser, model); 2722 } 2723 2724 START_TEST(test_dtd_elements_nesting) { 2725 // Payload inspired by a test in Perl's XML::Parser 2726 const char *text = "<!DOCTYPE foo [\n" 2727 "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n" 2728 "]>\n" 2729 "<foo/>"; 2730 2731 XML_SetUserData(g_parser, (void *)(uintptr_t)-1); 2732 2733 XML_SetElementDeclHandler(g_parser, element_decl_check_model); 2734 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 2735 == XML_STATUS_ERROR) 2736 xml_failure(g_parser); 2737 2738 if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0) 2739 fail("Element declaration model regression detected"); 2740 } 2741 END_TEST 2742 2743 /* Test foreign DTD handling */ 2744 START_TEST(test_set_foreign_dtd) { 2745 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"; 2746 const char *text2 = "<doc>&entity;</doc>"; 2747 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2748 2749 /* Check hash salt is passed through too */ 2750 XML_SetHashSalt(g_parser, 0x12345678); 2751 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2752 XML_SetUserData(g_parser, &test_data); 2753 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2754 /* Add a default handler to exercise more code paths */ 2755 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2756 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2757 fail("Could not set foreign DTD"); 2758 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 2759 == XML_STATUS_ERROR) 2760 xml_failure(g_parser); 2761 2762 /* Ensure that trying to set the DTD after parsing has started 2763 * is faulted, even if it's the same setting. 2764 */ 2765 if (XML_UseForeignDTD(g_parser, XML_TRUE) 2766 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING) 2767 fail("Failed to reject late foreign DTD setting"); 2768 /* Ditto for the hash salt */ 2769 if (XML_SetHashSalt(g_parser, 0x23456789)) 2770 fail("Failed to reject late hash salt change"); 2771 2772 /* Now finish the parse */ 2773 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 2774 == XML_STATUS_ERROR) 2775 xml_failure(g_parser); 2776 } 2777 END_TEST 2778 2779 /* Test foreign DTD handling with a failing NotStandalone handler */ 2780 START_TEST(test_foreign_dtd_not_standalone) { 2781 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2782 "<doc>&entity;</doc>"; 2783 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2784 2785 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2786 XML_SetUserData(g_parser, &test_data); 2787 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2788 XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler); 2789 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2790 fail("Could not set foreign DTD"); 2791 expect_failure(text, XML_ERROR_NOT_STANDALONE, 2792 "NotStandalonehandler failed to reject"); 2793 } 2794 END_TEST 2795 2796 /* Test invalid character in a foreign DTD is faulted */ 2797 START_TEST(test_invalid_foreign_dtd) { 2798 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2799 "<doc>&entity;</doc>"; 2800 ExtFaults test_data 2801 = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN}; 2802 2803 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2804 XML_SetUserData(g_parser, &test_data); 2805 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 2806 XML_UseForeignDTD(g_parser, XML_TRUE); 2807 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 2808 "Bad DTD should not have been accepted"); 2809 } 2810 END_TEST 2811 2812 /* Test foreign DTD use with a doctype */ 2813 START_TEST(test_foreign_dtd_with_doctype) { 2814 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 2815 "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n"; 2816 const char *text2 = "<doc>&entity;</doc>"; 2817 ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL}; 2818 2819 /* Check hash salt is passed through too */ 2820 XML_SetHashSalt(g_parser, 0x12345678); 2821 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2822 XML_SetUserData(g_parser, &test_data); 2823 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 2824 /* Add a default handler to exercise more code paths */ 2825 XML_SetDefaultHandler(g_parser, dummy_default_handler); 2826 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 2827 fail("Could not set foreign DTD"); 2828 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 2829 == XML_STATUS_ERROR) 2830 xml_failure(g_parser); 2831 2832 /* Ensure that trying to set the DTD after parsing has started 2833 * is faulted, even if it's the same setting. 2834 */ 2835 if (XML_UseForeignDTD(g_parser, XML_TRUE) 2836 != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING) 2837 fail("Failed to reject late foreign DTD setting"); 2838 /* Ditto for the hash salt */ 2839 if (XML_SetHashSalt(g_parser, 0x23456789)) 2840 fail("Failed to reject late hash salt change"); 2841 2842 /* Now finish the parse */ 2843 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 2844 == XML_STATUS_ERROR) 2845 xml_failure(g_parser); 2846 } 2847 END_TEST 2848 2849 /* Test XML_UseForeignDTD with no external subset present */ 2850 static int XMLCALL 2851 external_entity_null_loader(XML_Parser parser, const XML_Char *context, 2852 const XML_Char *base, const XML_Char *systemId, 2853 const XML_Char *publicId) { 2854 UNUSED_P(parser); 2855 UNUSED_P(context); 2856 UNUSED_P(base); 2857 UNUSED_P(systemId); 2858 UNUSED_P(publicId); 2859 return XML_STATUS_OK; 2860 } 2861 2862 START_TEST(test_foreign_dtd_without_external_subset) { 2863 const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n" 2864 "<doc>&foo;</doc>"; 2865 2866 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2867 XML_SetUserData(g_parser, NULL); 2868 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 2869 XML_UseForeignDTD(g_parser, XML_TRUE); 2870 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2871 == XML_STATUS_ERROR) 2872 xml_failure(g_parser); 2873 } 2874 END_TEST 2875 2876 START_TEST(test_empty_foreign_dtd) { 2877 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 2878 "<doc>&entity;</doc>"; 2879 2880 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 2881 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 2882 XML_UseForeignDTD(g_parser, XML_TRUE); 2883 expect_failure(text, XML_ERROR_UNDEFINED_ENTITY, 2884 "Undefined entity not faulted"); 2885 } 2886 END_TEST 2887 2888 /* Test XML Base is set and unset appropriately */ 2889 START_TEST(test_set_base) { 2890 const XML_Char *old_base; 2891 const XML_Char *new_base = XCS("/local/file/name.xml"); 2892 2893 old_base = XML_GetBase(g_parser); 2894 if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK) 2895 fail("Unable to set base"); 2896 if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0) 2897 fail("Base setting not correct"); 2898 if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK) 2899 fail("Unable to NULL base"); 2900 if (XML_GetBase(g_parser) != NULL) 2901 fail("Base setting not nulled"); 2902 XML_SetBase(g_parser, old_base); 2903 } 2904 END_TEST 2905 2906 /* Test attribute counts, indexing, etc */ 2907 typedef struct attrInfo { 2908 const XML_Char *name; 2909 const XML_Char *value; 2910 } AttrInfo; 2911 2912 typedef struct elementInfo { 2913 const XML_Char *name; 2914 int attr_count; 2915 const XML_Char *id_name; 2916 AttrInfo *attributes; 2917 } ElementInfo; 2918 2919 static void XMLCALL 2920 counting_start_element_handler(void *userData, const XML_Char *name, 2921 const XML_Char **atts) { 2922 ElementInfo *info = (ElementInfo *)userData; 2923 AttrInfo *attr; 2924 int count, id, i; 2925 2926 while (info->name != NULL) { 2927 if (! xcstrcmp(name, info->name)) 2928 break; 2929 info++; 2930 } 2931 if (info->name == NULL) 2932 fail("Element not recognised"); 2933 /* The attribute count is twice what you might expect. It is a 2934 * count of items in atts, an array which contains alternating 2935 * attribute names and attribute values. For the naive user this 2936 * is possibly a little unexpected, but it is what the 2937 * documentation in expat.h tells us to expect. 2938 */ 2939 count = XML_GetSpecifiedAttributeCount(g_parser); 2940 if (info->attr_count * 2 != count) { 2941 fail("Not got expected attribute count"); 2942 return; 2943 } 2944 id = XML_GetIdAttributeIndex(g_parser); 2945 if (id == -1 && info->id_name != NULL) { 2946 fail("ID not present"); 2947 return; 2948 } 2949 if (id != -1 && xcstrcmp(atts[id], info->id_name)) { 2950 fail("ID does not have the correct name"); 2951 return; 2952 } 2953 for (i = 0; i < info->attr_count; i++) { 2954 attr = info->attributes; 2955 while (attr->name != NULL) { 2956 if (! xcstrcmp(atts[0], attr->name)) 2957 break; 2958 attr++; 2959 } 2960 if (attr->name == NULL) { 2961 fail("Attribute not recognised"); 2962 return; 2963 } 2964 if (xcstrcmp(atts[1], attr->value)) { 2965 fail("Attribute has wrong value"); 2966 return; 2967 } 2968 /* Remember, two entries in atts per attribute (see above) */ 2969 atts += 2; 2970 } 2971 } 2972 2973 START_TEST(test_attributes) { 2974 const char *text = "<!DOCTYPE doc [\n" 2975 "<!ELEMENT doc (tag)>\n" 2976 "<!ATTLIST doc id ID #REQUIRED>\n" 2977 "]>" 2978 "<doc a='1' id='one' b='2'>" 2979 "<tag c='3'/>" 2980 "</doc>"; 2981 AttrInfo doc_info[] = {{XCS("a"), XCS("1")}, 2982 {XCS("b"), XCS("2")}, 2983 {XCS("id"), XCS("one")}, 2984 {NULL, NULL}}; 2985 AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}}; 2986 ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL}, 2987 {XCS("tag"), 1, NULL, NULL}, 2988 {NULL, 0, NULL, NULL}}; 2989 info[0].attributes = doc_info; 2990 info[1].attributes = tag_info; 2991 2992 XML_SetStartElementHandler(g_parser, counting_start_element_handler); 2993 XML_SetUserData(g_parser, info); 2994 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 2995 == XML_STATUS_ERROR) 2996 xml_failure(g_parser); 2997 } 2998 END_TEST 2999 3000 /* Test reset works correctly in the middle of processing an internal 3001 * entity. Exercises some obscure code in XML_ParserReset(). 3002 */ 3003 START_TEST(test_reset_in_entity) { 3004 const char *text = "<!DOCTYPE doc [\n" 3005 "<!ENTITY wombat 'wom'>\n" 3006 "<!ENTITY entity 'hi &wom; there'>\n" 3007 "]>\n" 3008 "<doc>&entity;</doc>"; 3009 XML_ParsingStatus status; 3010 3011 resumable = XML_TRUE; 3012 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3013 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3014 == XML_STATUS_ERROR) 3015 xml_failure(g_parser); 3016 XML_GetParsingStatus(g_parser, &status); 3017 if (status.parsing != XML_SUSPENDED) 3018 fail("Parsing status not SUSPENDED"); 3019 XML_ParserReset(g_parser, NULL); 3020 XML_GetParsingStatus(g_parser, &status); 3021 if (status.parsing != XML_INITIALIZED) 3022 fail("Parsing status doesn't reset to INITIALIZED"); 3023 } 3024 END_TEST 3025 3026 /* Test that resume correctly passes through parse errors */ 3027 START_TEST(test_resume_invalid_parse) { 3028 const char *text = "<doc>Hello</doc"; /* Missing closing wedge */ 3029 3030 resumable = XML_TRUE; 3031 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3032 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 3033 == XML_STATUS_ERROR) 3034 xml_failure(g_parser); 3035 if (XML_ResumeParser(g_parser) == XML_STATUS_OK) 3036 fail("Resumed invalid parse not faulted"); 3037 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN) 3038 fail("Invalid parse not correctly faulted"); 3039 } 3040 END_TEST 3041 3042 /* Test that re-suspended parses are correctly passed through */ 3043 START_TEST(test_resume_resuspended) { 3044 const char *text = "<doc>Hello<meep/>world</doc>"; 3045 3046 resumable = XML_TRUE; 3047 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3048 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 3049 == XML_STATUS_ERROR) 3050 xml_failure(g_parser); 3051 resumable = XML_TRUE; 3052 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 3053 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED) 3054 fail("Resumption not suspended"); 3055 /* This one should succeed and finish up */ 3056 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 3057 xml_failure(g_parser); 3058 } 3059 END_TEST 3060 3061 /* Test that CDATA shows up correctly through a default handler */ 3062 START_TEST(test_cdata_default) { 3063 const char *text = "<doc><![CDATA[Hello\nworld]]></doc>"; 3064 const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>"); 3065 CharData storage; 3066 3067 CharData_Init(&storage); 3068 XML_SetUserData(g_parser, &storage); 3069 XML_SetDefaultHandler(g_parser, accumulate_characters); 3070 3071 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3072 == XML_STATUS_ERROR) 3073 xml_failure(g_parser); 3074 CharData_CheckXMLChars(&storage, expected); 3075 } 3076 END_TEST 3077 3078 /* Test resetting a subordinate parser does exactly nothing */ 3079 static int XMLCALL 3080 external_entity_resetter(XML_Parser parser, const XML_Char *context, 3081 const XML_Char *base, const XML_Char *systemId, 3082 const XML_Char *publicId) { 3083 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3084 XML_Parser ext_parser; 3085 XML_ParsingStatus status; 3086 3087 UNUSED_P(base); 3088 UNUSED_P(systemId); 3089 UNUSED_P(publicId); 3090 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3091 if (ext_parser == NULL) 3092 fail("Could not create external entity parser"); 3093 XML_GetParsingStatus(ext_parser, &status); 3094 if (status.parsing != XML_INITIALIZED) { 3095 fail("Parsing status is not INITIALIZED"); 3096 return XML_STATUS_ERROR; 3097 } 3098 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3099 == XML_STATUS_ERROR) { 3100 xml_failure(parser); 3101 return XML_STATUS_ERROR; 3102 } 3103 XML_GetParsingStatus(ext_parser, &status); 3104 if (status.parsing != XML_FINISHED) { 3105 fail("Parsing status is not FINISHED"); 3106 return XML_STATUS_ERROR; 3107 } 3108 /* Check we can't parse here */ 3109 if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE) 3110 != XML_STATUS_ERROR) 3111 fail("Parsing when finished not faulted"); 3112 if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED) 3113 fail("Parsing when finished faulted with wrong code"); 3114 XML_ParserReset(ext_parser, NULL); 3115 XML_GetParsingStatus(ext_parser, &status); 3116 if (status.parsing != XML_FINISHED) { 3117 fail("Parsing status not still FINISHED"); 3118 return XML_STATUS_ERROR; 3119 } 3120 XML_ParserFree(ext_parser); 3121 return XML_STATUS_OK; 3122 } 3123 3124 START_TEST(test_subordinate_reset) { 3125 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3126 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3127 "<doc>&entity;</doc>"; 3128 3129 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3130 XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter); 3131 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3132 == XML_STATUS_ERROR) 3133 xml_failure(g_parser); 3134 } 3135 END_TEST 3136 3137 /* Test suspending a subordinate parser */ 3138 3139 static void XMLCALL 3140 entity_suspending_decl_handler(void *userData, const XML_Char *name, 3141 XML_Content *model) { 3142 XML_Parser ext_parser = (XML_Parser)userData; 3143 3144 UNUSED_P(name); 3145 if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR) 3146 fail("Attempting to suspend a subordinate parser not faulted"); 3147 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE) 3148 fail("Suspending subordinate parser get wrong code"); 3149 XML_SetElementDeclHandler(ext_parser, NULL); 3150 XML_FreeContentModel(g_parser, model); 3151 } 3152 3153 static int XMLCALL 3154 external_entity_suspender(XML_Parser parser, const XML_Char *context, 3155 const XML_Char *base, const XML_Char *systemId, 3156 const XML_Char *publicId) { 3157 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3158 XML_Parser ext_parser; 3159 3160 UNUSED_P(base); 3161 UNUSED_P(systemId); 3162 UNUSED_P(publicId); 3163 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3164 if (ext_parser == NULL) 3165 fail("Could not create external entity parser"); 3166 XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler); 3167 XML_SetUserData(ext_parser, ext_parser); 3168 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3169 == XML_STATUS_ERROR) { 3170 xml_failure(ext_parser); 3171 return XML_STATUS_ERROR; 3172 } 3173 XML_ParserFree(ext_parser); 3174 return XML_STATUS_OK; 3175 } 3176 3177 START_TEST(test_subordinate_suspend) { 3178 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3179 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3180 "<doc>&entity;</doc>"; 3181 3182 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3183 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender); 3184 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3185 == XML_STATUS_ERROR) 3186 xml_failure(g_parser); 3187 } 3188 END_TEST 3189 3190 /* Test suspending a subordinate parser from an XML declaration */ 3191 /* Increases code coverage of the tests */ 3192 static void XMLCALL 3193 entity_suspending_xdecl_handler(void *userData, const XML_Char *version, 3194 const XML_Char *encoding, int standalone) { 3195 XML_Parser ext_parser = (XML_Parser)userData; 3196 3197 UNUSED_P(version); 3198 UNUSED_P(encoding); 3199 UNUSED_P(standalone); 3200 XML_StopParser(ext_parser, resumable); 3201 XML_SetXmlDeclHandler(ext_parser, NULL); 3202 } 3203 3204 static int XMLCALL 3205 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context, 3206 const XML_Char *base, const XML_Char *systemId, 3207 const XML_Char *publicId) { 3208 const char *text = "<?xml version='1.0' encoding='us-ascii'?>"; 3209 XML_Parser ext_parser; 3210 XML_ParsingStatus status; 3211 enum XML_Status rc; 3212 3213 UNUSED_P(base); 3214 UNUSED_P(systemId); 3215 UNUSED_P(publicId); 3216 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3217 if (ext_parser == NULL) 3218 fail("Could not create external entity parser"); 3219 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 3220 XML_SetUserData(ext_parser, ext_parser); 3221 rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 3222 XML_GetParsingStatus(ext_parser, &status); 3223 if (resumable) { 3224 if (rc == XML_STATUS_ERROR) 3225 xml_failure(ext_parser); 3226 if (status.parsing != XML_SUSPENDED) 3227 fail("Ext Parsing status not SUSPENDED"); 3228 } else { 3229 if (rc != XML_STATUS_ERROR) 3230 fail("Ext parsing not aborted"); 3231 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED) 3232 xml_failure(ext_parser); 3233 if (status.parsing != XML_FINISHED) 3234 fail("Ext Parsing status not FINISHED"); 3235 } 3236 3237 XML_ParserFree(ext_parser); 3238 return XML_STATUS_OK; 3239 } 3240 3241 START_TEST(test_subordinate_xdecl_suspend) { 3242 const char *text 3243 = "<!DOCTYPE doc [\n" 3244 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n" 3245 "]>\n" 3246 "<doc>&entity;</doc>"; 3247 3248 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3249 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl); 3250 resumable = XML_TRUE; 3251 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3252 == XML_STATUS_ERROR) 3253 xml_failure(g_parser); 3254 } 3255 END_TEST 3256 3257 START_TEST(test_subordinate_xdecl_abort) { 3258 const char *text 3259 = "<!DOCTYPE doc [\n" 3260 " <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n" 3261 "]>\n" 3262 "<doc>&entity;</doc>"; 3263 3264 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3265 XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl); 3266 resumable = XML_FALSE; 3267 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3268 == XML_STATUS_ERROR) 3269 xml_failure(g_parser); 3270 } 3271 END_TEST 3272 3273 /* Test external entity fault handling with suspension */ 3274 static int XMLCALL 3275 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context, 3276 const XML_Char *base, 3277 const XML_Char *systemId, 3278 const XML_Char *publicId) { 3279 XML_Parser ext_parser; 3280 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 3281 void *buffer; 3282 int parse_len = (int)strlen(fault->parse_text); 3283 3284 UNUSED_P(base); 3285 UNUSED_P(systemId); 3286 UNUSED_P(publicId); 3287 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3288 if (ext_parser == NULL) 3289 fail("Could not create external entity parser"); 3290 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 3291 XML_SetUserData(ext_parser, ext_parser); 3292 resumable = XML_TRUE; 3293 buffer = XML_GetBuffer(ext_parser, parse_len); 3294 if (buffer == NULL) 3295 fail("Could not allocate parse buffer"); 3296 assert(buffer != NULL); 3297 memcpy(buffer, fault->parse_text, parse_len); 3298 if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED) 3299 fail("XML declaration did not suspend"); 3300 if (XML_ResumeParser(ext_parser) != XML_STATUS_OK) 3301 xml_failure(ext_parser); 3302 if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR) 3303 fail(fault->fail_text); 3304 if (XML_GetErrorCode(ext_parser) != fault->error) 3305 xml_failure(ext_parser); 3306 3307 XML_ParserFree(ext_parser); 3308 return XML_STATUS_ERROR; 3309 } 3310 3311 START_TEST(test_ext_entity_invalid_suspended_parse) { 3312 const char *text = "<!DOCTYPE doc [\n" 3313 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3314 "]>\n" 3315 "<doc>&en;</doc>"; 3316 ExtFaults faults[] 3317 = {{"<?xml version='1.0' encoding='us-ascii'?><", 3318 "Incomplete element declaration not faulted", NULL, 3319 XML_ERROR_UNCLOSED_TOKEN}, 3320 {/* First two bytes of a three-byte char */ 3321 "<?xml version='1.0' encoding='utf-8'?>\xe2\x82", 3322 "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR}, 3323 {NULL, NULL, NULL, XML_ERROR_NONE}}; 3324 ExtFaults *fault; 3325 3326 for (fault = &faults[0]; fault->parse_text != NULL; fault++) { 3327 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3328 XML_SetExternalEntityRefHandler(g_parser, 3329 external_entity_suspending_faulter); 3330 XML_SetUserData(g_parser, fault); 3331 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 3332 "Parser did not report external entity error"); 3333 XML_ParserReset(g_parser, NULL); 3334 } 3335 } 3336 END_TEST 3337 3338 /* Test setting an explicit encoding */ 3339 START_TEST(test_explicit_encoding) { 3340 const char *text1 = "<doc>Hello "; 3341 const char *text2 = " World</doc>"; 3342 3343 /* Just check that we can set the encoding to NULL before starting */ 3344 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK) 3345 fail("Failed to initialise encoding to NULL"); 3346 /* Say we are UTF-8 */ 3347 if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK) 3348 fail("Failed to set explicit encoding"); 3349 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 3350 == XML_STATUS_ERROR) 3351 xml_failure(g_parser); 3352 /* Try to switch encodings mid-parse */ 3353 if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR) 3354 fail("Allowed encoding change"); 3355 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 3356 == XML_STATUS_ERROR) 3357 xml_failure(g_parser); 3358 /* Try now the parse is over */ 3359 if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK) 3360 fail("Failed to unset encoding"); 3361 } 3362 END_TEST 3363 3364 /* Test handling of trailing CR (rather than newline) */ 3365 static void XMLCALL 3366 cr_cdata_handler(void *userData, const XML_Char *s, int len) { 3367 int *pfound = (int *)userData; 3368 3369 /* Internal processing turns the CR into a newline for the 3370 * character data handler, but not for the default handler 3371 */ 3372 if (len == 1 && (*s == XCS('\n') || *s == XCS('\r'))) 3373 *pfound = 1; 3374 } 3375 3376 START_TEST(test_trailing_cr) { 3377 const char *text = "<doc>\r"; 3378 int found_cr; 3379 3380 /* Try with a character handler, for code coverage */ 3381 XML_SetCharacterDataHandler(g_parser, cr_cdata_handler); 3382 XML_SetUserData(g_parser, &found_cr); 3383 found_cr = 0; 3384 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3385 == XML_STATUS_OK) 3386 fail("Failed to fault unclosed doc"); 3387 if (found_cr == 0) 3388 fail("Did not catch the carriage return"); 3389 XML_ParserReset(g_parser, NULL); 3390 3391 /* Now with a default handler instead */ 3392 XML_SetDefaultHandler(g_parser, cr_cdata_handler); 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 fail("Failed to fault unclosed doc"); 3398 if (found_cr == 0) 3399 fail("Did not catch default carriage return"); 3400 } 3401 END_TEST 3402 3403 /* Test trailing CR in an external entity parse */ 3404 static int XMLCALL 3405 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context, 3406 const XML_Char *base, const XML_Char *systemId, 3407 const XML_Char *publicId) { 3408 const char *text = "\r"; 3409 XML_Parser ext_parser; 3410 3411 UNUSED_P(base); 3412 UNUSED_P(systemId); 3413 UNUSED_P(publicId); 3414 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3415 if (ext_parser == NULL) 3416 fail("Could not create external entity parser"); 3417 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler); 3418 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3419 == XML_STATUS_ERROR) 3420 xml_failure(ext_parser); 3421 XML_ParserFree(ext_parser); 3422 return XML_STATUS_OK; 3423 } 3424 3425 static int XMLCALL 3426 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context, 3427 const XML_Char *base, const XML_Char *systemId, 3428 const XML_Char *publicId) { 3429 const char *text = "<tag>\r"; 3430 XML_Parser ext_parser; 3431 3432 UNUSED_P(base); 3433 UNUSED_P(systemId); 3434 UNUSED_P(publicId); 3435 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3436 if (ext_parser == NULL) 3437 fail("Could not create external entity parser"); 3438 XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler); 3439 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3440 == XML_STATUS_OK) 3441 fail("Async entity error not caught"); 3442 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY) 3443 xml_failure(ext_parser); 3444 XML_ParserFree(ext_parser); 3445 return XML_STATUS_OK; 3446 } 3447 3448 START_TEST(test_ext_entity_trailing_cr) { 3449 const char *text = "<!DOCTYPE doc [\n" 3450 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3451 "]>\n" 3452 "<doc>&en;</doc>"; 3453 int found_cr; 3454 3455 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3456 XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher); 3457 XML_SetUserData(g_parser, &found_cr); 3458 found_cr = 0; 3459 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3460 != XML_STATUS_OK) 3461 xml_failure(g_parser); 3462 if (found_cr == 0) 3463 fail("No carriage return found"); 3464 XML_ParserReset(g_parser, NULL); 3465 3466 /* Try again with a different trailing CR */ 3467 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3468 XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher); 3469 XML_SetUserData(g_parser, &found_cr); 3470 found_cr = 0; 3471 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3472 != XML_STATUS_OK) 3473 xml_failure(g_parser); 3474 if (found_cr == 0) 3475 fail("No carriage return found"); 3476 } 3477 END_TEST 3478 3479 /* Test handling of trailing square bracket */ 3480 static void XMLCALL 3481 rsqb_handler(void *userData, const XML_Char *s, int len) { 3482 int *pfound = (int *)userData; 3483 3484 if (len == 1 && *s == XCS(']')) 3485 *pfound = 1; 3486 } 3487 3488 START_TEST(test_trailing_rsqb) { 3489 const char *text8 = "<doc>]"; 3490 const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000"; 3491 int found_rsqb; 3492 int text8_len = (int)strlen(text8); 3493 3494 XML_SetCharacterDataHandler(g_parser, rsqb_handler); 3495 XML_SetUserData(g_parser, &found_rsqb); 3496 found_rsqb = 0; 3497 if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE) 3498 == XML_STATUS_OK) 3499 fail("Failed to fault unclosed doc"); 3500 if (found_rsqb == 0) 3501 fail("Did not catch the right square bracket"); 3502 3503 /* Try again with a different encoding */ 3504 XML_ParserReset(g_parser, NULL); 3505 XML_SetCharacterDataHandler(g_parser, rsqb_handler); 3506 XML_SetUserData(g_parser, &found_rsqb); 3507 found_rsqb = 0; 3508 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1, 3509 XML_TRUE) 3510 == XML_STATUS_OK) 3511 fail("Failed to fault unclosed doc"); 3512 if (found_rsqb == 0) 3513 fail("Did not catch the right square bracket"); 3514 3515 /* And finally with a default handler */ 3516 XML_ParserReset(g_parser, NULL); 3517 XML_SetDefaultHandler(g_parser, rsqb_handler); 3518 XML_SetUserData(g_parser, &found_rsqb); 3519 found_rsqb = 0; 3520 if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1, 3521 XML_TRUE) 3522 == XML_STATUS_OK) 3523 fail("Failed to fault unclosed doc"); 3524 if (found_rsqb == 0) 3525 fail("Did not catch the right square bracket"); 3526 } 3527 END_TEST 3528 3529 /* Test trailing right square bracket in an external entity parse */ 3530 static int XMLCALL 3531 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context, 3532 const XML_Char *base, const XML_Char *systemId, 3533 const XML_Char *publicId) { 3534 const char *text = "<tag>]"; 3535 XML_Parser ext_parser; 3536 3537 UNUSED_P(base); 3538 UNUSED_P(systemId); 3539 UNUSED_P(publicId); 3540 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3541 if (ext_parser == NULL) 3542 fail("Could not create external entity parser"); 3543 XML_SetCharacterDataHandler(ext_parser, rsqb_handler); 3544 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3545 != XML_STATUS_ERROR) 3546 fail("Async entity error not caught"); 3547 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY) 3548 xml_failure(ext_parser); 3549 XML_ParserFree(ext_parser); 3550 return XML_STATUS_OK; 3551 } 3552 3553 START_TEST(test_ext_entity_trailing_rsqb) { 3554 const char *text = "<!DOCTYPE doc [\n" 3555 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3556 "]>\n" 3557 "<doc>&en;</doc>"; 3558 int found_rsqb; 3559 3560 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3561 XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher); 3562 XML_SetUserData(g_parser, &found_rsqb); 3563 found_rsqb = 0; 3564 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3565 != XML_STATUS_OK) 3566 xml_failure(g_parser); 3567 if (found_rsqb == 0) 3568 fail("No right square bracket found"); 3569 } 3570 END_TEST 3571 3572 /* Test CDATA handling in an external entity */ 3573 static int XMLCALL 3574 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context, 3575 const XML_Char *base, const XML_Char *systemId, 3576 const XML_Char *publicId) { 3577 const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>"; 3578 const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>"); 3579 CharData storage; 3580 XML_Parser ext_parser; 3581 3582 UNUSED_P(base); 3583 UNUSED_P(systemId); 3584 UNUSED_P(publicId); 3585 CharData_Init(&storage); 3586 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3587 if (ext_parser == NULL) 3588 fail("Could not create external entity parser"); 3589 XML_SetUserData(ext_parser, &storage); 3590 XML_SetCharacterDataHandler(ext_parser, accumulate_characters); 3591 3592 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3593 == XML_STATUS_ERROR) 3594 xml_failure(ext_parser); 3595 CharData_CheckXMLChars(&storage, expected); 3596 3597 XML_ParserFree(ext_parser); 3598 return XML_STATUS_OK; 3599 } 3600 3601 START_TEST(test_ext_entity_good_cdata) { 3602 const char *text = "<!DOCTYPE doc [\n" 3603 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 3604 "]>\n" 3605 "<doc>&en;</doc>"; 3606 3607 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3608 XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii); 3609 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3610 != XML_STATUS_OK) 3611 xml_failure(g_parser); 3612 } 3613 END_TEST 3614 3615 /* Test user parameter settings */ 3616 /* Variable holding the expected handler userData */ 3617 static void *handler_data = NULL; 3618 /* Count of the number of times the comment handler has been invoked */ 3619 static int comment_count = 0; 3620 /* Count of the number of skipped entities */ 3621 static int skip_count = 0; 3622 /* Count of the number of times the XML declaration handler is invoked */ 3623 static int xdecl_count = 0; 3624 3625 static void XMLCALL 3626 xml_decl_handler(void *userData, const XML_Char *version, 3627 const XML_Char *encoding, int standalone) { 3628 UNUSED_P(version); 3629 UNUSED_P(encoding); 3630 if (userData != handler_data) 3631 fail("User data (xml decl) not correctly set"); 3632 if (standalone != -1) 3633 fail("Standalone not flagged as not present in XML decl"); 3634 xdecl_count++; 3635 } 3636 3637 static void XMLCALL 3638 param_check_skip_handler(void *userData, const XML_Char *entityName, 3639 int is_parameter_entity) { 3640 UNUSED_P(entityName); 3641 UNUSED_P(is_parameter_entity); 3642 if (userData != handler_data) 3643 fail("User data (skip) not correctly set"); 3644 skip_count++; 3645 } 3646 3647 static void XMLCALL 3648 data_check_comment_handler(void *userData, const XML_Char *data) { 3649 UNUSED_P(data); 3650 /* Check that the userData passed through is what we expect */ 3651 if (userData != handler_data) 3652 fail("User data (parser) not correctly set"); 3653 /* Check that the user data in the parser is appropriate */ 3654 if (XML_GetUserData(userData) != (void *)1) 3655 fail("User data in parser not correctly set"); 3656 comment_count++; 3657 } 3658 3659 static int XMLCALL 3660 external_entity_param_checker(XML_Parser parser, const XML_Char *context, 3661 const XML_Char *base, const XML_Char *systemId, 3662 const XML_Char *publicId) { 3663 const char *text = "<!-- Subordinate parser -->\n" 3664 "<!ELEMENT doc (#PCDATA)*>"; 3665 XML_Parser ext_parser; 3666 3667 UNUSED_P(base); 3668 UNUSED_P(systemId); 3669 UNUSED_P(publicId); 3670 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 3671 if (ext_parser == NULL) 3672 fail("Could not create external entity parser"); 3673 handler_data = ext_parser; 3674 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3675 == XML_STATUS_ERROR) { 3676 xml_failure(parser); 3677 return XML_STATUS_ERROR; 3678 } 3679 handler_data = parser; 3680 XML_ParserFree(ext_parser); 3681 return XML_STATUS_OK; 3682 } 3683 3684 START_TEST(test_user_parameters) { 3685 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3686 "<!-- Primary parse -->\n" 3687 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3688 "<doc>&entity;"; 3689 const char *epilog = "<!-- Back to primary parser -->\n" 3690 "</doc>"; 3691 3692 comment_count = 0; 3693 skip_count = 0; 3694 xdecl_count = 0; 3695 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3696 XML_SetXmlDeclHandler(g_parser, xml_decl_handler); 3697 XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker); 3698 XML_SetCommentHandler(g_parser, data_check_comment_handler); 3699 XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler); 3700 XML_UseParserAsHandlerArg(g_parser); 3701 XML_SetUserData(g_parser, (void *)1); 3702 handler_data = g_parser; 3703 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3704 == XML_STATUS_ERROR) 3705 xml_failure(g_parser); 3706 if (comment_count != 2) 3707 fail("Comment handler not invoked enough times"); 3708 /* Ensure we can't change policy mid-parse */ 3709 if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER)) 3710 fail("Changed param entity parsing policy while parsing"); 3711 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 3712 == XML_STATUS_ERROR) 3713 xml_failure(g_parser); 3714 if (comment_count != 3) 3715 fail("Comment handler not invoked enough times"); 3716 if (skip_count != 1) 3717 fail("Skip handler not invoked enough times"); 3718 if (xdecl_count != 1) 3719 fail("XML declaration handler not invoked"); 3720 } 3721 END_TEST 3722 3723 /* Test that an explicit external entity handler argument replaces 3724 * the parser as the first argument. 3725 * 3726 * We do not call the first parameter to the external entity handler 3727 * 'parser' for once, since the first time the handler is called it 3728 * will actually be a text string. We need to be able to access the 3729 * global 'parser' variable to create our external entity parser from, 3730 * since there are code paths we need to ensure get executed. 3731 */ 3732 static int XMLCALL 3733 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context, 3734 const XML_Char *base, 3735 const XML_Char *systemId, 3736 const XML_Char *publicId) { 3737 const char *text = "<!ELEMENT doc (#PCDATA)*>"; 3738 XML_Parser ext_parser; 3739 3740 UNUSED_P(base); 3741 UNUSED_P(systemId); 3742 UNUSED_P(publicId); 3743 if ((void *)parameter != handler_data) 3744 fail("External entity ref handler parameter not correct"); 3745 3746 /* Here we use the global 'parser' variable */ 3747 ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL); 3748 if (ext_parser == NULL) 3749 fail("Could not create external entity parser"); 3750 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 3751 == XML_STATUS_ERROR) 3752 xml_failure(ext_parser); 3753 3754 XML_ParserFree(ext_parser); 3755 return XML_STATUS_OK; 3756 } 3757 3758 START_TEST(test_ext_entity_ref_parameter) { 3759 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 3760 "<!DOCTYPE doc SYSTEM 'foo'>\n" 3761 "<doc>&entity;</doc>"; 3762 3763 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3764 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker); 3765 /* Set a handler arg that is not NULL and not parser (which is 3766 * what NULL would cause to be passed. 3767 */ 3768 XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text); 3769 handler_data = (void *)text; 3770 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3771 == XML_STATUS_ERROR) 3772 xml_failure(g_parser); 3773 3774 /* Now try again with unset args */ 3775 XML_ParserReset(g_parser, NULL); 3776 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 3777 XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker); 3778 XML_SetExternalEntityRefHandlerArg(g_parser, NULL); 3779 handler_data = (void *)g_parser; 3780 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3781 == XML_STATUS_ERROR) 3782 xml_failure(g_parser); 3783 } 3784 END_TEST 3785 3786 /* Test the parsing of an empty string */ 3787 START_TEST(test_empty_parse) { 3788 const char *text = "<doc></doc>"; 3789 const char *partial = "<doc>"; 3790 3791 if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR) 3792 fail("Parsing empty string faulted"); 3793 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 3794 fail("Parsing final empty string not faulted"); 3795 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS) 3796 fail("Parsing final empty string faulted for wrong reason"); 3797 3798 /* Now try with valid text before the empty end */ 3799 XML_ParserReset(g_parser, NULL); 3800 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 3801 == XML_STATUS_ERROR) 3802 xml_failure(g_parser); 3803 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR) 3804 fail("Parsing final empty string faulted"); 3805 3806 /* Now try with invalid text before the empty end */ 3807 XML_ParserReset(g_parser, NULL); 3808 if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial), 3809 XML_FALSE) 3810 == XML_STATUS_ERROR) 3811 xml_failure(g_parser); 3812 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 3813 fail("Parsing final incomplete empty string not faulted"); 3814 } 3815 END_TEST 3816 3817 /* Test odd corners of the XML_GetBuffer interface */ 3818 static enum XML_Status 3819 get_feature(enum XML_FeatureEnum feature_id, long *presult) { 3820 const XML_Feature *feature = XML_GetFeatureList(); 3821 3822 if (feature == NULL) 3823 return XML_STATUS_ERROR; 3824 for (; feature->feature != XML_FEATURE_END; feature++) { 3825 if (feature->feature == feature_id) { 3826 *presult = feature->value; 3827 return XML_STATUS_OK; 3828 } 3829 } 3830 return XML_STATUS_ERROR; 3831 } 3832 3833 /* Having an element name longer than 1024 characters exercises some 3834 * of the pool allocation code in the parser that otherwise does not 3835 * get executed. The count at the end of the line is the number of 3836 * characters (bytes) in the element name by that point.x 3837 */ 3838 static const char *get_buffer_test_text 3839 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */ 3840 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */ 3841 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */ 3842 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */ 3843 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */ 3844 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */ 3845 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */ 3846 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */ 3847 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */ 3848 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */ 3849 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */ 3850 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */ 3851 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */ 3852 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */ 3853 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */ 3854 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */ 3855 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */ 3856 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */ 3857 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */ 3858 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */ 3859 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */ 3860 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */ 3861 3862 /* Test odd corners of the XML_GetBuffer interface */ 3863 START_TEST(test_get_buffer_1) { 3864 const char *text = get_buffer_test_text; 3865 void *buffer; 3866 long context_bytes; 3867 3868 /* Attempt to allocate a negative length buffer */ 3869 if (XML_GetBuffer(g_parser, -12) != NULL) 3870 fail("Negative length buffer not failed"); 3871 3872 /* Now get a small buffer and extend it past valid length */ 3873 buffer = XML_GetBuffer(g_parser, 1536); 3874 if (buffer == NULL) 3875 fail("1.5K buffer failed"); 3876 assert(buffer != NULL); 3877 memcpy(buffer, text, strlen(text)); 3878 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 3879 == XML_STATUS_ERROR) 3880 xml_failure(g_parser); 3881 if (XML_GetBuffer(g_parser, INT_MAX) != NULL) 3882 fail("INT_MAX buffer not failed"); 3883 3884 /* Now try extending it a more reasonable but still too large 3885 * amount. The allocator in XML_GetBuffer() doubles the buffer 3886 * size until it exceeds the requested amount or INT_MAX. If it 3887 * exceeds INT_MAX, it rejects the request, so we want a request 3888 * between INT_MAX and INT_MAX/2. A gap of 1K seems comfortable, 3889 * with an extra byte just to ensure that the request is off any 3890 * boundary. The request will be inflated internally by 3891 * XML_CONTEXT_BYTES (if defined), so we subtract that from our 3892 * request. 3893 */ 3894 if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK) 3895 context_bytes = 0; 3896 if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL) 3897 fail("INT_MAX- buffer not failed"); 3898 3899 /* Now try extending it a carefully crafted amount */ 3900 if (XML_GetBuffer(g_parser, 1000) == NULL) 3901 fail("1000 buffer failed"); 3902 } 3903 END_TEST 3904 3905 /* Test more corners of the XML_GetBuffer interface */ 3906 START_TEST(test_get_buffer_2) { 3907 const char *text = get_buffer_test_text; 3908 void *buffer; 3909 3910 /* Now get a decent buffer */ 3911 buffer = XML_GetBuffer(g_parser, 1536); 3912 if (buffer == NULL) 3913 fail("1.5K buffer failed"); 3914 assert(buffer != NULL); 3915 memcpy(buffer, text, strlen(text)); 3916 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 3917 == XML_STATUS_ERROR) 3918 xml_failure(g_parser); 3919 3920 /* Extend it, to catch a different code path */ 3921 if (XML_GetBuffer(g_parser, 1024) == NULL) 3922 fail("1024 buffer failed"); 3923 } 3924 END_TEST 3925 3926 /* Test for signed integer overflow CVE-2022-23852 */ 3927 #if defined(XML_CONTEXT_BYTES) 3928 START_TEST(test_get_buffer_3_overflow) { 3929 XML_Parser parser = XML_ParserCreate(NULL); 3930 assert(parser != NULL); 3931 3932 const char *const text = "\n"; 3933 const int expectedKeepValue = (int)strlen(text); 3934 3935 // After this call, variable "keep" in XML_GetBuffer will 3936 // have value expectedKeepValue 3937 if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */) 3938 == XML_STATUS_ERROR) 3939 xml_failure(parser); 3940 3941 assert(expectedKeepValue > 0); 3942 if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL) 3943 fail("enlarging buffer not failed"); 3944 3945 XML_ParserFree(parser); 3946 } 3947 END_TEST 3948 #endif // defined(XML_CONTEXT_BYTES) 3949 3950 /* Test position information macros */ 3951 START_TEST(test_byte_info_at_end) { 3952 const char *text = "<doc></doc>"; 3953 3954 if (XML_GetCurrentByteIndex(g_parser) != -1 3955 || XML_GetCurrentByteCount(g_parser) != 0) 3956 fail("Byte index/count incorrect at start of parse"); 3957 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3958 == XML_STATUS_ERROR) 3959 xml_failure(g_parser); 3960 /* At end, the count will be zero and the index the end of string */ 3961 if (XML_GetCurrentByteCount(g_parser) != 0) 3962 fail("Terminal byte count incorrect"); 3963 if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text)) 3964 fail("Terminal byte index incorrect"); 3965 } 3966 END_TEST 3967 3968 /* Test position information from errors */ 3969 #define PRE_ERROR_STR "<doc></" 3970 #define POST_ERROR_STR "wombat></doc>" 3971 START_TEST(test_byte_info_at_error) { 3972 const char *text = PRE_ERROR_STR POST_ERROR_STR; 3973 3974 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 3975 == XML_STATUS_OK) 3976 fail("Syntax error not faulted"); 3977 if (XML_GetCurrentByteCount(g_parser) != 0) 3978 fail("Error byte count incorrect"); 3979 if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR)) 3980 fail("Error byte index incorrect"); 3981 } 3982 END_TEST 3983 #undef PRE_ERROR_STR 3984 #undef POST_ERROR_STR 3985 3986 /* Test position information in handler */ 3987 typedef struct ByteTestData { 3988 int start_element_len; 3989 int cdata_len; 3990 int total_string_len; 3991 } ByteTestData; 3992 3993 static void 3994 byte_character_handler(void *userData, const XML_Char *s, int len) { 3995 #ifdef XML_CONTEXT_BYTES 3996 int offset, size; 3997 const char *buffer; 3998 ByteTestData *data = (ByteTestData *)userData; 3999 4000 UNUSED_P(s); 4001 buffer = XML_GetInputContext(g_parser, &offset, &size); 4002 if (buffer == NULL) 4003 fail("Failed to get context buffer"); 4004 if (offset != data->start_element_len) 4005 fail("Context offset in unexpected position"); 4006 if (len != data->cdata_len) 4007 fail("CDATA length reported incorrectly"); 4008 if (size != data->total_string_len) 4009 fail("Context size is not full buffer"); 4010 if (XML_GetCurrentByteIndex(g_parser) != offset) 4011 fail("Character byte index incorrect"); 4012 if (XML_GetCurrentByteCount(g_parser) != len) 4013 fail("Character byte count incorrect"); 4014 #else 4015 UNUSED_P(s); 4016 UNUSED_P(userData); 4017 UNUSED_P(len); 4018 #endif 4019 } 4020 4021 #define START_ELEMENT "<e>" 4022 #define CDATA_TEXT "Hello" 4023 #define END_ELEMENT "</e>" 4024 START_TEST(test_byte_info_at_cdata) { 4025 const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT; 4026 int offset, size; 4027 ByteTestData data; 4028 4029 /* Check initial context is empty */ 4030 if (XML_GetInputContext(g_parser, &offset, &size) != NULL) 4031 fail("Unexpected context at start of parse"); 4032 4033 data.start_element_len = (int)strlen(START_ELEMENT); 4034 data.cdata_len = (int)strlen(CDATA_TEXT); 4035 data.total_string_len = (int)strlen(text); 4036 XML_SetCharacterDataHandler(g_parser, byte_character_handler); 4037 XML_SetUserData(g_parser, &data); 4038 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK) 4039 xml_failure(g_parser); 4040 } 4041 END_TEST 4042 #undef START_ELEMENT 4043 #undef CDATA_TEXT 4044 #undef END_ELEMENT 4045 4046 /* Test predefined entities are correctly recognised */ 4047 START_TEST(test_predefined_entities) { 4048 const char *text = "<doc><>&"'</doc>"; 4049 const XML_Char *expected = XCS("<doc><>&"'</doc>"); 4050 const XML_Char *result = XCS("<>&\"'"); 4051 CharData storage; 4052 4053 XML_SetDefaultHandler(g_parser, accumulate_characters); 4054 /* run_character_check uses XML_SetCharacterDataHandler(), which 4055 * unfortunately heads off a code path that we need to exercise. 4056 */ 4057 CharData_Init(&storage); 4058 XML_SetUserData(g_parser, &storage); 4059 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4060 == XML_STATUS_ERROR) 4061 xml_failure(g_parser); 4062 /* The default handler doesn't translate the entities */ 4063 CharData_CheckXMLChars(&storage, expected); 4064 4065 /* Now try again and check the translation */ 4066 XML_ParserReset(g_parser, NULL); 4067 run_character_check(text, result); 4068 } 4069 END_TEST 4070 4071 /* Regression test that an invalid tag in an external parameter 4072 * reference in an external DTD is correctly faulted. 4073 * 4074 * Only a few specific tags are legal in DTDs ignoring comments and 4075 * processing instructions, all of which begin with an exclamation 4076 * mark. "<el/>" is not one of them, so the parser should raise an 4077 * error on encountering it. 4078 */ 4079 static int XMLCALL 4080 external_entity_param(XML_Parser parser, const XML_Char *context, 4081 const XML_Char *base, const XML_Char *systemId, 4082 const XML_Char *publicId) { 4083 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4084 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4085 "<!ENTITY % e2 '%e1;'>\n" 4086 "%e1;\n"; 4087 const char *text2 = "<!ELEMENT el EMPTY>\n" 4088 "<el/>\n"; 4089 XML_Parser ext_parser; 4090 4091 UNUSED_P(base); 4092 UNUSED_P(publicId); 4093 if (systemId == NULL) 4094 return XML_STATUS_OK; 4095 4096 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4097 if (ext_parser == NULL) 4098 fail("Could not create external entity parser"); 4099 4100 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4101 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4102 != XML_STATUS_ERROR) 4103 fail("Inner DTD with invalid tag not rejected"); 4104 if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) 4105 xml_failure(ext_parser); 4106 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4107 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4108 != XML_STATUS_ERROR) 4109 fail("Invalid tag in external param not rejected"); 4110 if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX) 4111 xml_failure(ext_parser); 4112 } else { 4113 fail("Unknown system ID"); 4114 } 4115 4116 XML_ParserFree(ext_parser); 4117 return XML_STATUS_ERROR; 4118 } 4119 4120 START_TEST(test_invalid_tag_in_dtd) { 4121 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4122 "<doc></doc>\n"; 4123 4124 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4125 XML_SetExternalEntityRefHandler(g_parser, external_entity_param); 4126 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4127 "Invalid tag IN DTD external param not rejected"); 4128 } 4129 END_TEST 4130 4131 /* Test entities not quite the predefined ones are not mis-recognised */ 4132 START_TEST(test_not_predefined_entities) { 4133 const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>", 4134 "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL}; 4135 int i = 0; 4136 4137 while (text[i] != NULL) { 4138 expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY, 4139 "Undefined entity not rejected"); 4140 XML_ParserReset(g_parser, NULL); 4141 i++; 4142 } 4143 } 4144 END_TEST 4145 4146 /* Test conditional inclusion (IGNORE) */ 4147 static int XMLCALL 4148 external_entity_load_ignore(XML_Parser parser, const XML_Char *context, 4149 const XML_Char *base, const XML_Char *systemId, 4150 const XML_Char *publicId) { 4151 const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>"; 4152 XML_Parser ext_parser; 4153 4154 UNUSED_P(base); 4155 UNUSED_P(systemId); 4156 UNUSED_P(publicId); 4157 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4158 if (ext_parser == NULL) 4159 fail("Could not create external entity parser"); 4160 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 4161 == XML_STATUS_ERROR) 4162 xml_failure(parser); 4163 4164 XML_ParserFree(ext_parser); 4165 return XML_STATUS_OK; 4166 } 4167 4168 START_TEST(test_ignore_section) { 4169 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4170 "<doc><e>&entity;</e></doc>"; 4171 const XML_Char *expected 4172 = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;"); 4173 CharData storage; 4174 4175 CharData_Init(&storage); 4176 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4177 XML_SetUserData(g_parser, &storage); 4178 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore); 4179 XML_SetDefaultHandler(g_parser, accumulate_characters); 4180 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4181 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4182 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4183 XML_SetStartElementHandler(g_parser, dummy_start_element); 4184 XML_SetEndElementHandler(g_parser, dummy_end_element); 4185 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4186 == XML_STATUS_ERROR) 4187 xml_failure(g_parser); 4188 CharData_CheckXMLChars(&storage, expected); 4189 } 4190 END_TEST 4191 4192 static int XMLCALL 4193 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context, 4194 const XML_Char *base, 4195 const XML_Char *systemId, 4196 const XML_Char *publicId) { 4197 const char text[] = 4198 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */ 4199 "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0" 4200 "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0" 4201 "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0"; 4202 XML_Parser ext_parser; 4203 4204 UNUSED_P(base); 4205 UNUSED_P(systemId); 4206 UNUSED_P(publicId); 4207 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4208 if (ext_parser == NULL) 4209 fail("Could not create external entity parser"); 4210 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4211 == XML_STATUS_ERROR) 4212 xml_failure(parser); 4213 4214 XML_ParserFree(ext_parser); 4215 return XML_STATUS_OK; 4216 } 4217 4218 START_TEST(test_ignore_section_utf16) { 4219 const char text[] = 4220 /* <!DOCTYPE d SYSTEM 's'> */ 4221 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 " 4222 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0" 4223 /* <d><e>&en;</e></d> */ 4224 "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0"; 4225 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;"); 4226 CharData storage; 4227 4228 CharData_Init(&storage); 4229 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4230 XML_SetUserData(g_parser, &storage); 4231 XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16); 4232 XML_SetDefaultHandler(g_parser, accumulate_characters); 4233 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4234 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4235 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4236 XML_SetStartElementHandler(g_parser, dummy_start_element); 4237 XML_SetEndElementHandler(g_parser, dummy_end_element); 4238 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4239 == XML_STATUS_ERROR) 4240 xml_failure(g_parser); 4241 CharData_CheckXMLChars(&storage, expected); 4242 } 4243 END_TEST 4244 4245 static int XMLCALL 4246 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context, 4247 const XML_Char *base, 4248 const XML_Char *systemId, 4249 const XML_Char *publicId) { 4250 const char text[] = 4251 /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */ 4252 "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0[" 4253 "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 " 4254 "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>"; 4255 XML_Parser ext_parser; 4256 4257 UNUSED_P(base); 4258 UNUSED_P(systemId); 4259 UNUSED_P(publicId); 4260 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4261 if (ext_parser == NULL) 4262 fail("Could not create external entity parser"); 4263 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4264 == XML_STATUS_ERROR) 4265 xml_failure(parser); 4266 4267 XML_ParserFree(ext_parser); 4268 return XML_STATUS_OK; 4269 } 4270 4271 START_TEST(test_ignore_section_utf16_be) { 4272 const char text[] = 4273 /* <!DOCTYPE d SYSTEM 's'> */ 4274 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 " 4275 "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n" 4276 /* <d><e>&en;</e></d> */ 4277 "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>"; 4278 const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;"); 4279 CharData storage; 4280 4281 CharData_Init(&storage); 4282 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4283 XML_SetUserData(g_parser, &storage); 4284 XML_SetExternalEntityRefHandler(g_parser, 4285 external_entity_load_ignore_utf16_be); 4286 XML_SetDefaultHandler(g_parser, accumulate_characters); 4287 XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler); 4288 XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler); 4289 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4290 XML_SetStartElementHandler(g_parser, dummy_start_element); 4291 XML_SetEndElementHandler(g_parser, dummy_end_element); 4292 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 4293 == XML_STATUS_ERROR) 4294 xml_failure(g_parser); 4295 CharData_CheckXMLChars(&storage, expected); 4296 } 4297 END_TEST 4298 4299 /* Test mis-formatted conditional exclusion */ 4300 START_TEST(test_bad_ignore_section) { 4301 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4302 "<doc><e>&entity;</e></doc>"; 4303 ExtFaults faults[] 4304 = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL, 4305 XML_ERROR_SYNTAX}, 4306 {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL, 4307 XML_ERROR_INVALID_TOKEN}, 4308 {/* FIrst two bytes of a three-byte char */ 4309 "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL, 4310 XML_ERROR_PARTIAL_CHAR}, 4311 {NULL, NULL, NULL, XML_ERROR_NONE}}; 4312 ExtFaults *fault; 4313 4314 for (fault = &faults[0]; fault->parse_text != NULL; fault++) { 4315 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4316 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 4317 XML_SetUserData(g_parser, fault); 4318 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4319 "Incomplete IGNORE section not failed"); 4320 XML_ParserReset(g_parser, NULL); 4321 } 4322 } 4323 END_TEST 4324 4325 /* Test recursive parsing */ 4326 static int XMLCALL 4327 external_entity_valuer(XML_Parser parser, const XML_Char *context, 4328 const XML_Char *base, const XML_Char *systemId, 4329 const XML_Char *publicId) { 4330 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4331 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4332 "<!ENTITY % e2 '%e1;'>\n" 4333 "%e1;\n"; 4334 XML_Parser ext_parser; 4335 4336 UNUSED_P(base); 4337 UNUSED_P(publicId); 4338 if (systemId == NULL) 4339 return XML_STATUS_OK; 4340 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4341 if (ext_parser == NULL) 4342 fail("Could not create external entity parser"); 4343 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4344 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4345 == XML_STATUS_ERROR) 4346 xml_failure(ext_parser); 4347 } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4348 ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser); 4349 enum XML_Status status; 4350 enum XML_Error error; 4351 4352 status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text, 4353 (int)strlen(fault->parse_text), XML_TRUE); 4354 if (fault->error == XML_ERROR_NONE) { 4355 if (status == XML_STATUS_ERROR) 4356 xml_failure(ext_parser); 4357 } else { 4358 if (status != XML_STATUS_ERROR) 4359 fail(fault->fail_text); 4360 error = XML_GetErrorCode(ext_parser); 4361 if (error != fault->error 4362 && (fault->error != XML_ERROR_XML_DECL 4363 || error != XML_ERROR_TEXT_DECL)) 4364 xml_failure(ext_parser); 4365 } 4366 } 4367 4368 XML_ParserFree(ext_parser); 4369 return XML_STATUS_OK; 4370 } 4371 4372 START_TEST(test_external_entity_values) { 4373 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4374 "<doc></doc>\n"; 4375 ExtFaults data_004_2[] = { 4376 {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE}, 4377 {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL, 4378 XML_ERROR_INVALID_TOKEN}, 4379 {"'wombat", "Unterminated string not faulted", NULL, 4380 XML_ERROR_UNCLOSED_TOKEN}, 4381 {"\xe2\x82", "Partial UTF-8 character not faulted", NULL, 4382 XML_ERROR_PARTIAL_CHAR}, 4383 {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE}, 4384 {"<?xml?>", "Malformed XML declaration not faulted", NULL, 4385 XML_ERROR_XML_DECL}, 4386 {/* UTF-8 BOM */ 4387 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, 4388 XML_ERROR_NONE}, 4389 {"<?xml version='1.0' encoding='utf-8'?>\n$", 4390 "Invalid token after text declaration not faulted", NULL, 4391 XML_ERROR_INVALID_TOKEN}, 4392 {"<?xml version='1.0' encoding='utf-8'?>\n'wombat", 4393 "Unterminated string after text decl not faulted", NULL, 4394 XML_ERROR_UNCLOSED_TOKEN}, 4395 {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82", 4396 "Partial UTF-8 character after text decl not faulted", NULL, 4397 XML_ERROR_PARTIAL_CHAR}, 4398 {"%e1;", "Recursive parameter entity not faulted", NULL, 4399 XML_ERROR_RECURSIVE_ENTITY_REF}, 4400 {NULL, NULL, NULL, XML_ERROR_NONE}}; 4401 int i; 4402 4403 for (i = 0; data_004_2[i].parse_text != NULL; i++) { 4404 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4405 XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer); 4406 XML_SetUserData(g_parser, &data_004_2[i]); 4407 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4408 == XML_STATUS_ERROR) 4409 xml_failure(g_parser); 4410 XML_ParserReset(g_parser, NULL); 4411 } 4412 } 4413 END_TEST 4414 4415 /* Test the recursive parse interacts with a not standalone handler */ 4416 static int XMLCALL 4417 external_entity_not_standalone(XML_Parser parser, const XML_Char *context, 4418 const XML_Char *base, const XML_Char *systemId, 4419 const XML_Char *publicId) { 4420 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4421 "<!ENTITY % e1 SYSTEM 'bar'>\n" 4422 "%e1;\n"; 4423 const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>"; 4424 XML_Parser ext_parser; 4425 4426 UNUSED_P(base); 4427 UNUSED_P(publicId); 4428 if (systemId == NULL) 4429 return XML_STATUS_OK; 4430 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4431 if (ext_parser == NULL) 4432 fail("Could not create external entity parser"); 4433 if (! xcstrcmp(systemId, XCS("foo"))) { 4434 XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler); 4435 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4436 != XML_STATUS_ERROR) 4437 fail("Expected not standalone rejection"); 4438 if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE) 4439 xml_failure(ext_parser); 4440 XML_SetNotStandaloneHandler(ext_parser, NULL); 4441 XML_ParserFree(ext_parser); 4442 return XML_STATUS_ERROR; 4443 } else if (! xcstrcmp(systemId, XCS("bar"))) { 4444 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4445 == XML_STATUS_ERROR) 4446 xml_failure(ext_parser); 4447 } 4448 4449 XML_ParserFree(ext_parser); 4450 return XML_STATUS_OK; 4451 } 4452 4453 START_TEST(test_ext_entity_not_standalone) { 4454 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4455 "<doc></doc>"; 4456 4457 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4458 XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone); 4459 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4460 "Standalone rejection not caught"); 4461 } 4462 END_TEST 4463 4464 static int XMLCALL 4465 external_entity_value_aborter(XML_Parser parser, const XML_Char *context, 4466 const XML_Char *base, const XML_Char *systemId, 4467 const XML_Char *publicId) { 4468 const char *text1 = "<!ELEMENT doc EMPTY>\n" 4469 "<!ENTITY % e1 SYSTEM '004-2.ent'>\n" 4470 "<!ENTITY % e2 '%e1;'>\n" 4471 "%e1;\n"; 4472 const char *text2 = "<?xml version='1.0' encoding='utf-8'?>"; 4473 XML_Parser ext_parser; 4474 4475 UNUSED_P(base); 4476 UNUSED_P(publicId); 4477 if (systemId == NULL) 4478 return XML_STATUS_OK; 4479 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4480 if (ext_parser == NULL) 4481 fail("Could not create external entity parser"); 4482 if (! xcstrcmp(systemId, XCS("004-1.ent"))) { 4483 if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE) 4484 == XML_STATUS_ERROR) 4485 xml_failure(ext_parser); 4486 } 4487 if (! xcstrcmp(systemId, XCS("004-2.ent"))) { 4488 XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler); 4489 XML_SetUserData(ext_parser, ext_parser); 4490 if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE) 4491 != XML_STATUS_ERROR) 4492 fail("Aborted parse not faulted"); 4493 if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED) 4494 xml_failure(ext_parser); 4495 } 4496 4497 XML_ParserFree(ext_parser); 4498 return XML_STATUS_OK; 4499 } 4500 4501 START_TEST(test_ext_entity_value_abort) { 4502 const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n" 4503 "<doc></doc>\n"; 4504 4505 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4506 XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter); 4507 resumable = XML_FALSE; 4508 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4509 == XML_STATUS_ERROR) 4510 xml_failure(g_parser); 4511 } 4512 END_TEST 4513 4514 START_TEST(test_bad_public_doctype) { 4515 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 4516 "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n" 4517 "<doc></doc>"; 4518 4519 /* Setting a handler provokes a particular code path */ 4520 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 4521 dummy_end_doctype_handler); 4522 expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed"); 4523 } 4524 END_TEST 4525 4526 /* Test based on ibm/valid/P32/ibm32v04.xml */ 4527 START_TEST(test_attribute_enum_value) { 4528 const char *text = "<?xml version='1.0' standalone='no'?>\n" 4529 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 4530 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 4531 ExtTest dtd_data 4532 = {"<!ELEMENT animal (#PCDATA|a)*>\n" 4533 "<!ELEMENT a EMPTY>\n" 4534 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>", 4535 NULL, NULL}; 4536 const XML_Char *expected = XCS("This is a \n \n\nyellow tiger"); 4537 4538 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 4539 XML_SetUserData(g_parser, &dtd_data); 4540 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4541 /* An attribute list handler provokes a different code path */ 4542 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 4543 run_ext_character_check(text, &dtd_data, expected); 4544 } 4545 END_TEST 4546 4547 /* Slightly bizarrely, the library seems to silently ignore entity 4548 * definitions for predefined entities, even when they are wrong. The 4549 * language of the XML 1.0 spec is somewhat unhelpful as to what ought 4550 * to happen, so this is currently treated as acceptable. 4551 */ 4552 START_TEST(test_predefined_entity_redefinition) { 4553 const char *text = "<!DOCTYPE doc [\n" 4554 "<!ENTITY apos 'foo'>\n" 4555 "]>\n" 4556 "<doc>'</doc>"; 4557 run_character_check(text, XCS("'")); 4558 } 4559 END_TEST 4560 4561 /* Test that the parser stops processing the DTD after an unresolved 4562 * parameter entity is encountered. 4563 */ 4564 START_TEST(test_dtd_stop_processing) { 4565 const char *text = "<!DOCTYPE doc [\n" 4566 "%foo;\n" 4567 "<!ENTITY bar 'bas'>\n" 4568 "]><doc/>"; 4569 4570 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 4571 dummy_handler_flags = 0; 4572 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4573 == XML_STATUS_ERROR) 4574 xml_failure(g_parser); 4575 if (dummy_handler_flags != 0) 4576 fail("DTD processing still going after undefined PE"); 4577 } 4578 END_TEST 4579 4580 /* Test public notations with no system ID */ 4581 START_TEST(test_public_notation_no_sysid) { 4582 const char *text = "<!DOCTYPE doc [\n" 4583 "<!NOTATION note PUBLIC 'foo'>\n" 4584 "<!ELEMENT doc EMPTY>\n" 4585 "]>\n<doc/>"; 4586 4587 dummy_handler_flags = 0; 4588 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 4589 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4590 == XML_STATUS_ERROR) 4591 xml_failure(g_parser); 4592 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 4593 fail("Notation declaration handler not called"); 4594 } 4595 END_TEST 4596 4597 static void XMLCALL 4598 record_element_start_handler(void *userData, const XML_Char *name, 4599 const XML_Char **atts) { 4600 UNUSED_P(atts); 4601 CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name)); 4602 } 4603 4604 START_TEST(test_nested_groups) { 4605 const char *text 4606 = "<!DOCTYPE doc [\n" 4607 "<!ELEMENT doc " 4608 /* Sixteen elements per line */ 4609 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 4610 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 4611 "))))))))))))))))))))))))))))))))>\n" 4612 "<!ELEMENT e EMPTY>" 4613 "]>\n" 4614 "<doc><e/></doc>"; 4615 CharData storage; 4616 4617 CharData_Init(&storage); 4618 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4619 XML_SetStartElementHandler(g_parser, record_element_start_handler); 4620 XML_SetUserData(g_parser, &storage); 4621 dummy_handler_flags = 0; 4622 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4623 == XML_STATUS_ERROR) 4624 xml_failure(g_parser); 4625 CharData_CheckXMLChars(&storage, XCS("doce")); 4626 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 4627 fail("Element handler not fired"); 4628 } 4629 END_TEST 4630 4631 START_TEST(test_group_choice) { 4632 const char *text = "<!DOCTYPE doc [\n" 4633 "<!ELEMENT doc (a|b|c)+>\n" 4634 "<!ELEMENT a EMPTY>\n" 4635 "<!ELEMENT b (#PCDATA)>\n" 4636 "<!ELEMENT c ANY>\n" 4637 "]>\n" 4638 "<doc>\n" 4639 "<a/>\n" 4640 "<b attr='foo'>This is a foo</b>\n" 4641 "<c></c>\n" 4642 "</doc>\n"; 4643 4644 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 4645 dummy_handler_flags = 0; 4646 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4647 == XML_STATUS_ERROR) 4648 xml_failure(g_parser); 4649 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 4650 fail("Element handler flag not raised"); 4651 } 4652 END_TEST 4653 4654 static int XMLCALL 4655 external_entity_public(XML_Parser parser, const XML_Char *context, 4656 const XML_Char *base, const XML_Char *systemId, 4657 const XML_Char *publicId) { 4658 const char *text1 = (const char *)XML_GetUserData(parser); 4659 const char *text2 = "<!ATTLIST doc a CDATA 'value'>"; 4660 const char *text = NULL; 4661 XML_Parser ext_parser; 4662 int parse_res; 4663 4664 UNUSED_P(base); 4665 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4666 if (ext_parser == NULL) 4667 return XML_STATUS_ERROR; 4668 if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) { 4669 text = text1; 4670 } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) { 4671 text = text2; 4672 } else 4673 fail("Unexpected parameters to external entity parser"); 4674 assert(text != NULL); 4675 parse_res 4676 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 4677 XML_ParserFree(ext_parser); 4678 return parse_res; 4679 } 4680 4681 START_TEST(test_standalone_parameter_entity) { 4682 const char *text = "<?xml version='1.0' standalone='yes'?>\n" 4683 "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n" 4684 "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n" 4685 "%entity;\n" 4686 "]>\n" 4687 "<doc></doc>"; 4688 char dtd_data[] = "<!ENTITY % e1 'foo'>\n"; 4689 4690 XML_SetUserData(g_parser, dtd_data); 4691 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4692 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 4693 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4694 == XML_STATUS_ERROR) 4695 xml_failure(g_parser); 4696 } 4697 END_TEST 4698 4699 /* Test skipping of parameter entity in an external DTD */ 4700 /* Derived from ibm/invalid/P69/ibm69i01.xml */ 4701 START_TEST(test_skipped_parameter_entity) { 4702 const char *text = "<?xml version='1.0'?>\n" 4703 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n" 4704 "<!ELEMENT root (#PCDATA|a)* >\n" 4705 "]>\n" 4706 "<root></root>"; 4707 ExtTest dtd_data = {"%pe2;", NULL, NULL}; 4708 4709 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 4710 XML_SetUserData(g_parser, &dtd_data); 4711 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4712 XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler); 4713 dummy_handler_flags = 0; 4714 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4715 == XML_STATUS_ERROR) 4716 xml_failure(g_parser); 4717 if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG) 4718 fail("Skip handler not executed"); 4719 } 4720 END_TEST 4721 4722 /* Test recursive parameter entity definition rejected in external DTD */ 4723 START_TEST(test_recursive_external_parameter_entity) { 4724 const char *text = "<?xml version='1.0'?>\n" 4725 "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n" 4726 "<!ELEMENT root (#PCDATA|a)* >\n" 4727 "]>\n" 4728 "<root></root>"; 4729 ExtFaults dtd_data = {"<!ENTITY % pe2 '%pe2;'>\n%pe2;", 4730 "Recursive external parameter entity not faulted", NULL, 4731 XML_ERROR_RECURSIVE_ENTITY_REF}; 4732 4733 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 4734 XML_SetUserData(g_parser, &dtd_data); 4735 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4736 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 4737 "Recursive external parameter not spotted"); 4738 } 4739 END_TEST 4740 4741 /* Test undefined parameter entity in external entity handler */ 4742 static int XMLCALL 4743 external_entity_devaluer(XML_Parser parser, const XML_Char *context, 4744 const XML_Char *base, const XML_Char *systemId, 4745 const XML_Char *publicId) { 4746 const char *text = "<!ELEMENT doc EMPTY>\n" 4747 "<!ENTITY % e1 SYSTEM 'bar'>\n" 4748 "%e1;\n"; 4749 XML_Parser ext_parser; 4750 intptr_t clear_handler = (intptr_t)XML_GetUserData(parser); 4751 4752 UNUSED_P(base); 4753 UNUSED_P(publicId); 4754 if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar"))) 4755 return XML_STATUS_OK; 4756 if (xcstrcmp(systemId, XCS("foo"))) 4757 fail("Unexpected system ID"); 4758 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 4759 if (ext_parser == NULL) 4760 fail("Could note create external entity parser"); 4761 if (clear_handler) 4762 XML_SetExternalEntityRefHandler(ext_parser, NULL); 4763 if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) 4764 == XML_STATUS_ERROR) 4765 xml_failure(ext_parser); 4766 4767 XML_ParserFree(ext_parser); 4768 return XML_STATUS_OK; 4769 } 4770 4771 START_TEST(test_undefined_ext_entity_in_external_dtd) { 4772 const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n" 4773 "<doc></doc>\n"; 4774 4775 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4776 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer); 4777 XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE); 4778 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4779 == XML_STATUS_ERROR) 4780 xml_failure(g_parser); 4781 4782 /* Now repeat without the external entity ref handler invoking 4783 * another copy of itself. 4784 */ 4785 XML_ParserReset(g_parser, NULL); 4786 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 4787 XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer); 4788 XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE); 4789 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4790 == XML_STATUS_ERROR) 4791 xml_failure(g_parser); 4792 } 4793 END_TEST 4794 4795 static void XMLCALL 4796 aborting_xdecl_handler(void *userData, const XML_Char *version, 4797 const XML_Char *encoding, int standalone) { 4798 UNUSED_P(userData); 4799 UNUSED_P(version); 4800 UNUSED_P(encoding); 4801 UNUSED_P(standalone); 4802 XML_StopParser(g_parser, resumable); 4803 XML_SetXmlDeclHandler(g_parser, NULL); 4804 } 4805 4806 /* Test suspending the parse on receiving an XML declaration works */ 4807 START_TEST(test_suspend_xdecl) { 4808 const char *text = long_character_data_text; 4809 4810 XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler); 4811 resumable = XML_TRUE; 4812 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4813 != XML_STATUS_SUSPENDED) 4814 xml_failure(g_parser); 4815 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 4816 xml_failure(g_parser); 4817 /* Attempt to start a new parse while suspended */ 4818 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4819 != XML_STATUS_ERROR) 4820 fail("Attempt to parse while suspended not faulted"); 4821 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 4822 fail("Suspended parse not faulted with correct error"); 4823 } 4824 END_TEST 4825 4826 /* Test aborting the parse in an epilog works */ 4827 static void XMLCALL 4828 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) { 4829 const XML_Char *match = (const XML_Char *)userData; 4830 4831 if (match == NULL 4832 || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) { 4833 XML_StopParser(g_parser, resumable); 4834 XML_SetDefaultHandler(g_parser, NULL); 4835 } 4836 } 4837 4838 START_TEST(test_abort_epilog) { 4839 const char *text = "<doc></doc>\n\r\n"; 4840 XML_Char match[] = XCS("\r"); 4841 4842 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4843 XML_SetUserData(g_parser, match); 4844 resumable = XML_FALSE; 4845 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4846 != XML_STATUS_ERROR) 4847 fail("Abort not triggered"); 4848 if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED) 4849 xml_failure(g_parser); 4850 } 4851 END_TEST 4852 4853 /* Test a different code path for abort in the epilog */ 4854 START_TEST(test_abort_epilog_2) { 4855 const char *text = "<doc></doc>\n"; 4856 XML_Char match[] = XCS("\n"); 4857 4858 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4859 XML_SetUserData(g_parser, match); 4860 resumable = XML_FALSE; 4861 expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered"); 4862 } 4863 END_TEST 4864 4865 /* Test suspension from the epilog */ 4866 START_TEST(test_suspend_epilog) { 4867 const char *text = "<doc></doc>\n"; 4868 XML_Char match[] = XCS("\n"); 4869 4870 XML_SetDefaultHandler(g_parser, selective_aborting_default_handler); 4871 XML_SetUserData(g_parser, match); 4872 resumable = XML_TRUE; 4873 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4874 != XML_STATUS_SUSPENDED) 4875 xml_failure(g_parser); 4876 } 4877 END_TEST 4878 4879 static void XMLCALL 4880 suspending_end_handler(void *userData, const XML_Char *s) { 4881 UNUSED_P(s); 4882 XML_StopParser((XML_Parser)userData, 1); 4883 } 4884 4885 START_TEST(test_suspend_in_sole_empty_tag) { 4886 const char *text = "<doc/>"; 4887 enum XML_Status rc; 4888 4889 XML_SetEndElementHandler(g_parser, suspending_end_handler); 4890 XML_SetUserData(g_parser, g_parser); 4891 rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 4892 if (rc == XML_STATUS_ERROR) 4893 xml_failure(g_parser); 4894 else if (rc != XML_STATUS_SUSPENDED) 4895 fail("Suspend not triggered"); 4896 rc = XML_ResumeParser(g_parser); 4897 if (rc == XML_STATUS_ERROR) 4898 xml_failure(g_parser); 4899 else if (rc != XML_STATUS_OK) 4900 fail("Resume failed"); 4901 } 4902 END_TEST 4903 4904 START_TEST(test_unfinished_epilog) { 4905 const char *text = "<doc></doc><"; 4906 4907 expect_failure(text, XML_ERROR_UNCLOSED_TOKEN, 4908 "Incomplete epilog entry not faulted"); 4909 } 4910 END_TEST 4911 4912 START_TEST(test_partial_char_in_epilog) { 4913 const char *text = "<doc></doc>\xe2\x82"; 4914 4915 /* First check that no fault is raised if the parse is not finished */ 4916 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 4917 == XML_STATUS_ERROR) 4918 xml_failure(g_parser); 4919 /* Now check that it is faulted once we finish */ 4920 if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR) 4921 fail("Partial character in epilog not faulted"); 4922 if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR) 4923 xml_failure(g_parser); 4924 } 4925 END_TEST 4926 4927 START_TEST(test_hash_collision) { 4928 /* For full coverage of the lookup routine, we need to ensure a 4929 * hash collision even though we can only tell that we have one 4930 * through breakpoint debugging or coverage statistics. The 4931 * following will cause a hash collision on machines with a 64-bit 4932 * long type; others will have to experiment. The full coverage 4933 * tests invoked from qa.sh usually provide a hash collision, but 4934 * not always. This is an attempt to provide insurance. 4935 */ 4936 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U) 4937 const char *text 4938 = "<doc>\n" 4939 "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n" 4940 "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n" 4941 "<b5></b5><b6></b6><b7></b7><b8></b8>\n" 4942 "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n" 4943 "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n" 4944 "<d8>This triggers the table growth and collides with b2</d8>\n" 4945 "</doc>\n"; 4946 4947 XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT); 4948 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 4949 == XML_STATUS_ERROR) 4950 xml_failure(g_parser); 4951 } 4952 END_TEST 4953 #undef COLLIDING_HASH_SALT 4954 4955 /* Test resuming a parse suspended in entity substitution */ 4956 static void XMLCALL 4957 start_element_suspender(void *userData, const XML_Char *name, 4958 const XML_Char **atts) { 4959 UNUSED_P(userData); 4960 UNUSED_P(atts); 4961 if (! xcstrcmp(name, XCS("suspend"))) 4962 XML_StopParser(g_parser, XML_TRUE); 4963 if (! xcstrcmp(name, XCS("abort"))) 4964 XML_StopParser(g_parser, XML_FALSE); 4965 } 4966 4967 START_TEST(test_suspend_resume_internal_entity) { 4968 const char *text 4969 = "<!DOCTYPE doc [\n" 4970 "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n" 4971 "]>\n" 4972 "<doc>&foo;</doc>\n"; 4973 const XML_Char *expected1 = XCS("Hi"); 4974 const XML_Char *expected2 = XCS("HiHo"); 4975 CharData storage; 4976 4977 CharData_Init(&storage); 4978 XML_SetStartElementHandler(g_parser, start_element_suspender); 4979 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 4980 XML_SetUserData(g_parser, &storage); 4981 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 4982 != XML_STATUS_SUSPENDED) 4983 xml_failure(g_parser); 4984 CharData_CheckXMLChars(&storage, XCS("")); 4985 if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED) 4986 xml_failure(g_parser); 4987 CharData_CheckXMLChars(&storage, expected1); 4988 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 4989 xml_failure(g_parser); 4990 CharData_CheckXMLChars(&storage, expected2); 4991 } 4992 END_TEST 4993 4994 /* Test syntax error is caught at parse resumption */ 4995 START_TEST(test_resume_entity_with_syntax_error) { 4996 const char *text = "<!DOCTYPE doc [\n" 4997 "<!ENTITY foo '<suspend>Hi</wombat>'>\n" 4998 "]>\n" 4999 "<doc>&foo;</doc>\n"; 5000 5001 XML_SetStartElementHandler(g_parser, start_element_suspender); 5002 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5003 != XML_STATUS_SUSPENDED) 5004 xml_failure(g_parser); 5005 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 5006 fail("Syntax error in entity not faulted"); 5007 if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH) 5008 xml_failure(g_parser); 5009 } 5010 END_TEST 5011 5012 /* Test suspending and resuming in a parameter entity substitution */ 5013 static void XMLCALL 5014 element_decl_suspender(void *userData, const XML_Char *name, 5015 XML_Content *model) { 5016 UNUSED_P(userData); 5017 UNUSED_P(name); 5018 XML_StopParser(g_parser, XML_TRUE); 5019 XML_FreeContentModel(g_parser, model); 5020 } 5021 5022 START_TEST(test_suspend_resume_parameter_entity) { 5023 const char *text = "<!DOCTYPE doc [\n" 5024 "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n" 5025 "%foo;\n" 5026 "]>\n" 5027 "<doc>Hello, world</doc>"; 5028 const XML_Char *expected = XCS("Hello, world"); 5029 CharData storage; 5030 5031 CharData_Init(&storage); 5032 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5033 XML_SetElementDeclHandler(g_parser, element_decl_suspender); 5034 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 5035 XML_SetUserData(g_parser, &storage); 5036 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5037 != XML_STATUS_SUSPENDED) 5038 xml_failure(g_parser); 5039 CharData_CheckXMLChars(&storage, XCS("")); 5040 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 5041 xml_failure(g_parser); 5042 CharData_CheckXMLChars(&storage, expected); 5043 } 5044 END_TEST 5045 5046 /* Test attempting to use parser after an error is faulted */ 5047 START_TEST(test_restart_on_error) { 5048 const char *text = "<$doc><doc></doc>"; 5049 5050 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5051 != XML_STATUS_ERROR) 5052 fail("Invalid tag name not faulted"); 5053 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 5054 xml_failure(g_parser); 5055 if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) 5056 fail("Restarting invalid parse not faulted"); 5057 if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN) 5058 xml_failure(g_parser); 5059 } 5060 END_TEST 5061 5062 /* Test that angle brackets in an attribute default value are faulted */ 5063 START_TEST(test_reject_lt_in_attribute_value) { 5064 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n" 5065 "<doc></doc>"; 5066 5067 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5068 "Bad attribute default not faulted"); 5069 } 5070 END_TEST 5071 5072 START_TEST(test_reject_unfinished_param_in_att_value) { 5073 const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n" 5074 "<doc></doc>"; 5075 5076 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5077 "Bad attribute default not faulted"); 5078 } 5079 END_TEST 5080 5081 START_TEST(test_trailing_cr_in_att_value) { 5082 const char *text = "<doc a='value\r'/>"; 5083 5084 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5085 == XML_STATUS_ERROR) 5086 xml_failure(g_parser); 5087 } 5088 END_TEST 5089 5090 /* Try parsing a general entity within a parameter entity in a 5091 * standalone internal DTD. Covers a corner case in the parser. 5092 */ 5093 START_TEST(test_standalone_internal_entity) { 5094 const char *text = "<?xml version='1.0' standalone='yes' ?>\n" 5095 "<!DOCTYPE doc [\n" 5096 " <!ELEMENT doc (#PCDATA)>\n" 5097 " <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"≥\">'>\n" 5098 " <!ENTITY ge 'AttDefaultValue'>\n" 5099 " %pe;\n" 5100 "]>\n" 5101 "<doc att2='any'/>"; 5102 5103 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5104 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5105 == XML_STATUS_ERROR) 5106 xml_failure(g_parser); 5107 } 5108 END_TEST 5109 5110 /* Test that a reference to an unknown external entity is skipped */ 5111 START_TEST(test_skipped_external_entity) { 5112 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5113 "<doc></doc>\n"; 5114 ExtTest test_data = {"<!ELEMENT doc EMPTY>\n" 5115 "<!ENTITY % e2 '%e1;'>\n", 5116 NULL, NULL}; 5117 5118 XML_SetUserData(g_parser, &test_data); 5119 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5120 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5121 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5122 == XML_STATUS_ERROR) 5123 xml_failure(g_parser); 5124 } 5125 END_TEST 5126 5127 /* Test a different form of unknown external entity */ 5128 typedef struct ext_hdlr_data { 5129 const char *parse_text; 5130 XML_ExternalEntityRefHandler handler; 5131 } ExtHdlrData; 5132 5133 static int XMLCALL 5134 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context, 5135 const XML_Char *base, const XML_Char *systemId, 5136 const XML_Char *publicId) { 5137 ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser); 5138 XML_Parser ext_parser; 5139 5140 UNUSED_P(base); 5141 UNUSED_P(systemId); 5142 UNUSED_P(publicId); 5143 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 5144 if (ext_parser == NULL) 5145 fail("Could not create external entity parser."); 5146 /* Use the requested entity parser for further externals */ 5147 XML_SetExternalEntityRefHandler(ext_parser, test_data->handler); 5148 if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text, 5149 (int)strlen(test_data->parse_text), XML_TRUE) 5150 == XML_STATUS_ERROR) { 5151 xml_failure(ext_parser); 5152 } 5153 5154 XML_ParserFree(ext_parser); 5155 return XML_STATUS_OK; 5156 } 5157 5158 START_TEST(test_skipped_null_loaded_ext_entity) { 5159 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5160 "<doc />"; 5161 ExtHdlrData test_data 5162 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5163 "<!ENTITY % pe2 '%pe1;'>\n" 5164 "%pe2;\n", 5165 external_entity_null_loader}; 5166 5167 XML_SetUserData(g_parser, &test_data); 5168 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5169 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5170 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5171 == XML_STATUS_ERROR) 5172 xml_failure(g_parser); 5173 } 5174 END_TEST 5175 5176 START_TEST(test_skipped_unloaded_ext_entity) { 5177 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 5178 "<doc />"; 5179 ExtHdlrData test_data 5180 = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n" 5181 "<!ENTITY % pe2 '%pe1;'>\n" 5182 "%pe2;\n", 5183 NULL}; 5184 5185 XML_SetUserData(g_parser, &test_data); 5186 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5187 XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader); 5188 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5189 == XML_STATUS_ERROR) 5190 xml_failure(g_parser); 5191 } 5192 END_TEST 5193 5194 /* Test that a parameter entity value ending with a carriage return 5195 * has it translated internally into a newline. 5196 */ 5197 START_TEST(test_param_entity_with_trailing_cr) { 5198 #define PARAM_ENTITY_NAME "pe" 5199 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">" 5200 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 5201 "<doc/>"; 5202 ExtTest test_data 5203 = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n" 5204 "%" PARAM_ENTITY_NAME ";\n", 5205 NULL, NULL}; 5206 5207 XML_SetUserData(g_parser, &test_data); 5208 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 5209 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader); 5210 XML_SetEntityDeclHandler(g_parser, param_entity_match_handler); 5211 entity_name_to_match = XCS(PARAM_ENTITY_NAME); 5212 entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n"); 5213 entity_match_flag = ENTITY_MATCH_NOT_FOUND; 5214 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5215 == XML_STATUS_ERROR) 5216 xml_failure(g_parser); 5217 if (entity_match_flag == ENTITY_MATCH_FAIL) 5218 fail("Parameter entity CR->NEWLINE conversion failed"); 5219 else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND) 5220 fail("Parameter entity not parsed"); 5221 } 5222 #undef PARAM_ENTITY_NAME 5223 #undef PARAM_ENTITY_CORE_VALUE 5224 END_TEST 5225 5226 START_TEST(test_invalid_character_entity) { 5227 const char *text = "<!DOCTYPE doc [\n" 5228 " <!ENTITY entity '�'>\n" 5229 "]>\n" 5230 "<doc>&entity;</doc>"; 5231 5232 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5233 "Out of range character reference not faulted"); 5234 } 5235 END_TEST 5236 5237 START_TEST(test_invalid_character_entity_2) { 5238 const char *text = "<!DOCTYPE doc [\n" 5239 " <!ENTITY entity '&#xg0;'>\n" 5240 "]>\n" 5241 "<doc>&entity;</doc>"; 5242 5243 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5244 "Out of range character reference not faulted"); 5245 } 5246 END_TEST 5247 5248 START_TEST(test_invalid_character_entity_3) { 5249 const char text[] = 5250 /* <!DOCTYPE doc [\n */ 5251 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 5252 /* U+0E04 = KHO KHWAI 5253 * U+0E08 = CHO CHAN */ 5254 /* <!ENTITY entity '&\u0e04\u0e08;'>\n */ 5255 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 " 5256 "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n" 5257 /* ]>\n */ 5258 "\0]\0>\0\n" 5259 /* <doc>&entity;</doc> */ 5260 "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>"; 5261 5262 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5263 != XML_STATUS_ERROR) 5264 fail("Invalid start of entity name not faulted"); 5265 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY) 5266 xml_failure(g_parser); 5267 } 5268 END_TEST 5269 5270 START_TEST(test_invalid_character_entity_4) { 5271 const char *text = "<!DOCTYPE doc [\n" 5272 " <!ENTITY entity '�'>\n" /* = � */ 5273 "]>\n" 5274 "<doc>&entity;</doc>"; 5275 5276 expect_failure(text, XML_ERROR_BAD_CHAR_REF, 5277 "Out of range character reference not faulted"); 5278 } 5279 END_TEST 5280 5281 /* Test that processing instructions are picked up by a default handler */ 5282 START_TEST(test_pi_handled_in_default) { 5283 const char *text = "<?test processing instruction?>\n<doc/>"; 5284 const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>"); 5285 CharData storage; 5286 5287 CharData_Init(&storage); 5288 XML_SetDefaultHandler(g_parser, accumulate_characters); 5289 XML_SetUserData(g_parser, &storage); 5290 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5291 == XML_STATUS_ERROR) 5292 xml_failure(g_parser); 5293 CharData_CheckXMLChars(&storage, expected); 5294 } 5295 END_TEST 5296 5297 /* Test that comments are picked up by a default handler */ 5298 START_TEST(test_comment_handled_in_default) { 5299 const char *text = "<!-- This is a comment -->\n<doc/>"; 5300 const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>"); 5301 CharData storage; 5302 5303 CharData_Init(&storage); 5304 XML_SetDefaultHandler(g_parser, accumulate_characters); 5305 XML_SetUserData(g_parser, &storage); 5306 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5307 == XML_STATUS_ERROR) 5308 xml_failure(g_parser); 5309 CharData_CheckXMLChars(&storage, expected); 5310 } 5311 END_TEST 5312 5313 /* Test PIs that look almost but not quite like XML declarations */ 5314 static void XMLCALL 5315 accumulate_pi_characters(void *userData, const XML_Char *target, 5316 const XML_Char *data) { 5317 CharData *storage = (CharData *)userData; 5318 5319 CharData_AppendXMLChars(storage, target, -1); 5320 CharData_AppendXMLChars(storage, XCS(": "), 2); 5321 CharData_AppendXMLChars(storage, data, -1); 5322 CharData_AppendXMLChars(storage, XCS("\n"), 1); 5323 } 5324 5325 START_TEST(test_pi_yml) { 5326 const char *text = "<?yml something like data?><doc/>"; 5327 const XML_Char *expected = XCS("yml: something like data\n"); 5328 CharData storage; 5329 5330 CharData_Init(&storage); 5331 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5332 XML_SetUserData(g_parser, &storage); 5333 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5334 == XML_STATUS_ERROR) 5335 xml_failure(g_parser); 5336 CharData_CheckXMLChars(&storage, expected); 5337 } 5338 END_TEST 5339 5340 START_TEST(test_pi_xnl) { 5341 const char *text = "<?xnl nothing like data?><doc/>"; 5342 const XML_Char *expected = XCS("xnl: nothing like data\n"); 5343 CharData storage; 5344 5345 CharData_Init(&storage); 5346 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5347 XML_SetUserData(g_parser, &storage); 5348 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5349 == XML_STATUS_ERROR) 5350 xml_failure(g_parser); 5351 CharData_CheckXMLChars(&storage, expected); 5352 } 5353 END_TEST 5354 5355 START_TEST(test_pi_xmm) { 5356 const char *text = "<?xmm everything like data?><doc/>"; 5357 const XML_Char *expected = XCS("xmm: everything like data\n"); 5358 CharData storage; 5359 5360 CharData_Init(&storage); 5361 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5362 XML_SetUserData(g_parser, &storage); 5363 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5364 == XML_STATUS_ERROR) 5365 xml_failure(g_parser); 5366 CharData_CheckXMLChars(&storage, expected); 5367 } 5368 END_TEST 5369 5370 START_TEST(test_utf16_pi) { 5371 const char text[] = 5372 /* <?{KHO KHWAI}{CHO CHAN}?> 5373 * where {KHO KHWAI} = U+0E04 5374 * and {CHO CHAN} = U+0E08 5375 */ 5376 "<\0?\0\x04\x0e\x08\x0e?\0>\0" 5377 /* <q/> */ 5378 "<\0q\0/\0>\0"; 5379 #ifdef XML_UNICODE 5380 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5381 #else 5382 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5383 #endif 5384 CharData storage; 5385 5386 CharData_Init(&storage); 5387 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5388 XML_SetUserData(g_parser, &storage); 5389 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5390 == XML_STATUS_ERROR) 5391 xml_failure(g_parser); 5392 CharData_CheckXMLChars(&storage, expected); 5393 } 5394 END_TEST 5395 5396 START_TEST(test_utf16_be_pi) { 5397 const char text[] = 5398 /* <?{KHO KHWAI}{CHO CHAN}?> 5399 * where {KHO KHWAI} = U+0E04 5400 * and {CHO CHAN} = U+0E08 5401 */ 5402 "\0<\0?\x0e\x04\x0e\x08\0?\0>" 5403 /* <q/> */ 5404 "\0<\0q\0/\0>"; 5405 #ifdef XML_UNICODE 5406 const XML_Char *expected = XCS("\x0e04\x0e08: \n"); 5407 #else 5408 const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n"); 5409 #endif 5410 CharData storage; 5411 5412 CharData_Init(&storage); 5413 XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters); 5414 XML_SetUserData(g_parser, &storage); 5415 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5416 == XML_STATUS_ERROR) 5417 xml_failure(g_parser); 5418 CharData_CheckXMLChars(&storage, expected); 5419 } 5420 END_TEST 5421 5422 /* Test that comments can be picked up and translated */ 5423 static void XMLCALL 5424 accumulate_comment(void *userData, const XML_Char *data) { 5425 CharData *storage = (CharData *)userData; 5426 5427 CharData_AppendXMLChars(storage, data, -1); 5428 } 5429 5430 START_TEST(test_utf16_be_comment) { 5431 const char text[] = 5432 /* <!-- Comment A --> */ 5433 "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n" 5434 /* <doc/> */ 5435 "\0<\0d\0o\0c\0/\0>"; 5436 const XML_Char *expected = XCS(" Comment A "); 5437 CharData storage; 5438 5439 CharData_Init(&storage); 5440 XML_SetCommentHandler(g_parser, accumulate_comment); 5441 XML_SetUserData(g_parser, &storage); 5442 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5443 == XML_STATUS_ERROR) 5444 xml_failure(g_parser); 5445 CharData_CheckXMLChars(&storage, expected); 5446 } 5447 END_TEST 5448 5449 START_TEST(test_utf16_le_comment) { 5450 const char text[] = 5451 /* <!-- Comment B --> */ 5452 "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0" 5453 /* <doc/> */ 5454 "<\0d\0o\0c\0/\0>\0"; 5455 const XML_Char *expected = XCS(" Comment B "); 5456 CharData storage; 5457 5458 CharData_Init(&storage); 5459 XML_SetCommentHandler(g_parser, accumulate_comment); 5460 XML_SetUserData(g_parser, &storage); 5461 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 5462 == XML_STATUS_ERROR) 5463 xml_failure(g_parser); 5464 CharData_CheckXMLChars(&storage, expected); 5465 } 5466 END_TEST 5467 5468 /* Test that the unknown encoding handler with map entries that expect 5469 * conversion but no conversion function is faulted 5470 */ 5471 static int XMLCALL 5472 failing_converter(void *data, const char *s) { 5473 UNUSED_P(data); 5474 UNUSED_P(s); 5475 /* Always claim to have failed */ 5476 return -1; 5477 } 5478 5479 static int XMLCALL 5480 prefix_converter(void *data, const char *s) { 5481 UNUSED_P(data); 5482 /* If the first byte is 0xff, raise an error */ 5483 if (s[0] == (char)-1) 5484 return -1; 5485 /* Just add the low bits of the first byte to the second */ 5486 return (s[1] + (s[0] & 0x7f)) & 0x01ff; 5487 } 5488 5489 static int XMLCALL 5490 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) { 5491 int i; 5492 int high_map = -2; /* Assume a 2-byte sequence */ 5493 5494 if (! xcstrcmp(encoding, XCS("invalid-9")) 5495 || ! xcstrcmp(encoding, XCS("ascii-like")) 5496 || ! xcstrcmp(encoding, XCS("invalid-len")) 5497 || ! xcstrcmp(encoding, XCS("invalid-a")) 5498 || ! xcstrcmp(encoding, XCS("invalid-surrogate")) 5499 || ! xcstrcmp(encoding, XCS("invalid-high"))) 5500 high_map = -1; 5501 5502 for (i = 0; i < 128; ++i) 5503 info->map[i] = i; 5504 for (; i < 256; ++i) 5505 info->map[i] = high_map; 5506 5507 /* If required, put an invalid value in the ASCII entries */ 5508 if (! xcstrcmp(encoding, XCS("invalid-9"))) 5509 info->map[9] = 5; 5510 /* If required, have a top-bit set character starts a 5-byte sequence */ 5511 if (! xcstrcmp(encoding, XCS("invalid-len"))) 5512 info->map[0x81] = -5; 5513 /* If required, make a top-bit set character a valid ASCII character */ 5514 if (! xcstrcmp(encoding, XCS("invalid-a"))) 5515 info->map[0x82] = 'a'; 5516 /* If required, give a top-bit set character a forbidden value, 5517 * what would otherwise be the first of a surrogate pair. 5518 */ 5519 if (! xcstrcmp(encoding, XCS("invalid-surrogate"))) 5520 info->map[0x83] = 0xd801; 5521 /* If required, give a top-bit set character too high a value */ 5522 if (! xcstrcmp(encoding, XCS("invalid-high"))) 5523 info->map[0x84] = 0x010101; 5524 5525 info->data = data; 5526 info->release = NULL; 5527 if (! xcstrcmp(encoding, XCS("failing-conv"))) 5528 info->convert = failing_converter; 5529 else if (! xcstrcmp(encoding, XCS("prefix-conv"))) 5530 info->convert = prefix_converter; 5531 else 5532 info->convert = NULL; 5533 return XML_STATUS_OK; 5534 } 5535 5536 START_TEST(test_missing_encoding_conversion_fn) { 5537 const char *text = "<?xml version='1.0' encoding='no-conv'?>\n" 5538 "<doc>\x81</doc>"; 5539 5540 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5541 /* MiscEncodingHandler sets up an encoding with every top-bit-set 5542 * character introducing a two-byte sequence. For this, it 5543 * requires a convert function. The above function call doesn't 5544 * pass one through, so when BadEncodingHandler actually gets 5545 * called it should supply an invalid encoding. 5546 */ 5547 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5548 "Encoding with missing convert() not faulted"); 5549 } 5550 END_TEST 5551 5552 START_TEST(test_failing_encoding_conversion_fn) { 5553 const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n" 5554 "<doc>\x81</doc>"; 5555 5556 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5557 /* BadEncodingHandler sets up an encoding with every top-bit-set 5558 * character introducing a two-byte sequence. For this, it 5559 * requires a convert function. The above function call passes 5560 * one that insists all possible sequences are invalid anyway. 5561 */ 5562 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5563 "Encoding with failing convert() not faulted"); 5564 } 5565 END_TEST 5566 5567 /* Test unknown encoding conversions */ 5568 START_TEST(test_unknown_encoding_success) { 5569 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5570 /* Equivalent to <eoc>Hello, world</eoc> */ 5571 "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>"; 5572 5573 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5574 run_character_check(text, XCS("Hello, world")); 5575 } 5576 END_TEST 5577 5578 /* Test bad name character in unknown encoding */ 5579 START_TEST(test_unknown_encoding_bad_name) { 5580 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5581 "<\xff\x64oc>Hello, world</\xff\x64oc>"; 5582 5583 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5584 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5585 "Bad name start in unknown encoding not faulted"); 5586 } 5587 END_TEST 5588 5589 /* Test bad mid-name character in unknown encoding */ 5590 START_TEST(test_unknown_encoding_bad_name_2) { 5591 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5592 "<d\xffoc>Hello, world</d\xffoc>"; 5593 5594 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5595 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5596 "Bad name in unknown encoding not faulted"); 5597 } 5598 END_TEST 5599 5600 /* Test element name that is long enough to fill the conversion buffer 5601 * in an unknown encoding, finishing with an encoded character. 5602 */ 5603 START_TEST(test_unknown_encoding_long_name_1) { 5604 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5605 "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>" 5606 "Hi" 5607 "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"; 5608 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5609 CharData storage; 5610 5611 CharData_Init(&storage); 5612 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5613 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5614 XML_SetUserData(g_parser, &storage); 5615 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5616 == XML_STATUS_ERROR) 5617 xml_failure(g_parser); 5618 CharData_CheckXMLChars(&storage, expected); 5619 } 5620 END_TEST 5621 5622 /* Test element name that is long enough to fill the conversion buffer 5623 * in an unknown encoding, finishing with an simple character. 5624 */ 5625 START_TEST(test_unknown_encoding_long_name_2) { 5626 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5627 "<abcdefghabcdefghabcdefghijklmnop>" 5628 "Hi" 5629 "</abcdefghabcdefghabcdefghijklmnop>"; 5630 const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop"); 5631 CharData storage; 5632 5633 CharData_Init(&storage); 5634 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5635 XML_SetStartElementHandler(g_parser, record_element_start_handler); 5636 XML_SetUserData(g_parser, &storage); 5637 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5638 == XML_STATUS_ERROR) 5639 xml_failure(g_parser); 5640 CharData_CheckXMLChars(&storage, expected); 5641 } 5642 END_TEST 5643 5644 START_TEST(test_invalid_unknown_encoding) { 5645 const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n" 5646 "<doc>Hello world</doc>"; 5647 5648 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5649 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5650 "Invalid unknown encoding not faulted"); 5651 } 5652 END_TEST 5653 5654 START_TEST(test_unknown_ascii_encoding_ok) { 5655 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5656 "<doc>Hello, world</doc>"; 5657 5658 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5659 run_character_check(text, XCS("Hello, world")); 5660 } 5661 END_TEST 5662 5663 START_TEST(test_unknown_ascii_encoding_fail) { 5664 const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n" 5665 "<doc>Hello, \x80 world</doc>"; 5666 5667 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5668 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5669 "Invalid character not faulted"); 5670 } 5671 END_TEST 5672 5673 START_TEST(test_unknown_encoding_invalid_length) { 5674 const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n" 5675 "<doc>Hello, world</doc>"; 5676 5677 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5678 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5679 "Invalid unknown encoding not faulted"); 5680 } 5681 END_TEST 5682 5683 START_TEST(test_unknown_encoding_invalid_topbit) { 5684 const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n" 5685 "<doc>Hello, world</doc>"; 5686 5687 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5688 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5689 "Invalid unknown encoding not faulted"); 5690 } 5691 END_TEST 5692 5693 START_TEST(test_unknown_encoding_invalid_surrogate) { 5694 const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n" 5695 "<doc>Hello, \x82 world</doc>"; 5696 5697 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5698 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5699 "Invalid unknown encoding not faulted"); 5700 } 5701 END_TEST 5702 5703 START_TEST(test_unknown_encoding_invalid_high) { 5704 const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n" 5705 "<doc>Hello, world</doc>"; 5706 5707 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5708 expect_failure(text, XML_ERROR_UNKNOWN_ENCODING, 5709 "Invalid unknown encoding not faulted"); 5710 } 5711 END_TEST 5712 5713 START_TEST(test_unknown_encoding_invalid_attr_value) { 5714 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 5715 "<doc attr='\xff\x30'/>"; 5716 5717 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 5718 expect_failure(text, XML_ERROR_INVALID_TOKEN, 5719 "Invalid attribute valid not faulted"); 5720 } 5721 END_TEST 5722 5723 /* Test an external entity parser set to use latin-1 detects UTF-16 5724 * BOMs correctly. 5725 */ 5726 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 }; 5727 5728 typedef struct ExtTest2 { 5729 const char *parse_text; 5730 int parse_len; 5731 const XML_Char *encoding; 5732 CharData *storage; 5733 enum ee_parse_flags flags; 5734 } ExtTest2; 5735 5736 static int XMLCALL 5737 external_entity_loader2(XML_Parser parser, const XML_Char *context, 5738 const XML_Char *base, const XML_Char *systemId, 5739 const XML_Char *publicId) { 5740 ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser); 5741 XML_Parser extparser; 5742 5743 UNUSED_P(base); 5744 UNUSED_P(systemId); 5745 UNUSED_P(publicId); 5746 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 5747 if (extparser == NULL) 5748 fail("Coulr not create external entity parser"); 5749 if (test_data->encoding != NULL) { 5750 if (! XML_SetEncoding(extparser, test_data->encoding)) 5751 fail("XML_SetEncoding() ignored for external entity"); 5752 } 5753 if (test_data->flags & EE_PARSE_FULL_BUFFER) { 5754 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 5755 XML_TRUE) 5756 == XML_STATUS_ERROR) { 5757 xml_failure(extparser); 5758 } 5759 } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text, 5760 test_data->parse_len, XML_TRUE) 5761 == XML_STATUS_ERROR) { 5762 xml_failure(extparser); 5763 } 5764 5765 XML_ParserFree(extparser); 5766 return XML_STATUS_OK; 5767 } 5768 5769 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */ 5770 static void XMLCALL 5771 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) { 5772 ExtTest2 *test_data = (ExtTest2 *)userData; 5773 accumulate_characters(test_data->storage, s, len); 5774 } 5775 5776 START_TEST(test_ext_entity_latin1_utf16le_bom) { 5777 const char *text = "<!DOCTYPE doc [\n" 5778 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5779 "]>\n" 5780 "<doc>&en;</doc>"; 5781 ExtTest2 test_data 5782 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5783 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5784 * 0x4c = L and 0x20 is a space 5785 */ 5786 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5787 #ifdef XML_UNICODE 5788 const XML_Char *expected = XCS("\x00ff\x00feL "); 5789 #else 5790 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5791 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5792 #endif 5793 CharData storage; 5794 5795 CharData_Init(&storage); 5796 test_data.storage = &storage; 5797 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5798 XML_SetUserData(g_parser, &test_data); 5799 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5800 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5801 == XML_STATUS_ERROR) 5802 xml_failure(g_parser); 5803 CharData_CheckXMLChars(&storage, expected); 5804 } 5805 END_TEST 5806 5807 START_TEST(test_ext_entity_latin1_utf16be_bom) { 5808 const char *text = "<!DOCTYPE doc [\n" 5809 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5810 "]>\n" 5811 "<doc>&en;</doc>"; 5812 ExtTest2 test_data 5813 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5814 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5815 * 0x4c = L and 0x20 is a space 5816 */ 5817 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE}; 5818 #ifdef XML_UNICODE 5819 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5820 #else 5821 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5822 const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L"); 5823 #endif 5824 CharData storage; 5825 5826 CharData_Init(&storage); 5827 test_data.storage = &storage; 5828 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5829 XML_SetUserData(g_parser, &test_data); 5830 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5831 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5832 == XML_STATUS_ERROR) 5833 xml_failure(g_parser); 5834 CharData_CheckXMLChars(&storage, expected); 5835 } 5836 END_TEST 5837 5838 /* Parsing the full buffer rather than a byte at a time makes a 5839 * difference to the encoding scanning code, so repeat the above tests 5840 * without breaking them down by byte. 5841 */ 5842 START_TEST(test_ext_entity_latin1_utf16le_bom2) { 5843 const char *text = "<!DOCTYPE doc [\n" 5844 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5845 "]>\n" 5846 "<doc>&en;</doc>"; 5847 ExtTest2 test_data 5848 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5849 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5850 * 0x4c = L and 0x20 is a space 5851 */ 5852 "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5853 #ifdef XML_UNICODE 5854 const XML_Char *expected = XCS("\x00ff\x00feL "); 5855 #else 5856 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5857 const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL "); 5858 #endif 5859 CharData storage; 5860 5861 CharData_Init(&storage); 5862 test_data.storage = &storage; 5863 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5864 XML_SetUserData(g_parser, &test_data); 5865 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5866 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5867 == XML_STATUS_ERROR) 5868 xml_failure(g_parser); 5869 CharData_CheckXMLChars(&storage, expected); 5870 } 5871 END_TEST 5872 5873 START_TEST(test_ext_entity_latin1_utf16be_bom2) { 5874 const char *text = "<!DOCTYPE doc [\n" 5875 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5876 "]>\n" 5877 "<doc>&en;</doc>"; 5878 ExtTest2 test_data 5879 = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */ 5880 /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn, 5881 * 0x4c = L and 0x20 is a space 5882 */ 5883 "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER}; 5884 #ifdef XML_UNICODE 5885 const XML_Char *expected = XCS("\x00fe\x00ff L"); 5886 #else 5887 /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */ 5888 const XML_Char *expected = "\xc3\xbe\xc3\xbf L"; 5889 #endif 5890 CharData storage; 5891 5892 CharData_Init(&storage); 5893 test_data.storage = &storage; 5894 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5895 XML_SetUserData(g_parser, &test_data); 5896 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5897 if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) 5898 == XML_STATUS_ERROR) 5899 xml_failure(g_parser); 5900 CharData_CheckXMLChars(&storage, expected); 5901 } 5902 END_TEST 5903 5904 /* Test little-endian UTF-16 given an explicit big-endian encoding */ 5905 START_TEST(test_ext_entity_utf16_be) { 5906 const char *text = "<!DOCTYPE doc [\n" 5907 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5908 "]>\n" 5909 "<doc>&en;</doc>"; 5910 ExtTest2 test_data 5911 = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE}; 5912 #ifdef XML_UNICODE 5913 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 5914 #else 5915 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 5916 "\xe6\x94\x80" /* U+6500 */ 5917 "\xe2\xbc\x80" /* U+2F00 */ 5918 "\xe3\xb8\x80"); /* U+3E00 */ 5919 #endif 5920 CharData storage; 5921 5922 CharData_Init(&storage); 5923 test_data.storage = &storage; 5924 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5925 XML_SetUserData(g_parser, &test_data); 5926 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5927 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5928 == XML_STATUS_ERROR) 5929 xml_failure(g_parser); 5930 CharData_CheckXMLChars(&storage, expected); 5931 } 5932 END_TEST 5933 5934 /* Test big-endian UTF-16 given an explicit little-endian encoding */ 5935 START_TEST(test_ext_entity_utf16_le) { 5936 const char *text = "<!DOCTYPE doc [\n" 5937 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 5938 "]>\n" 5939 "<doc>&en;</doc>"; 5940 ExtTest2 test_data 5941 = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE}; 5942 #ifdef XML_UNICODE 5943 const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00"); 5944 #else 5945 const XML_Char *expected = XCS("\xe3\xb0\x80" /* U+3C00 */ 5946 "\xe6\x94\x80" /* U+6500 */ 5947 "\xe2\xbc\x80" /* U+2F00 */ 5948 "\xe3\xb8\x80"); /* U+3E00 */ 5949 #endif 5950 CharData storage; 5951 5952 CharData_Init(&storage); 5953 test_data.storage = &storage; 5954 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 5955 XML_SetUserData(g_parser, &test_data); 5956 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 5957 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 5958 == XML_STATUS_ERROR) 5959 xml_failure(g_parser); 5960 CharData_CheckXMLChars(&storage, expected); 5961 } 5962 END_TEST 5963 5964 /* Test little-endian UTF-16 given no explicit encoding. 5965 * The existing default encoding (UTF-8) is assumed to hold without a 5966 * BOM to contradict it, so the entity value will in fact provoke an 5967 * error because 0x00 is not a valid XML character. We parse the 5968 * whole buffer in one go rather than feeding it in byte by byte to 5969 * exercise different code paths in the initial scanning routines. 5970 */ 5971 typedef struct ExtFaults2 { 5972 const char *parse_text; 5973 int parse_len; 5974 const char *fail_text; 5975 const XML_Char *encoding; 5976 enum XML_Error error; 5977 } ExtFaults2; 5978 5979 static int XMLCALL 5980 external_entity_faulter2(XML_Parser parser, const XML_Char *context, 5981 const XML_Char *base, const XML_Char *systemId, 5982 const XML_Char *publicId) { 5983 ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser); 5984 XML_Parser extparser; 5985 5986 UNUSED_P(base); 5987 UNUSED_P(systemId); 5988 UNUSED_P(publicId); 5989 extparser = XML_ExternalEntityParserCreate(parser, context, NULL); 5990 if (extparser == NULL) 5991 fail("Could not create external entity parser"); 5992 if (test_data->encoding != NULL) { 5993 if (! XML_SetEncoding(extparser, test_data->encoding)) 5994 fail("XML_SetEncoding() ignored for external entity"); 5995 } 5996 if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len, 5997 XML_TRUE) 5998 != XML_STATUS_ERROR) 5999 fail(test_data->fail_text); 6000 if (XML_GetErrorCode(extparser) != test_data->error) 6001 xml_failure(extparser); 6002 6003 XML_ParserFree(extparser); 6004 return XML_STATUS_ERROR; 6005 } 6006 6007 START_TEST(test_ext_entity_utf16_unknown) { 6008 const char *text = "<!DOCTYPE doc [\n" 6009 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 6010 "]>\n" 6011 "<doc>&en;</doc>"; 6012 ExtFaults2 test_data 6013 = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL, 6014 XML_ERROR_INVALID_TOKEN}; 6015 6016 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2); 6017 XML_SetUserData(g_parser, &test_data); 6018 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 6019 "Invalid character should not have been accepted"); 6020 } 6021 END_TEST 6022 6023 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */ 6024 START_TEST(test_ext_entity_utf8_non_bom) { 6025 const char *text = "<!DOCTYPE doc [\n" 6026 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 6027 "]>\n" 6028 "<doc>&en;</doc>"; 6029 ExtTest2 test_data 6030 = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */ 6031 3, NULL, NULL, EE_PARSE_NONE}; 6032 #ifdef XML_UNICODE 6033 const XML_Char *expected = XCS("\xfec0"); 6034 #else 6035 const XML_Char *expected = XCS("\xef\xbb\x80"); 6036 #endif 6037 CharData storage; 6038 6039 CharData_Init(&storage); 6040 test_data.storage = &storage; 6041 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6042 XML_SetUserData(g_parser, &test_data); 6043 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6044 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6045 == XML_STATUS_ERROR) 6046 xml_failure(g_parser); 6047 CharData_CheckXMLChars(&storage, expected); 6048 } 6049 END_TEST 6050 6051 /* Test that UTF-8 in a CDATA section is correctly passed through */ 6052 START_TEST(test_utf8_in_cdata_section) { 6053 const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>"; 6054 #ifdef XML_UNICODE 6055 const XML_Char *expected = XCS("one \x00e9 two"); 6056 #else 6057 const XML_Char *expected = XCS("one \xc3\xa9 two"); 6058 #endif 6059 6060 run_character_check(text, expected); 6061 } 6062 END_TEST 6063 6064 /* Test that little-endian UTF-16 in a CDATA section is handled */ 6065 START_TEST(test_utf8_in_cdata_section_2) { 6066 const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>"; 6067 #ifdef XML_UNICODE 6068 const XML_Char *expected = XCS("\x00e9]\x00e9two"); 6069 #else 6070 const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two"); 6071 #endif 6072 6073 run_character_check(text, expected); 6074 } 6075 END_TEST 6076 6077 START_TEST(test_utf8_in_start_tags) { 6078 struct test_case { 6079 bool goodName; 6080 bool goodNameStart; 6081 const char *tagName; 6082 }; 6083 6084 // The idea with the tests below is this: 6085 // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences 6086 // go to isNever and are hence not a concern. 6087 // 6088 // We start with a character that is a valid name character 6089 // (or even name-start character, see XML 1.0r4 spec) and then we flip 6090 // single bits at places where (1) the result leaves the UTF-8 encoding space 6091 // and (2) we stay in the same n-byte sequence family. 6092 // 6093 // The flipped bits are highlighted in angle brackets in comments, 6094 // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped 6095 // the most significant bit to 1 to leave UTF-8 encoding space. 6096 struct test_case cases[] = { 6097 // 1-byte UTF-8: [0xxx xxxx] 6098 {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':' 6099 {false, false, "\xBA"}, // [<1>011 1010] 6100 {true, false, "\x39"}, // [0011 1001] = ASCII nine '9' 6101 {false, false, "\xB9"}, // [<1>011 1001] 6102 6103 // 2-byte UTF-8: [110x xxxx] [10xx xxxx] 6104 {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] = 6105 // Arabic small waw U+06E5 6106 {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101] 6107 {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101] 6108 {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101] 6109 {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] = 6110 // combining char U+0301 6111 {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001] 6112 {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001] 6113 {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001] 6114 6115 // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx] 6116 {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] = 6117 // Devanagari Letter A U+0905 6118 {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101] 6119 {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101] 6120 {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101] 6121 {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101] 6122 {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101] 6123 {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] = 6124 // combining char U+0901 6125 {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001] 6126 {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001] 6127 {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001] 6128 {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001] 6129 {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001] 6130 }; 6131 const bool atNameStart[] = {true, false}; 6132 6133 size_t i = 0; 6134 char doc[1024]; 6135 size_t failCount = 0; 6136 6137 for (; i < sizeof(cases) / sizeof(cases[0]); i++) { 6138 size_t j = 0; 6139 for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) { 6140 const bool expectedSuccess 6141 = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName; 6142 sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName); 6143 XML_Parser parser = XML_ParserCreate(NULL); 6144 6145 const enum XML_Status status 6146 = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE); 6147 6148 bool success = true; 6149 if ((status == XML_STATUS_OK) != expectedSuccess) { 6150 success = false; 6151 } 6152 if ((status == XML_STATUS_ERROR) 6153 && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) { 6154 success = false; 6155 } 6156 6157 if (! success) { 6158 fprintf( 6159 stderr, 6160 "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n", 6161 (unsigned)i + 1u, atNameStart[j] ? " " : "not ", 6162 (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser)); 6163 failCount++; 6164 } 6165 6166 XML_ParserFree(parser); 6167 } 6168 } 6169 6170 if (failCount > 0) { 6171 fail("UTF-8 regression detected"); 6172 } 6173 } 6174 END_TEST 6175 6176 /* Test trailing spaces in elements are accepted */ 6177 static void XMLCALL 6178 record_element_end_handler(void *userData, const XML_Char *name) { 6179 CharData *storage = (CharData *)userData; 6180 6181 CharData_AppendXMLChars(storage, XCS("/"), 1); 6182 CharData_AppendXMLChars(storage, name, -1); 6183 } 6184 6185 START_TEST(test_trailing_spaces_in_elements) { 6186 const char *text = "<doc >Hi</doc >"; 6187 const XML_Char *expected = XCS("doc/doc"); 6188 CharData storage; 6189 6190 CharData_Init(&storage); 6191 XML_SetElementHandler(g_parser, record_element_start_handler, 6192 record_element_end_handler); 6193 XML_SetUserData(g_parser, &storage); 6194 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6195 == XML_STATUS_ERROR) 6196 xml_failure(g_parser); 6197 CharData_CheckXMLChars(&storage, expected); 6198 } 6199 END_TEST 6200 6201 START_TEST(test_utf16_attribute) { 6202 const char text[] = 6203 /* <d {KHO KHWAI}{CHO CHAN}='a'/> 6204 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6205 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6206 */ 6207 "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0"; 6208 const XML_Char *expected = XCS("a"); 6209 CharData storage; 6210 6211 CharData_Init(&storage); 6212 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6213 XML_SetUserData(g_parser, &storage); 6214 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6215 == XML_STATUS_ERROR) 6216 xml_failure(g_parser); 6217 CharData_CheckXMLChars(&storage, expected); 6218 } 6219 END_TEST 6220 6221 START_TEST(test_utf16_second_attr) { 6222 /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/> 6223 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6224 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6225 */ 6226 const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0" 6227 "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0"; 6228 const XML_Char *expected = XCS("1"); 6229 CharData storage; 6230 6231 CharData_Init(&storage); 6232 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6233 XML_SetUserData(g_parser, &storage); 6234 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6235 == XML_STATUS_ERROR) 6236 xml_failure(g_parser); 6237 CharData_CheckXMLChars(&storage, expected); 6238 } 6239 END_TEST 6240 6241 START_TEST(test_attr_after_solidus) { 6242 const char *text = "<doc attr1='a' / attr2='b'>"; 6243 6244 expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted"); 6245 } 6246 END_TEST 6247 6248 static void XMLCALL 6249 accumulate_entity_decl(void *userData, const XML_Char *entityName, 6250 int is_parameter_entity, const XML_Char *value, 6251 int value_length, const XML_Char *base, 6252 const XML_Char *systemId, const XML_Char *publicId, 6253 const XML_Char *notationName) { 6254 CharData *storage = (CharData *)userData; 6255 6256 UNUSED_P(is_parameter_entity); 6257 UNUSED_P(base); 6258 UNUSED_P(systemId); 6259 UNUSED_P(publicId); 6260 UNUSED_P(notationName); 6261 CharData_AppendXMLChars(storage, entityName, -1); 6262 CharData_AppendXMLChars(storage, XCS("="), 1); 6263 CharData_AppendXMLChars(storage, value, value_length); 6264 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6265 } 6266 6267 START_TEST(test_utf16_pe) { 6268 /* <!DOCTYPE doc [ 6269 * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'> 6270 * %{KHO KHWAI}{CHO CHAN}; 6271 * ]> 6272 * <doc></doc> 6273 * 6274 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6275 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6276 */ 6277 const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n" 6278 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 " 6279 "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 " 6280 "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n" 6281 "\0%\x0e\x04\x0e\x08\0;\0\n" 6282 "\0]\0>\0\n" 6283 "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>"; 6284 #ifdef XML_UNICODE 6285 const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n"); 6286 #else 6287 const XML_Char *expected 6288 = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n"); 6289 #endif 6290 CharData storage; 6291 6292 CharData_Init(&storage); 6293 XML_SetUserData(g_parser, &storage); 6294 XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl); 6295 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6296 == XML_STATUS_ERROR) 6297 xml_failure(g_parser); 6298 CharData_CheckXMLChars(&storage, expected); 6299 } 6300 END_TEST 6301 6302 /* Test that duff attribute description keywords are rejected */ 6303 START_TEST(test_bad_attr_desc_keyword) { 6304 const char *text = "<!DOCTYPE doc [\n" 6305 " <!ATTLIST doc attr CDATA #!IMPLIED>\n" 6306 "]>\n" 6307 "<doc />"; 6308 6309 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6310 "Bad keyword !IMPLIED not faulted"); 6311 } 6312 END_TEST 6313 6314 /* Test that an invalid attribute description keyword consisting of 6315 * UTF-16 characters with their top bytes non-zero are correctly 6316 * faulted 6317 */ 6318 START_TEST(test_bad_attr_desc_keyword_utf16) { 6319 /* <!DOCTYPE d [ 6320 * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}> 6321 * ]><d/> 6322 * 6323 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 6324 * and {CHO CHAN} = U+0E08 = 0xe0 0xb8 0x88 in UTF-8 6325 */ 6326 const char text[] 6327 = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6328 "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 " 6329 "\0#\x0e\x04\x0e\x08\0>\0\n" 6330 "\0]\0>\0<\0d\0/\0>"; 6331 6332 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6333 != XML_STATUS_ERROR) 6334 fail("Invalid UTF16 attribute keyword not faulted"); 6335 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6336 xml_failure(g_parser); 6337 } 6338 END_TEST 6339 6340 /* Test that invalid syntax in a <!DOCTYPE> is rejected. Do this 6341 * using prefix-encoding (see above) to trigger specific code paths 6342 */ 6343 START_TEST(test_bad_doctype) { 6344 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 6345 "<!DOCTYPE doc [ \x80\x44 ]><doc/>"; 6346 6347 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6348 expect_failure(text, XML_ERROR_SYNTAX, 6349 "Invalid bytes in DOCTYPE not faulted"); 6350 } 6351 END_TEST 6352 6353 START_TEST(test_bad_doctype_utf8) { 6354 const char *text = "<!DOCTYPE \xDB\x25" 6355 "doc><doc/>"; // [1101 1011] [<0>010 0101] 6356 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6357 "Invalid UTF-8 in DOCTYPE not faulted"); 6358 } 6359 END_TEST 6360 6361 START_TEST(test_bad_doctype_utf16) { 6362 const char text[] = 6363 /* <!DOCTYPE doc [ \x06f2 ]><doc/> 6364 * 6365 * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number 6366 * (name character) but not a valid letter (name start character) 6367 */ 6368 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 " 6369 "\x06\xf2" 6370 "\0 \0]\0>\0<\0d\0o\0c\0/\0>"; 6371 6372 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6373 != XML_STATUS_ERROR) 6374 fail("Invalid bytes in DOCTYPE not faulted"); 6375 if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX) 6376 xml_failure(g_parser); 6377 } 6378 END_TEST 6379 6380 START_TEST(test_bad_doctype_plus) { 6381 const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n" 6382 "<1+>&foo;</1+>"; 6383 6384 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6385 "'+' in document name not faulted"); 6386 } 6387 END_TEST 6388 6389 START_TEST(test_bad_doctype_star) { 6390 const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n" 6391 "<1*>&foo;</1*>"; 6392 6393 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6394 "'*' in document name not faulted"); 6395 } 6396 END_TEST 6397 6398 START_TEST(test_bad_doctype_query) { 6399 const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n" 6400 "<1?>&foo;</1?>"; 6401 6402 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6403 "'?' in document name not faulted"); 6404 } 6405 END_TEST 6406 6407 START_TEST(test_unknown_encoding_bad_ignore) { 6408 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>" 6409 "<!DOCTYPE doc SYSTEM 'foo'>" 6410 "<doc><e>&entity;</e></doc>"; 6411 ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>", 6412 "Invalid character not faulted", XCS("prefix-conv"), 6413 XML_ERROR_INVALID_TOKEN}; 6414 6415 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 6416 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6417 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 6418 XML_SetUserData(g_parser, &fault); 6419 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 6420 "Bad IGNORE section with unknown encoding not failed"); 6421 } 6422 END_TEST 6423 6424 START_TEST(test_entity_in_utf16_be_attr) { 6425 const char text[] = 6426 /* <e a='ä ä'></e> */ 6427 "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 " 6428 "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>"; 6429 #ifdef XML_UNICODE 6430 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6431 #else 6432 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6433 #endif 6434 CharData storage; 6435 6436 CharData_Init(&storage); 6437 XML_SetUserData(g_parser, &storage); 6438 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6439 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6440 == XML_STATUS_ERROR) 6441 xml_failure(g_parser); 6442 CharData_CheckXMLChars(&storage, expected); 6443 } 6444 END_TEST 6445 6446 START_TEST(test_entity_in_utf16_le_attr) { 6447 const char text[] = 6448 /* <e a='ä ä'></e> */ 6449 "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0" 6450 "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0"; 6451 #ifdef XML_UNICODE 6452 const XML_Char *expected = XCS("\x00e4 \x00e4"); 6453 #else 6454 const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4"); 6455 #endif 6456 CharData storage; 6457 6458 CharData_Init(&storage); 6459 XML_SetUserData(g_parser, &storage); 6460 XML_SetStartElementHandler(g_parser, accumulate_attribute); 6461 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6462 == XML_STATUS_ERROR) 6463 xml_failure(g_parser); 6464 CharData_CheckXMLChars(&storage, expected); 6465 } 6466 END_TEST 6467 6468 START_TEST(test_entity_public_utf16_be) { 6469 const char text[] = 6470 /* <!DOCTYPE d [ */ 6471 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n" 6472 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6473 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 " 6474 "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n" 6475 /* %e; */ 6476 "\0%\0e\0;\0\n" 6477 /* ]> */ 6478 "\0]\0>\0\n" 6479 /* <d>&j;</d> */ 6480 "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>"; 6481 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6482 "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>", 6483 34, NULL, NULL, EE_PARSE_NONE}; 6484 const XML_Char *expected = XCS("baz"); 6485 CharData storage; 6486 6487 CharData_Init(&storage); 6488 test_data.storage = &storage; 6489 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6490 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6491 XML_SetUserData(g_parser, &test_data); 6492 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6493 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6494 == XML_STATUS_ERROR) 6495 xml_failure(g_parser); 6496 CharData_CheckXMLChars(&storage, expected); 6497 } 6498 END_TEST 6499 6500 START_TEST(test_entity_public_utf16_le) { 6501 const char text[] = 6502 /* <!DOCTYPE d [ */ 6503 "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0" 6504 /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */ 6505 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0" 6506 "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0" 6507 /* %e; */ 6508 "%\0e\0;\0\n\0" 6509 /* ]> */ 6510 "]\0>\0\n\0" 6511 /* <d>&j;</d> */ 6512 "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0"; 6513 ExtTest2 test_data = {/* <!ENTITY j 'baz'> */ 6514 "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0", 6515 34, NULL, NULL, EE_PARSE_NONE}; 6516 const XML_Char *expected = XCS("baz"); 6517 CharData storage; 6518 6519 CharData_Init(&storage); 6520 test_data.storage = &storage; 6521 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6522 XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2); 6523 XML_SetUserData(g_parser, &test_data); 6524 XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters); 6525 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 6526 == XML_STATUS_ERROR) 6527 xml_failure(g_parser); 6528 CharData_CheckXMLChars(&storage, expected); 6529 } 6530 END_TEST 6531 6532 /* Test that a doctype with neither an internal nor external subset is 6533 * faulted 6534 */ 6535 START_TEST(test_short_doctype) { 6536 const char *text = "<!DOCTYPE doc></doc>"; 6537 expect_failure(text, XML_ERROR_INVALID_TOKEN, 6538 "DOCTYPE without subset not rejected"); 6539 } 6540 END_TEST 6541 6542 START_TEST(test_short_doctype_2) { 6543 const char *text = "<!DOCTYPE doc PUBLIC></doc>"; 6544 expect_failure(text, XML_ERROR_SYNTAX, 6545 "DOCTYPE without Public ID not rejected"); 6546 } 6547 END_TEST 6548 6549 START_TEST(test_short_doctype_3) { 6550 const char *text = "<!DOCTYPE doc SYSTEM></doc>"; 6551 expect_failure(text, XML_ERROR_SYNTAX, 6552 "DOCTYPE without System ID not rejected"); 6553 } 6554 END_TEST 6555 6556 START_TEST(test_long_doctype) { 6557 const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>"; 6558 expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected"); 6559 } 6560 END_TEST 6561 6562 START_TEST(test_bad_entity) { 6563 const char *text = "<!DOCTYPE doc [\n" 6564 " <!ENTITY foo PUBLIC>\n" 6565 "]>\n" 6566 "<doc/>"; 6567 expect_failure(text, XML_ERROR_SYNTAX, 6568 "ENTITY without Public ID is not rejected"); 6569 } 6570 END_TEST 6571 6572 /* Test unquoted value is faulted */ 6573 START_TEST(test_bad_entity_2) { 6574 const char *text = "<!DOCTYPE doc [\n" 6575 " <!ENTITY % foo bar>\n" 6576 "]>\n" 6577 "<doc/>"; 6578 expect_failure(text, XML_ERROR_SYNTAX, 6579 "ENTITY without Public ID is not rejected"); 6580 } 6581 END_TEST 6582 6583 START_TEST(test_bad_entity_3) { 6584 const char *text = "<!DOCTYPE doc [\n" 6585 " <!ENTITY % foo PUBLIC>\n" 6586 "]>\n" 6587 "<doc/>"; 6588 expect_failure(text, XML_ERROR_SYNTAX, 6589 "Parameter ENTITY without Public ID is not rejected"); 6590 } 6591 END_TEST 6592 6593 START_TEST(test_bad_entity_4) { 6594 const char *text = "<!DOCTYPE doc [\n" 6595 " <!ENTITY % foo SYSTEM>\n" 6596 "]>\n" 6597 "<doc/>"; 6598 expect_failure(text, XML_ERROR_SYNTAX, 6599 "Parameter ENTITY without Public ID is not rejected"); 6600 } 6601 END_TEST 6602 6603 START_TEST(test_bad_notation) { 6604 const char *text = "<!DOCTYPE doc [\n" 6605 " <!NOTATION n SYSTEM>\n" 6606 "]>\n" 6607 "<doc/>"; 6608 expect_failure(text, XML_ERROR_SYNTAX, 6609 "Notation without System ID is not rejected"); 6610 } 6611 END_TEST 6612 6613 /* Test for issue #11, wrongly suppressed default handler */ 6614 typedef struct default_check { 6615 const XML_Char *expected; 6616 const int expectedLen; 6617 XML_Bool seen; 6618 } DefaultCheck; 6619 6620 static void XMLCALL 6621 checking_default_handler(void *userData, const XML_Char *s, int len) { 6622 DefaultCheck *data = (DefaultCheck *)userData; 6623 int i; 6624 6625 for (i = 0; data[i].expected != NULL; i++) { 6626 if (data[i].expectedLen == len 6627 && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) { 6628 data[i].seen = XML_TRUE; 6629 break; 6630 } 6631 } 6632 } 6633 6634 START_TEST(test_default_doctype_handler) { 6635 const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n" 6636 " <!ENTITY foo 'bar'>\n" 6637 "]>\n" 6638 "<doc>&foo;</doc>"; 6639 DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE}, 6640 {XCS("'test.dtd'"), 10, XML_FALSE}, 6641 {NULL, 0, XML_FALSE}}; 6642 int i; 6643 6644 XML_SetUserData(g_parser, &test_data); 6645 XML_SetDefaultHandler(g_parser, checking_default_handler); 6646 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 6647 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6648 == XML_STATUS_ERROR) 6649 xml_failure(g_parser); 6650 for (i = 0; test_data[i].expected != NULL; i++) 6651 if (! test_data[i].seen) 6652 fail("Default handler not run for public !DOCTYPE"); 6653 } 6654 END_TEST 6655 6656 START_TEST(test_empty_element_abort) { 6657 const char *text = "<abort/>"; 6658 6659 XML_SetStartElementHandler(g_parser, start_element_suspender); 6660 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6661 != XML_STATUS_ERROR) 6662 fail("Expected to error on abort"); 6663 } 6664 END_TEST 6665 6666 /* 6667 * Namespaces tests. 6668 */ 6669 6670 static void 6671 namespace_setup(void) { 6672 g_parser = XML_ParserCreateNS(NULL, XCS(' ')); 6673 if (g_parser == NULL) 6674 fail("Parser not created."); 6675 } 6676 6677 static void 6678 namespace_teardown(void) { 6679 basic_teardown(); 6680 } 6681 6682 /* Check that an element name and attribute name match the expected values. 6683 The expected values are passed as an array reference of string pointers 6684 provided as the userData argument; the first is the expected 6685 element name, and the second is the expected attribute name. 6686 */ 6687 static int triplet_start_flag = XML_FALSE; 6688 static int triplet_end_flag = XML_FALSE; 6689 6690 static void XMLCALL 6691 triplet_start_checker(void *userData, const XML_Char *name, 6692 const XML_Char **atts) { 6693 XML_Char **elemstr = (XML_Char **)userData; 6694 char buffer[1024]; 6695 if (xcstrcmp(elemstr[0], name) != 0) { 6696 sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name); 6697 fail(buffer); 6698 } 6699 if (xcstrcmp(elemstr[1], atts[0]) != 0) { 6700 sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]); 6701 fail(buffer); 6702 } 6703 triplet_start_flag = XML_TRUE; 6704 } 6705 6706 /* Check that the element name passed to the end-element handler matches 6707 the expected value. The expected value is passed as the first element 6708 in an array of strings passed as the userData argument. 6709 */ 6710 static void XMLCALL 6711 triplet_end_checker(void *userData, const XML_Char *name) { 6712 XML_Char **elemstr = (XML_Char **)userData; 6713 if (xcstrcmp(elemstr[0], name) != 0) { 6714 char buffer[1024]; 6715 sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name); 6716 fail(buffer); 6717 } 6718 triplet_end_flag = XML_TRUE; 6719 } 6720 6721 START_TEST(test_return_ns_triplet) { 6722 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 6723 " xmlns:bar='http://example.org/'>"; 6724 const char *epilog = "</foo:e>"; 6725 const XML_Char *elemstr[] 6726 = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")}; 6727 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6728 XML_SetUserData(g_parser, (void *)elemstr); 6729 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 6730 XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler, 6731 dummy_end_namespace_decl_handler); 6732 triplet_start_flag = XML_FALSE; 6733 triplet_end_flag = XML_FALSE; 6734 dummy_handler_flags = 0; 6735 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE) 6736 == XML_STATUS_ERROR) 6737 xml_failure(g_parser); 6738 if (! triplet_start_flag) 6739 fail("triplet_start_checker not invoked"); 6740 /* Check that unsetting "return triplets" fails while still parsing */ 6741 XML_SetReturnNSTriplet(g_parser, XML_FALSE); 6742 if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE) 6743 == XML_STATUS_ERROR) 6744 xml_failure(g_parser); 6745 if (! triplet_end_flag) 6746 fail("triplet_end_checker not invoked"); 6747 if (dummy_handler_flags 6748 != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG)) 6749 fail("Namespace handlers not called"); 6750 } 6751 END_TEST 6752 6753 static void XMLCALL 6754 overwrite_start_checker(void *userData, const XML_Char *name, 6755 const XML_Char **atts) { 6756 CharData *storage = (CharData *)userData; 6757 CharData_AppendXMLChars(storage, XCS("start "), 6); 6758 CharData_AppendXMLChars(storage, name, -1); 6759 while (*atts != NULL) { 6760 CharData_AppendXMLChars(storage, XCS("\nattribute "), 11); 6761 CharData_AppendXMLChars(storage, *atts, -1); 6762 atts += 2; 6763 } 6764 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6765 } 6766 6767 static void XMLCALL 6768 overwrite_end_checker(void *userData, const XML_Char *name) { 6769 CharData *storage = (CharData *)userData; 6770 CharData_AppendXMLChars(storage, XCS("end "), 4); 6771 CharData_AppendXMLChars(storage, name, -1); 6772 CharData_AppendXMLChars(storage, XCS("\n"), 1); 6773 } 6774 6775 static void 6776 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) { 6777 CharData storage; 6778 CharData_Init(&storage); 6779 XML_SetUserData(g_parser, &storage); 6780 XML_SetElementHandler(g_parser, overwrite_start_checker, 6781 overwrite_end_checker); 6782 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6783 == XML_STATUS_ERROR) 6784 xml_failure(g_parser); 6785 CharData_CheckXMLChars(&storage, result); 6786 } 6787 6788 /* Regression test for SF bug #566334. */ 6789 START_TEST(test_ns_tagname_overwrite) { 6790 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6791 " <n:f n:attr='foo'/>\n" 6792 " <n:g n:attr2='bar'/>\n" 6793 "</n:e>"; 6794 const XML_Char *result = XCS("start http://example.org/ e\n") 6795 XCS("start http://example.org/ f\n") 6796 XCS("attribute http://example.org/ attr\n") 6797 XCS("end http://example.org/ f\n") 6798 XCS("start http://example.org/ g\n") 6799 XCS("attribute http://example.org/ attr2\n") 6800 XCS("end http://example.org/ g\n") 6801 XCS("end http://example.org/ e\n"); 6802 run_ns_tagname_overwrite_test(text, result); 6803 } 6804 END_TEST 6805 6806 /* Regression test for SF bug #566334. */ 6807 START_TEST(test_ns_tagname_overwrite_triplet) { 6808 const char *text = "<n:e xmlns:n='http://example.org/'>\n" 6809 " <n:f n:attr='foo'/>\n" 6810 " <n:g n:attr2='bar'/>\n" 6811 "</n:e>"; 6812 const XML_Char *result = XCS("start http://example.org/ e n\n") 6813 XCS("start http://example.org/ f n\n") 6814 XCS("attribute http://example.org/ attr n\n") 6815 XCS("end http://example.org/ f n\n") 6816 XCS("start http://example.org/ g n\n") 6817 XCS("attribute http://example.org/ attr2 n\n") 6818 XCS("end http://example.org/ g n\n") 6819 XCS("end http://example.org/ e n\n"); 6820 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6821 run_ns_tagname_overwrite_test(text, result); 6822 } 6823 END_TEST 6824 6825 /* Regression test for SF bug #620343. */ 6826 static void XMLCALL 6827 start_element_fail(void *userData, const XML_Char *name, 6828 const XML_Char **atts) { 6829 UNUSED_P(userData); 6830 UNUSED_P(name); 6831 UNUSED_P(atts); 6832 6833 /* We should never get here. */ 6834 fail("should never reach start_element_fail()"); 6835 } 6836 6837 static void XMLCALL 6838 start_ns_clearing_start_element(void *userData, const XML_Char *prefix, 6839 const XML_Char *uri) { 6840 UNUSED_P(prefix); 6841 UNUSED_P(uri); 6842 XML_SetStartElementHandler((XML_Parser)userData, NULL); 6843 } 6844 6845 START_TEST(test_start_ns_clears_start_element) { 6846 /* This needs to use separate start/end tags; using the empty tag 6847 syntax doesn't cause the problematic path through Expat to be 6848 taken. 6849 */ 6850 const char *text = "<e xmlns='http://example.org/'></e>"; 6851 6852 XML_SetStartElementHandler(g_parser, start_element_fail); 6853 XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element); 6854 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 6855 XML_UseParserAsHandlerArg(g_parser); 6856 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6857 == XML_STATUS_ERROR) 6858 xml_failure(g_parser); 6859 } 6860 END_TEST 6861 6862 /* Regression test for SF bug #616863. */ 6863 static int XMLCALL 6864 external_entity_handler(XML_Parser parser, const XML_Char *context, 6865 const XML_Char *base, const XML_Char *systemId, 6866 const XML_Char *publicId) { 6867 intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser); 6868 const char *text; 6869 XML_Parser p2; 6870 6871 UNUSED_P(base); 6872 UNUSED_P(systemId); 6873 UNUSED_P(publicId); 6874 if (callno == 1) 6875 text = ("<!ELEMENT doc (e+)>\n" 6876 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 6877 "<!ELEMENT e EMPTY>\n"); 6878 else 6879 text = ("<?xml version='1.0' encoding='us-ascii'?>" 6880 "<e/>"); 6881 6882 XML_SetUserData(parser, (void *)callno); 6883 p2 = XML_ExternalEntityParserCreate(parser, context, NULL); 6884 if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE) 6885 == XML_STATUS_ERROR) { 6886 xml_failure(p2); 6887 return XML_STATUS_ERROR; 6888 } 6889 XML_ParserFree(p2); 6890 return XML_STATUS_OK; 6891 } 6892 6893 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) { 6894 const char *text = "<?xml version='1.0'?>\n" 6895 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 6896 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 6897 "]>\n" 6898 "<doc xmlns='http://example.org/ns1'>\n" 6899 "&en;\n" 6900 "</doc>"; 6901 6902 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 6903 XML_SetExternalEntityRefHandler(g_parser, external_entity_handler); 6904 /* We actually need to set this handler to tickle this bug. */ 6905 XML_SetStartElementHandler(g_parser, dummy_start_element); 6906 XML_SetUserData(g_parser, NULL); 6907 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6908 == XML_STATUS_ERROR) 6909 xml_failure(g_parser); 6910 } 6911 END_TEST 6912 6913 /* Regression test #1 for SF bug #673791. */ 6914 START_TEST(test_ns_prefix_with_empty_uri_1) { 6915 const char *text = "<doc xmlns:prefix='http://example.org/'>\n" 6916 " <e xmlns:prefix=''/>\n" 6917 "</doc>"; 6918 6919 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6920 "Did not report re-setting namespace" 6921 " URI with prefix to ''."); 6922 } 6923 END_TEST 6924 6925 /* Regression test #2 for SF bug #673791. */ 6926 START_TEST(test_ns_prefix_with_empty_uri_2) { 6927 const char *text = "<?xml version='1.0'?>\n" 6928 "<docelem xmlns:pre=''/>"; 6929 6930 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6931 "Did not report setting namespace URI with prefix to ''."); 6932 } 6933 END_TEST 6934 6935 /* Regression test #3 for SF bug #673791. */ 6936 START_TEST(test_ns_prefix_with_empty_uri_3) { 6937 const char *text = "<!DOCTYPE doc [\n" 6938 " <!ELEMENT doc EMPTY>\n" 6939 " <!ATTLIST doc\n" 6940 " xmlns:prefix CDATA ''>\n" 6941 "]>\n" 6942 "<doc/>"; 6943 6944 expect_failure(text, XML_ERROR_UNDECLARING_PREFIX, 6945 "Didn't report attr default setting NS w/ prefix to ''."); 6946 } 6947 END_TEST 6948 6949 /* Regression test #4 for SF bug #673791. */ 6950 START_TEST(test_ns_prefix_with_empty_uri_4) { 6951 const char *text = "<!DOCTYPE doc [\n" 6952 " <!ELEMENT prefix:doc EMPTY>\n" 6953 " <!ATTLIST prefix:doc\n" 6954 " xmlns:prefix CDATA 'http://example.org/'>\n" 6955 "]>\n" 6956 "<prefix:doc/>"; 6957 /* Packaged info expected by the end element handler; 6958 the weird structuring lets us re-use the triplet_end_checker() 6959 function also used for another test. */ 6960 const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")}; 6961 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 6962 XML_SetUserData(g_parser, (void *)elemstr); 6963 XML_SetEndElementHandler(g_parser, triplet_end_checker); 6964 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6965 == XML_STATUS_ERROR) 6966 xml_failure(g_parser); 6967 } 6968 END_TEST 6969 6970 /* Test with non-xmlns prefix */ 6971 START_TEST(test_ns_unbound_prefix) { 6972 const char *text = "<!DOCTYPE doc [\n" 6973 " <!ELEMENT prefix:doc EMPTY>\n" 6974 " <!ATTLIST prefix:doc\n" 6975 " notxmlns:prefix CDATA 'http://example.org/'>\n" 6976 "]>\n" 6977 "<prefix:doc/>"; 6978 6979 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6980 != XML_STATUS_ERROR) 6981 fail("Unbound prefix incorrectly passed"); 6982 if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX) 6983 xml_failure(g_parser); 6984 } 6985 END_TEST 6986 6987 START_TEST(test_ns_default_with_empty_uri) { 6988 const char *text = "<doc xmlns='http://example.org/'>\n" 6989 " <e xmlns=''/>\n" 6990 "</doc>"; 6991 /* Add some handlers to exercise extra code paths */ 6992 XML_SetStartNamespaceDeclHandler(g_parser, 6993 dummy_start_namespace_decl_handler); 6994 XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler); 6995 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 6996 == XML_STATUS_ERROR) 6997 xml_failure(g_parser); 6998 } 6999 END_TEST 7000 7001 /* Regression test for SF bug #692964: two prefixes for one namespace. */ 7002 START_TEST(test_ns_duplicate_attrs_diff_prefixes) { 7003 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7004 " xmlns:b='http://example.org/a'\n" 7005 " a:a='v' b:a='v' />"; 7006 expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE, 7007 "did not report multiple attributes with same URI+name"); 7008 } 7009 END_TEST 7010 7011 START_TEST(test_ns_duplicate_hashes) { 7012 /* The hash of an attribute is calculated as the hash of its URI 7013 * concatenated with a space followed by its name (after the 7014 * colon). We wish to generate attributes with the same hash 7015 * value modulo the attribute table size so that we can check that 7016 * the attribute hash table works correctly. The attribute hash 7017 * table size will be the smallest power of two greater than the 7018 * number of attributes, but at least eight. There is 7019 * unfortunately no programmatic way of getting the hash or the 7020 * table size at user level, but the test code coverage percentage 7021 * will drop if the hashes cease to point to the same row. 7022 * 7023 * The cunning plan is to have few enough attributes to have a 7024 * reliable table size of 8, and have the single letter attribute 7025 * names be 8 characters apart, producing a hash which will be the 7026 * same modulo 8. 7027 */ 7028 const char *text = "<doc xmlns:a='http://example.org/a'\n" 7029 " a:a='v' a:i='w' />"; 7030 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7031 == XML_STATUS_ERROR) 7032 xml_failure(g_parser); 7033 } 7034 END_TEST 7035 7036 /* Regression test for SF bug #695401: unbound prefix. */ 7037 START_TEST(test_ns_unbound_prefix_on_attribute) { 7038 const char *text = "<doc a:attr=''/>"; 7039 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7040 "did not report unbound prefix on attribute"); 7041 } 7042 END_TEST 7043 7044 /* Regression test for SF bug #695401: unbound prefix. */ 7045 START_TEST(test_ns_unbound_prefix_on_element) { 7046 const char *text = "<a:doc/>"; 7047 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, 7048 "did not report unbound prefix on element"); 7049 } 7050 END_TEST 7051 7052 /* Test that the parsing status is correctly reset by XML_ParserReset(). 7053 * We usE test_return_ns_triplet() for our example parse to improve 7054 * coverage of tidying up code executed. 7055 */ 7056 START_TEST(test_ns_parser_reset) { 7057 XML_ParsingStatus status; 7058 7059 XML_GetParsingStatus(g_parser, &status); 7060 if (status.parsing != XML_INITIALIZED) 7061 fail("parsing status doesn't start INITIALIZED"); 7062 test_return_ns_triplet(); 7063 XML_GetParsingStatus(g_parser, &status); 7064 if (status.parsing != XML_FINISHED) 7065 fail("parsing status doesn't end FINISHED"); 7066 XML_ParserReset(g_parser, NULL); 7067 XML_GetParsingStatus(g_parser, &status); 7068 if (status.parsing != XML_INITIALIZED) 7069 fail("parsing status doesn't reset to INITIALIZED"); 7070 } 7071 END_TEST 7072 7073 /* Test that long element names with namespaces are handled correctly */ 7074 START_TEST(test_ns_long_element) { 7075 const char *text 7076 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 7077 " xmlns:foo='http://example.org/' bar:a='12'\n" 7078 " xmlns:bar='http://example.org/'>" 7079 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 7080 const XML_Char *elemstr[] 7081 = {XCS("http://example.org/") 7082 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 7083 XCS("http://example.org/ a bar")}; 7084 7085 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 7086 XML_SetUserData(g_parser, (void *)elemstr); 7087 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 7088 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7089 == XML_STATUS_ERROR) 7090 xml_failure(g_parser); 7091 } 7092 END_TEST 7093 7094 /* Test mixed population of prefixed and unprefixed attributes */ 7095 START_TEST(test_ns_mixed_prefix_atts) { 7096 const char *text = "<e a='12' bar:b='13'\n" 7097 " xmlns:bar='http://example.org/'>" 7098 "</e>"; 7099 7100 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7101 == XML_STATUS_ERROR) 7102 xml_failure(g_parser); 7103 } 7104 END_TEST 7105 7106 /* Test having a long namespaced element name inside a short one. 7107 * This exercises some internal buffer reallocation that is shared 7108 * across elements with the same namespace URI. 7109 */ 7110 START_TEST(test_ns_extend_uri_buffer) { 7111 const char *text = "<foo:e xmlns:foo='http://example.org/'>" 7112 " <foo:thisisalongenoughnametotriggerallocationaction" 7113 " foo:a='12' />" 7114 "</foo:e>"; 7115 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7116 == XML_STATUS_ERROR) 7117 xml_failure(g_parser); 7118 } 7119 END_TEST 7120 7121 /* Test that xmlns is correctly rejected as an attribute in the xmlns 7122 * namespace, but not in other namespaces 7123 */ 7124 START_TEST(test_ns_reserved_attributes) { 7125 const char *text1 7126 = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />"; 7127 const char *text2 7128 = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />"; 7129 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS, 7130 "xmlns not rejected as an attribute"); 7131 XML_ParserReset(g_parser, NULL); 7132 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7133 == XML_STATUS_ERROR) 7134 xml_failure(g_parser); 7135 } 7136 END_TEST 7137 7138 /* Test more reserved attributes */ 7139 START_TEST(test_ns_reserved_attributes_2) { 7140 const char *text1 = "<foo:e xmlns:foo='http://example.org/'" 7141 " xmlns:xml='http://example.org/' />"; 7142 const char *text2 7143 = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />"; 7144 const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />"; 7145 7146 expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML, 7147 "xml not rejected as an attribute"); 7148 XML_ParserReset(g_parser, NULL); 7149 expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI, 7150 "Use of w3.org URL not faulted"); 7151 XML_ParserReset(g_parser, NULL); 7152 expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI, 7153 "Use of w3.org xmlns URL not faulted"); 7154 } 7155 END_TEST 7156 7157 /* Test string pool handling of namespace names of 2048 characters */ 7158 /* Exercises a particular string pool growth path */ 7159 START_TEST(test_ns_extremely_long_prefix) { 7160 /* C99 compilers are only required to support 4095-character 7161 * strings, so the following needs to be split in two to be safe 7162 * for all compilers. 7163 */ 7164 const char *text1 7165 = "<doc " 7166 /* 64 character on each line */ 7167 /* ...gives a total length of 2048 */ 7168 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7169 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7170 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7171 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7172 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7173 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7174 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7175 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7176 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7177 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7178 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7179 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7180 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7181 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7182 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7183 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7184 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7185 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7186 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7187 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7188 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7189 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7190 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7191 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7192 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7193 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7194 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7195 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7196 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7197 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7198 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7199 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7200 ":a='12'"; 7201 const char *text2 7202 = " xmlns:" 7203 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7204 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7205 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7206 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7207 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7208 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7209 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7210 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7211 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7212 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7213 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7214 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7215 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7216 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7217 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7218 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7219 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7220 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7221 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7222 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7223 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7224 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7225 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7226 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7227 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7228 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7229 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7230 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7231 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7232 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7233 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7234 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7235 "='foo'\n>" 7236 "</doc>"; 7237 7238 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 7239 == XML_STATUS_ERROR) 7240 xml_failure(g_parser); 7241 if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE) 7242 == XML_STATUS_ERROR) 7243 xml_failure(g_parser); 7244 } 7245 END_TEST 7246 7247 /* Test unknown encoding handlers in namespace setup */ 7248 START_TEST(test_ns_unknown_encoding_success) { 7249 const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n" 7250 "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>"; 7251 7252 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7253 run_character_check(text, XCS("Hi")); 7254 } 7255 END_TEST 7256 7257 /* Test that too many colons are rejected */ 7258 START_TEST(test_ns_double_colon) { 7259 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />"; 7260 const enum XML_Status status 7261 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7262 #ifdef XML_NS 7263 if ((status == XML_STATUS_OK) 7264 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7265 fail("Double colon in attribute name not faulted" 7266 " (despite active namespace support)"); 7267 } 7268 #else 7269 if (status != XML_STATUS_OK) { 7270 fail("Double colon in attribute name faulted" 7271 " (despite inactive namespace support"); 7272 } 7273 #endif 7274 } 7275 END_TEST 7276 7277 START_TEST(test_ns_double_colon_element) { 7278 const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />"; 7279 const enum XML_Status status 7280 = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE); 7281 #ifdef XML_NS 7282 if ((status == XML_STATUS_OK) 7283 || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) { 7284 fail("Double colon in element name not faulted" 7285 " (despite active namespace support)"); 7286 } 7287 #else 7288 if (status != XML_STATUS_OK) { 7289 fail("Double colon in element name faulted" 7290 " (despite inactive namespace support"); 7291 } 7292 #endif 7293 } 7294 END_TEST 7295 7296 /* Test that non-name characters after a colon are rejected */ 7297 START_TEST(test_ns_bad_attr_leafname) { 7298 const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />"; 7299 7300 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7301 "Invalid character in leafname not faulted"); 7302 } 7303 END_TEST 7304 7305 START_TEST(test_ns_bad_element_leafname) { 7306 const char *text = "<foo:?oc xmlns:foo='http://example.org/' />"; 7307 7308 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7309 "Invalid character in element leafname not faulted"); 7310 } 7311 END_TEST 7312 7313 /* Test high-byte-set UTF-16 characters are valid in a leafname */ 7314 START_TEST(test_ns_utf16_leafname) { 7315 const char text[] = 7316 /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' /> 7317 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7318 */ 7319 "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0" 7320 "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0"; 7321 const XML_Char *expected = XCS("a"); 7322 CharData storage; 7323 7324 CharData_Init(&storage); 7325 XML_SetStartElementHandler(g_parser, accumulate_attribute); 7326 XML_SetUserData(g_parser, &storage); 7327 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7328 == XML_STATUS_ERROR) 7329 xml_failure(g_parser); 7330 CharData_CheckXMLChars(&storage, expected); 7331 } 7332 END_TEST 7333 7334 START_TEST(test_ns_utf16_element_leafname) { 7335 const char text[] = 7336 /* <n:{KHO KHWAI} xmlns:n='URI'/> 7337 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7338 */ 7339 "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>"; 7340 #ifdef XML_UNICODE 7341 const XML_Char *expected = XCS("URI \x0e04"); 7342 #else 7343 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7344 #endif 7345 CharData storage; 7346 7347 CharData_Init(&storage); 7348 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7349 XML_SetUserData(g_parser, &storage); 7350 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7351 == XML_STATUS_ERROR) 7352 xml_failure(g_parser); 7353 CharData_CheckXMLChars(&storage, expected); 7354 } 7355 END_TEST 7356 7357 START_TEST(test_ns_utf16_doctype) { 7358 const char text[] = 7359 /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n 7360 * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8 7361 */ 7362 "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 " 7363 "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 " 7364 "\0]\0>\0\n" 7365 /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */ 7366 "\0<\0f\0o\0o\0:\x0e\x04\0 " 7367 "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>" 7368 "\0&\0b\0a\0r\0;" 7369 "\0<\0/\0f\0o\0o\0:\x0e\x04\0>"; 7370 #ifdef XML_UNICODE 7371 const XML_Char *expected = XCS("URI \x0e04"); 7372 #else 7373 const XML_Char *expected = XCS("URI \xe0\xb8\x84"); 7374 #endif 7375 CharData storage; 7376 7377 CharData_Init(&storage); 7378 XML_SetUserData(g_parser, &storage); 7379 XML_SetStartElementHandler(g_parser, start_element_event_handler); 7380 XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL); 7381 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7382 == XML_STATUS_ERROR) 7383 xml_failure(g_parser); 7384 CharData_CheckXMLChars(&storage, expected); 7385 } 7386 END_TEST 7387 7388 START_TEST(test_ns_invalid_doctype) { 7389 const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n" 7390 "<foo:!bad>&bar;</foo:!bad>"; 7391 7392 expect_failure(text, XML_ERROR_INVALID_TOKEN, 7393 "Invalid character in document local name not faulted"); 7394 } 7395 END_TEST 7396 7397 START_TEST(test_ns_double_colon_doctype) { 7398 const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n" 7399 "<foo:a:doc>&bar;</foo:a:doc>"; 7400 7401 expect_failure(text, XML_ERROR_SYNTAX, 7402 "Double colon in document name not faulted"); 7403 } 7404 END_TEST 7405 7406 START_TEST(test_ns_separator_in_uri) { 7407 struct test_case { 7408 enum XML_Status expectedStatus; 7409 const char *doc; 7410 }; 7411 struct test_case cases[] = { 7412 {XML_STATUS_OK, "<doc xmlns='one_two' />"}, 7413 {XML_STATUS_ERROR, "<doc xmlns='one
two' />"}, 7414 }; 7415 7416 size_t i = 0; 7417 size_t failCount = 0; 7418 for (; i < sizeof(cases) / sizeof(cases[0]); i++) { 7419 XML_Parser parser = XML_ParserCreateNS(NULL, '\n'); 7420 XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); 7421 if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), 7422 /*isFinal*/ XML_TRUE) 7423 != cases[i].expectedStatus) { 7424 failCount++; 7425 } 7426 XML_ParserFree(parser); 7427 } 7428 7429 if (failCount) { 7430 fail("Namespace separator handling is broken"); 7431 } 7432 } 7433 END_TEST 7434 7435 /* Control variable; the number of times duff_allocator() will successfully 7436 * allocate */ 7437 #define ALLOC_ALWAYS_SUCCEED (-1) 7438 #define REALLOC_ALWAYS_SUCCEED (-1) 7439 7440 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED; 7441 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED; 7442 7443 /* Crocked allocator for allocation failure tests */ 7444 static void * 7445 duff_allocator(size_t size) { 7446 if (allocation_count == 0) 7447 return NULL; 7448 if (allocation_count != ALLOC_ALWAYS_SUCCEED) 7449 allocation_count--; 7450 return malloc(size); 7451 } 7452 7453 /* Crocked reallocator for allocation failure tests */ 7454 static void * 7455 duff_reallocator(void *ptr, size_t size) { 7456 if (reallocation_count == 0) 7457 return NULL; 7458 if (reallocation_count != REALLOC_ALWAYS_SUCCEED) 7459 reallocation_count--; 7460 return realloc(ptr, size); 7461 } 7462 7463 /* Test that a failure to allocate the parser structure fails gracefully */ 7464 START_TEST(test_misc_alloc_create_parser) { 7465 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7466 unsigned int i; 7467 const unsigned int max_alloc_count = 10; 7468 7469 /* Something this simple shouldn't need more than 10 allocations */ 7470 for (i = 0; i < max_alloc_count; i++) { 7471 allocation_count = i; 7472 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7473 if (g_parser != NULL) 7474 break; 7475 } 7476 if (i == 0) 7477 fail("Parser unexpectedly ignored failing allocator"); 7478 else if (i == max_alloc_count) 7479 fail("Parser not created with max allocation count"); 7480 } 7481 END_TEST 7482 7483 /* Test memory allocation failures for a parser with an encoding */ 7484 START_TEST(test_misc_alloc_create_parser_with_encoding) { 7485 XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free}; 7486 unsigned int i; 7487 const unsigned int max_alloc_count = 10; 7488 7489 /* Try several levels of allocation */ 7490 for (i = 0; i < max_alloc_count; i++) { 7491 allocation_count = i; 7492 g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL); 7493 if (g_parser != NULL) 7494 break; 7495 } 7496 if (i == 0) 7497 fail("Parser ignored failing allocator"); 7498 else if (i == max_alloc_count) 7499 fail("Parser not created with max allocation count"); 7500 } 7501 END_TEST 7502 7503 /* Test that freeing a NULL parser doesn't cause an explosion. 7504 * (Not actually tested anywhere else) 7505 */ 7506 START_TEST(test_misc_null_parser) { 7507 XML_ParserFree(NULL); 7508 } 7509 END_TEST 7510 7511 /* Test that XML_ErrorString rejects out-of-range codes */ 7512 START_TEST(test_misc_error_string) { 7513 if (XML_ErrorString((enum XML_Error) - 1) != NULL) 7514 fail("Negative error code not rejected"); 7515 if (XML_ErrorString((enum XML_Error)100) != NULL) 7516 fail("Large error code not rejected"); 7517 } 7518 END_TEST 7519 7520 /* Test the version information is consistent */ 7521 7522 /* Since we are working in XML_LChars (potentially 16-bits), we 7523 * can't use the standard C library functions for character 7524 * manipulation and have to roll our own. 7525 */ 7526 static int 7527 parse_version(const XML_LChar *version_text, 7528 XML_Expat_Version *version_struct) { 7529 if (! version_text) 7530 return XML_FALSE; 7531 7532 while (*version_text != 0x00) { 7533 if (*version_text >= ASCII_0 && *version_text <= ASCII_9) 7534 break; 7535 version_text++; 7536 } 7537 if (*version_text == 0x00) 7538 return XML_FALSE; 7539 7540 /* version_struct->major = strtoul(version_text, 10, &version_text) */ 7541 version_struct->major = 0; 7542 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7543 version_struct->major 7544 = 10 * version_struct->major + (*version_text++ - ASCII_0); 7545 } 7546 if (*version_text++ != ASCII_PERIOD) 7547 return XML_FALSE; 7548 7549 /* Now for the minor version number */ 7550 version_struct->minor = 0; 7551 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7552 version_struct->minor 7553 = 10 * version_struct->minor + (*version_text++ - ASCII_0); 7554 } 7555 if (*version_text++ != ASCII_PERIOD) 7556 return XML_FALSE; 7557 7558 /* Finally the micro version number */ 7559 version_struct->micro = 0; 7560 while (*version_text >= ASCII_0 && *version_text <= ASCII_9) { 7561 version_struct->micro 7562 = 10 * version_struct->micro + (*version_text++ - ASCII_0); 7563 } 7564 if (*version_text != 0x00) 7565 return XML_FALSE; 7566 return XML_TRUE; 7567 } 7568 7569 static int 7570 versions_equal(const XML_Expat_Version *first, 7571 const XML_Expat_Version *second) { 7572 return (first->major == second->major && first->minor == second->minor 7573 && first->micro == second->micro); 7574 } 7575 7576 START_TEST(test_misc_version) { 7577 XML_Expat_Version read_version = XML_ExpatVersionInfo(); 7578 /* Silence compiler warning with the following assignment */ 7579 XML_Expat_Version parsed_version = {0, 0, 0}; 7580 const XML_LChar *version_text = XML_ExpatVersion(); 7581 7582 if (version_text == NULL) 7583 fail("Could not obtain version text"); 7584 assert(version_text != NULL); 7585 if (! parse_version(version_text, &parsed_version)) 7586 fail("Unable to parse version text"); 7587 if (! versions_equal(&read_version, &parsed_version)) 7588 fail("Version mismatch"); 7589 7590 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) 7591 if (xcstrcmp(version_text, XCS("expat_2.4.6"))) /* needs bump on releases */ 7592 fail("XML_*_VERSION in expat.h out of sync?\n"); 7593 #else 7594 /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T 7595 * then XML_LChar is defined as char, for some reason. 7596 */ 7597 if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */ 7598 fail("XML_*_VERSION in expat.h out of sync?\n"); 7599 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */ 7600 } 7601 END_TEST 7602 7603 /* Test feature information */ 7604 START_TEST(test_misc_features) { 7605 const XML_Feature *features = XML_GetFeatureList(); 7606 7607 /* Prevent problems with double-freeing parsers */ 7608 g_parser = NULL; 7609 if (features == NULL) { 7610 fail("Failed to get feature information"); 7611 } else { 7612 /* Loop through the features checking what we can */ 7613 while (features->feature != XML_FEATURE_END) { 7614 switch (features->feature) { 7615 case XML_FEATURE_SIZEOF_XML_CHAR: 7616 if (features->value != sizeof(XML_Char)) 7617 fail("Incorrect size of XML_Char"); 7618 break; 7619 case XML_FEATURE_SIZEOF_XML_LCHAR: 7620 if (features->value != sizeof(XML_LChar)) 7621 fail("Incorrect size of XML_LChar"); 7622 break; 7623 default: 7624 break; 7625 } 7626 features++; 7627 } 7628 } 7629 } 7630 END_TEST 7631 7632 /* Regression test for GitHub Issue #17: memory leak parsing attribute 7633 * values with mixed bound and unbound namespaces. 7634 */ 7635 START_TEST(test_misc_attribute_leak) { 7636 const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>"; 7637 XML_Memory_Handling_Suite memsuite 7638 = {tracking_malloc, tracking_realloc, tracking_free}; 7639 7640 g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n")); 7641 expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found"); 7642 XML_ParserFree(g_parser); 7643 /* Prevent the teardown trying to double free */ 7644 g_parser = NULL; 7645 7646 if (! tracking_report()) 7647 fail("Memory leak found"); 7648 } 7649 END_TEST 7650 7651 /* Test parser created for UTF-16LE is successful */ 7652 START_TEST(test_misc_utf16le) { 7653 const char text[] = 7654 /* <?xml version='1.0'?><q>Hi</q> */ 7655 "<\0?\0x\0m\0l\0 \0" 7656 "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0" 7657 "<\0q\0>\0H\0i\0<\0/\0q\0>\0"; 7658 const XML_Char *expected = XCS("Hi"); 7659 CharData storage; 7660 7661 g_parser = XML_ParserCreate(XCS("UTF-16LE")); 7662 if (g_parser == NULL) 7663 fail("Parser not created"); 7664 7665 CharData_Init(&storage); 7666 XML_SetUserData(g_parser, &storage); 7667 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 7668 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE) 7669 == XML_STATUS_ERROR) 7670 xml_failure(g_parser); 7671 CharData_CheckXMLChars(&storage, expected); 7672 } 7673 END_TEST 7674 7675 typedef struct { 7676 XML_Parser parser; 7677 int deep; 7678 } DataIssue240; 7679 7680 static void 7681 start_element_issue_240(void *userData, const XML_Char *name, 7682 const XML_Char **atts) { 7683 DataIssue240 *mydata = (DataIssue240 *)userData; 7684 UNUSED_P(name); 7685 UNUSED_P(atts); 7686 mydata->deep++; 7687 } 7688 7689 static void 7690 end_element_issue_240(void *userData, const XML_Char *name) { 7691 DataIssue240 *mydata = (DataIssue240 *)userData; 7692 7693 UNUSED_P(name); 7694 mydata->deep--; 7695 if (mydata->deep == 0) { 7696 XML_StopParser(mydata->parser, 0); 7697 } 7698 } 7699 7700 START_TEST(test_misc_stop_during_end_handler_issue_240_1) { 7701 XML_Parser parser; 7702 DataIssue240 *mydata; 7703 enum XML_Status result; 7704 const char *const doc1 = "<doc><e1/><e><foo/></e></doc>"; 7705 7706 parser = XML_ParserCreate(NULL); 7707 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7708 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7709 mydata->parser = parser; 7710 mydata->deep = 0; 7711 XML_SetUserData(parser, mydata); 7712 7713 result = XML_Parse(parser, doc1, (int)strlen(doc1), 1); 7714 XML_ParserFree(parser); 7715 free(mydata); 7716 if (result != XML_STATUS_ERROR) 7717 fail("Stopping the parser did not work as expected"); 7718 } 7719 END_TEST 7720 7721 START_TEST(test_misc_stop_during_end_handler_issue_240_2) { 7722 XML_Parser parser; 7723 DataIssue240 *mydata; 7724 enum XML_Status result; 7725 const char *const doc2 = "<doc><elem/></doc>"; 7726 7727 parser = XML_ParserCreate(NULL); 7728 XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240); 7729 mydata = (DataIssue240 *)malloc(sizeof(DataIssue240)); 7730 mydata->parser = parser; 7731 mydata->deep = 0; 7732 XML_SetUserData(parser, mydata); 7733 7734 result = XML_Parse(parser, doc2, (int)strlen(doc2), 1); 7735 XML_ParserFree(parser); 7736 free(mydata); 7737 if (result != XML_STATUS_ERROR) 7738 fail("Stopping the parser did not work as expected"); 7739 } 7740 END_TEST 7741 7742 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) { 7743 const char *const inputOne = "<!DOCTYPE d [\n" 7744 "<!ENTITY % e ']><d/>'>\n" 7745 "\n" 7746 "%e;"; 7747 const char *const inputTwo = "<!DOCTYPE d [\n" 7748 "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n" 7749 "\n" 7750 "%e2;"; 7751 const char *const inputThree = "<!DOCTYPE d [\n" 7752 "<!ENTITY % e ']><d'>\n" 7753 "\n" 7754 "%e;"; 7755 const char *const inputIssue317 = "<!DOCTYPE doc [\n" 7756 "<!ENTITY % foo ']>\n" 7757 "<doc>Hell<oc (#PCDATA)*>'>\n" 7758 "%foo;\n" 7759 "]>\n" 7760 "<doc>Hello, world</dVc>"; 7761 7762 const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317}; 7763 size_t inputIndex = 0; 7764 7765 for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) { 7766 XML_Parser parser; 7767 enum XML_Status parseResult; 7768 int setParamEntityResult; 7769 XML_Size lineNumber; 7770 XML_Size columnNumber; 7771 const char *const input = inputs[inputIndex]; 7772 7773 parser = XML_ParserCreate(NULL); 7774 setParamEntityResult 7775 = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 7776 if (setParamEntityResult != 1) 7777 fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS."); 7778 7779 parseResult = XML_Parse(parser, input, (int)strlen(input), 0); 7780 if (parseResult != XML_STATUS_ERROR) { 7781 parseResult = XML_Parse(parser, "", 0, 1); 7782 if (parseResult != XML_STATUS_ERROR) { 7783 fail("Parsing was expected to fail but succeeded."); 7784 } 7785 } 7786 7787 if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN) 7788 fail("Error code does not match XML_ERROR_INVALID_TOKEN"); 7789 7790 lineNumber = XML_GetCurrentLineNumber(parser); 7791 if (lineNumber != 4) 7792 fail("XML_GetCurrentLineNumber does not work as expected."); 7793 7794 columnNumber = XML_GetCurrentColumnNumber(parser); 7795 if (columnNumber != 0) 7796 fail("XML_GetCurrentColumnNumber does not work as expected."); 7797 7798 XML_ParserFree(parser); 7799 } 7800 } 7801 END_TEST 7802 7803 static void 7804 alloc_setup(void) { 7805 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 7806 7807 /* Ensure the parser creation will go through */ 7808 allocation_count = ALLOC_ALWAYS_SUCCEED; 7809 reallocation_count = REALLOC_ALWAYS_SUCCEED; 7810 g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); 7811 if (g_parser == NULL) 7812 fail("Parser not created"); 7813 } 7814 7815 static void 7816 alloc_teardown(void) { 7817 basic_teardown(); 7818 } 7819 7820 /* Test the effects of allocation failures on xml declaration processing */ 7821 START_TEST(test_alloc_parse_xdecl) { 7822 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7823 "<doc>Hello, world</doc>"; 7824 int i; 7825 const int max_alloc_count = 15; 7826 7827 for (i = 0; i < max_alloc_count; i++) { 7828 allocation_count = i; 7829 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7830 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7831 != XML_STATUS_ERROR) 7832 break; 7833 /* Resetting the parser is insufficient, because some memory 7834 * allocations are cached within the parser. Instead we use 7835 * the teardown and setup routines to ensure that we have the 7836 * right sort of parser back in our hands. 7837 */ 7838 alloc_teardown(); 7839 alloc_setup(); 7840 } 7841 if (i == 0) 7842 fail("Parse succeeded despite failing allocator"); 7843 if (i == max_alloc_count) 7844 fail("Parse failed with max allocations"); 7845 } 7846 END_TEST 7847 7848 /* As above, but with an encoding big enough to cause storing the 7849 * version information to expand the string pool being used. 7850 */ 7851 static int XMLCALL 7852 long_encoding_handler(void *userData, const XML_Char *encoding, 7853 XML_Encoding *info) { 7854 int i; 7855 7856 UNUSED_P(userData); 7857 UNUSED_P(encoding); 7858 for (i = 0; i < 256; i++) 7859 info->map[i] = i; 7860 info->data = NULL; 7861 info->convert = NULL; 7862 info->release = NULL; 7863 return XML_STATUS_OK; 7864 } 7865 7866 START_TEST(test_alloc_parse_xdecl_2) { 7867 const char *text 7868 = "<?xml version='1.0' encoding='" 7869 /* Each line is 64 characters */ 7870 "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456" 7871 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7872 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7873 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7874 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7875 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7876 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7877 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7878 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7879 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7880 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7881 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7882 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7883 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7884 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7885 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN" 7886 "'?>" 7887 "<doc>Hello, world</doc>"; 7888 int i; 7889 const int max_alloc_count = 20; 7890 7891 for (i = 0; i < max_alloc_count; i++) { 7892 allocation_count = i; 7893 XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); 7894 XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL); 7895 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7896 != XML_STATUS_ERROR) 7897 break; 7898 /* See comment in test_alloc_parse_xdecl() */ 7899 alloc_teardown(); 7900 alloc_setup(); 7901 } 7902 if (i == 0) 7903 fail("Parse succeeded despite failing allocator"); 7904 if (i == max_alloc_count) 7905 fail("Parse failed with max allocations"); 7906 } 7907 END_TEST 7908 7909 /* Test the effects of allocation failures on a straightforward parse */ 7910 START_TEST(test_alloc_parse_pi) { 7911 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7912 "<?pi unknown?>\n" 7913 "<doc>" 7914 "Hello, world" 7915 "</doc>"; 7916 int i; 7917 const int max_alloc_count = 15; 7918 7919 for (i = 0; i < max_alloc_count; i++) { 7920 allocation_count = i; 7921 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7922 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7923 != XML_STATUS_ERROR) 7924 break; 7925 /* See comment in test_alloc_parse_xdecl() */ 7926 alloc_teardown(); 7927 alloc_setup(); 7928 } 7929 if (i == 0) 7930 fail("Parse succeeded despite failing allocator"); 7931 if (i == max_alloc_count) 7932 fail("Parse failed with max allocations"); 7933 } 7934 END_TEST 7935 7936 START_TEST(test_alloc_parse_pi_2) { 7937 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 7938 "<doc>" 7939 "Hello, world" 7940 "<?pi unknown?>\n" 7941 "</doc>"; 7942 int i; 7943 const int max_alloc_count = 15; 7944 7945 for (i = 0; i < max_alloc_count; i++) { 7946 allocation_count = i; 7947 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7948 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7949 != XML_STATUS_ERROR) 7950 break; 7951 /* See comment in test_alloc_parse_xdecl() */ 7952 alloc_teardown(); 7953 alloc_setup(); 7954 } 7955 if (i == 0) 7956 fail("Parse succeeded despite failing allocator"); 7957 if (i == max_alloc_count) 7958 fail("Parse failed with max allocations"); 7959 } 7960 END_TEST 7961 7962 START_TEST(test_alloc_parse_pi_3) { 7963 const char *text 7964 = "<?" 7965 /* 64 characters per line */ 7966 "This processing instruction should be long enough to ensure that" 7967 "it triggers the growth of an internal string pool when the " 7968 "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP" 7969 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7970 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7971 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7972 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7973 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7974 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7975 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7976 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7977 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7978 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7979 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7980 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7981 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 7982 "Q?><doc/>"; 7983 int i; 7984 const int max_alloc_count = 20; 7985 7986 for (i = 0; i < max_alloc_count; i++) { 7987 allocation_count = i; 7988 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 7989 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 7990 != XML_STATUS_ERROR) 7991 break; 7992 /* See comment in test_alloc_parse_xdecl() */ 7993 alloc_teardown(); 7994 alloc_setup(); 7995 } 7996 if (i == 0) 7997 fail("Parse succeeded despite failing allocator"); 7998 if (i == max_alloc_count) 7999 fail("Parse failed with max allocations"); 8000 } 8001 END_TEST 8002 8003 START_TEST(test_alloc_parse_comment) { 8004 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8005 "<!-- Test parsing this comment -->" 8006 "<doc>Hi</doc>"; 8007 int i; 8008 const int max_alloc_count = 15; 8009 8010 for (i = 0; i < max_alloc_count; i++) { 8011 allocation_count = i; 8012 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8013 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8014 != XML_STATUS_ERROR) 8015 break; 8016 /* See comment in test_alloc_parse_xdecl() */ 8017 alloc_teardown(); 8018 alloc_setup(); 8019 } 8020 if (i == 0) 8021 fail("Parse succeeded despite failing allocator"); 8022 if (i == max_alloc_count) 8023 fail("Parse failed with max allocations"); 8024 } 8025 END_TEST 8026 8027 START_TEST(test_alloc_parse_comment_2) { 8028 const char *text = "<?xml version='1.0' encoding='utf-8'?>\n" 8029 "<doc>" 8030 "Hello, world" 8031 "<!-- Parse this comment too -->" 8032 "</doc>"; 8033 int i; 8034 const int max_alloc_count = 15; 8035 8036 for (i = 0; i < max_alloc_count; i++) { 8037 allocation_count = i; 8038 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8039 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8040 != XML_STATUS_ERROR) 8041 break; 8042 /* See comment in test_alloc_parse_xdecl() */ 8043 alloc_teardown(); 8044 alloc_setup(); 8045 } 8046 if (i == 0) 8047 fail("Parse succeeded despite failing allocator"); 8048 if (i == max_alloc_count) 8049 fail("Parse failed with max allocations"); 8050 } 8051 END_TEST 8052 8053 static int XMLCALL 8054 external_entity_duff_loader(XML_Parser parser, const XML_Char *context, 8055 const XML_Char *base, const XML_Char *systemId, 8056 const XML_Char *publicId) { 8057 XML_Parser new_parser; 8058 unsigned int i; 8059 const unsigned int max_alloc_count = 10; 8060 8061 UNUSED_P(base); 8062 UNUSED_P(systemId); 8063 UNUSED_P(publicId); 8064 /* Try a few different allocation levels */ 8065 for (i = 0; i < max_alloc_count; i++) { 8066 allocation_count = i; 8067 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8068 if (new_parser != NULL) { 8069 XML_ParserFree(new_parser); 8070 break; 8071 } 8072 } 8073 if (i == 0) 8074 fail("External parser creation ignored failing allocator"); 8075 else if (i == max_alloc_count) 8076 fail("Extern parser not created with max allocation count"); 8077 8078 /* Make sure other random allocation doesn't now fail */ 8079 allocation_count = ALLOC_ALWAYS_SUCCEED; 8080 8081 /* Make sure the failure code path is executed too */ 8082 return XML_STATUS_ERROR; 8083 } 8084 8085 /* Test that external parser creation running out of memory is 8086 * correctly reported. Based on the external entity test cases. 8087 */ 8088 START_TEST(test_alloc_create_external_parser) { 8089 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8090 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8091 "<doc>&entity;</doc>"; 8092 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8093 8094 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8095 XML_SetUserData(g_parser, foo_text); 8096 XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader); 8097 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8098 != XML_STATUS_ERROR) { 8099 fail("External parser allocator returned success incorrectly"); 8100 } 8101 } 8102 END_TEST 8103 8104 /* More external parser memory allocation testing */ 8105 START_TEST(test_alloc_run_external_parser) { 8106 const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n" 8107 "<!DOCTYPE doc SYSTEM 'foo'>\n" 8108 "<doc>&entity;</doc>"; 8109 char foo_text[] = "<!ELEMENT doc (#PCDATA)*>"; 8110 unsigned int i; 8111 const unsigned int max_alloc_count = 15; 8112 8113 for (i = 0; i < max_alloc_count; i++) { 8114 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8115 XML_SetUserData(g_parser, foo_text); 8116 XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); 8117 allocation_count = i; 8118 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8119 != XML_STATUS_ERROR) 8120 break; 8121 /* See comment in test_alloc_parse_xdecl() */ 8122 alloc_teardown(); 8123 alloc_setup(); 8124 } 8125 if (i == 0) 8126 fail("Parsing ignored failing allocator"); 8127 else if (i == max_alloc_count) 8128 fail("Parsing failed with allocation count 10"); 8129 } 8130 END_TEST 8131 8132 static int XMLCALL 8133 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context, 8134 const XML_Char *base, const XML_Char *systemId, 8135 const XML_Char *publicId) { 8136 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8137 const char *text; 8138 XML_Parser new_parser; 8139 int i; 8140 const int max_alloc_count = 20; 8141 8142 UNUSED_P(base); 8143 UNUSED_P(systemId); 8144 UNUSED_P(publicId); 8145 if (callno == 0) { 8146 /* First time through, check how many calls to malloc occur */ 8147 text = ("<!ELEMENT doc (e+)>\n" 8148 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8149 "<!ELEMENT e EMPTY>\n"); 8150 allocation_count = 10000; 8151 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8152 if (new_parser == NULL) { 8153 fail("Unable to allocate first external parser"); 8154 return XML_STATUS_ERROR; 8155 } 8156 /* Stash the number of calls in the user data */ 8157 XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count)); 8158 } else { 8159 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8160 "<e/>"); 8161 /* Try at varying levels to exercise more code paths */ 8162 for (i = 0; i < max_alloc_count; i++) { 8163 allocation_count = callno + i; 8164 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8165 if (new_parser != NULL) 8166 break; 8167 } 8168 if (i == 0) { 8169 fail("Second external parser unexpectedly created"); 8170 XML_ParserFree(new_parser); 8171 return XML_STATUS_ERROR; 8172 } else if (i == max_alloc_count) { 8173 fail("Second external parser not created"); 8174 return XML_STATUS_ERROR; 8175 } 8176 } 8177 8178 allocation_count = ALLOC_ALWAYS_SUCCEED; 8179 if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE) 8180 == XML_STATUS_ERROR) { 8181 xml_failure(new_parser); 8182 return XML_STATUS_ERROR; 8183 } 8184 XML_ParserFree(new_parser); 8185 return XML_STATUS_OK; 8186 } 8187 8188 /* Test that running out of memory in dtdCopy is correctly reported. 8189 * Based on test_default_ns_from_ext_subset_and_ext_ge() 8190 */ 8191 START_TEST(test_alloc_dtd_copy_default_atts) { 8192 const char *text = "<?xml version='1.0'?>\n" 8193 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8194 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8195 "]>\n" 8196 "<doc xmlns='http://example.org/ns1'>\n" 8197 "&en;\n" 8198 "</doc>"; 8199 8200 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8201 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler); 8202 XML_SetUserData(g_parser, NULL); 8203 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8204 == XML_STATUS_ERROR) 8205 xml_failure(g_parser); 8206 } 8207 END_TEST 8208 8209 static int XMLCALL 8210 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context, 8211 const XML_Char *base, const XML_Char *systemId, 8212 const XML_Char *publicId) { 8213 intptr_t callno = (intptr_t)XML_GetUserData(parser); 8214 const char *text; 8215 XML_Parser new_parser; 8216 enum XML_Status rv; 8217 8218 UNUSED_P(base); 8219 UNUSED_P(systemId); 8220 UNUSED_P(publicId); 8221 if (callno == 0) { 8222 /* Try different allocation levels for whole exercise */ 8223 text = ("<!ELEMENT doc (e+)>\n" 8224 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n" 8225 "<!ELEMENT e EMPTY>\n"); 8226 XML_SetUserData(parser, (void *)(intptr_t)1); 8227 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8228 if (new_parser == NULL) 8229 return XML_STATUS_ERROR; 8230 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8231 } else { 8232 /* Just run through once */ 8233 text = ("<?xml version='1.0' encoding='us-ascii'?>" 8234 "<e/>"); 8235 new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8236 if (new_parser == NULL) 8237 return XML_STATUS_ERROR; 8238 rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE); 8239 } 8240 XML_ParserFree(new_parser); 8241 if (rv == XML_STATUS_ERROR) 8242 return XML_STATUS_ERROR; 8243 return XML_STATUS_OK; 8244 } 8245 8246 /* Test more external entity allocation failure paths */ 8247 START_TEST(test_alloc_external_entity) { 8248 const char *text = "<?xml version='1.0'?>\n" 8249 "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n" 8250 " <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n" 8251 "]>\n" 8252 "<doc xmlns='http://example.org/ns1'>\n" 8253 "&en;\n" 8254 "</doc>"; 8255 int i; 8256 const int alloc_test_max_repeats = 50; 8257 8258 for (i = 0; i < alloc_test_max_repeats; i++) { 8259 allocation_count = -1; 8260 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8261 XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2); 8262 XML_SetUserData(g_parser, NULL); 8263 allocation_count = i; 8264 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8265 == XML_STATUS_OK) 8266 break; 8267 /* See comment in test_alloc_parse_xdecl() */ 8268 alloc_teardown(); 8269 alloc_setup(); 8270 } 8271 allocation_count = -1; 8272 if (i == 0) 8273 fail("External entity parsed despite duff allocator"); 8274 if (i == alloc_test_max_repeats) 8275 fail("External entity not parsed at max allocation count"); 8276 } 8277 END_TEST 8278 8279 /* Test more allocation failure paths */ 8280 static int XMLCALL 8281 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context, 8282 const XML_Char *base, 8283 const XML_Char *systemId, 8284 const XML_Char *publicId) { 8285 /* As for external_entity_loader() */ 8286 const char *text = "<?xml encoding='iso-8859-3'?>" 8287 "\xC3\xA9"; 8288 XML_Parser ext_parser; 8289 enum XML_Status status; 8290 8291 UNUSED_P(base); 8292 UNUSED_P(systemId); 8293 UNUSED_P(publicId); 8294 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8295 if (ext_parser == NULL) 8296 return XML_STATUS_ERROR; 8297 if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) { 8298 XML_ParserFree(ext_parser); 8299 return XML_STATUS_ERROR; 8300 } 8301 status 8302 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8303 XML_ParserFree(ext_parser); 8304 if (status == XML_STATUS_ERROR) 8305 return XML_STATUS_ERROR; 8306 return XML_STATUS_OK; 8307 } 8308 8309 START_TEST(test_alloc_ext_entity_set_encoding) { 8310 const char *text = "<!DOCTYPE doc [\n" 8311 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8312 "]>\n" 8313 "<doc>&en;</doc>"; 8314 int i; 8315 const int max_allocation_count = 30; 8316 8317 for (i = 0; i < max_allocation_count; i++) { 8318 XML_SetExternalEntityRefHandler(g_parser, 8319 external_entity_alloc_set_encoding); 8320 allocation_count = i; 8321 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8322 == XML_STATUS_OK) 8323 break; 8324 allocation_count = -1; 8325 /* See comment in test_alloc_parse_xdecl() */ 8326 alloc_teardown(); 8327 alloc_setup(); 8328 } 8329 if (i == 0) 8330 fail("Encoding check succeeded despite failing allocator"); 8331 if (i == max_allocation_count) 8332 fail("Encoding failed at max allocation count"); 8333 } 8334 END_TEST 8335 8336 static int XMLCALL 8337 unknown_released_encoding_handler(void *data, const XML_Char *encoding, 8338 XML_Encoding *info) { 8339 UNUSED_P(data); 8340 if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) { 8341 int i; 8342 8343 for (i = 0; i < 256; i++) 8344 info->map[i] = i; 8345 info->data = NULL; 8346 info->convert = NULL; 8347 info->release = dummy_release; 8348 return XML_STATUS_OK; 8349 } 8350 return XML_STATUS_ERROR; 8351 } 8352 8353 /* Test the effects of allocation failure in internal entities. 8354 * Based on test_unknown_encoding_internal_entity 8355 */ 8356 START_TEST(test_alloc_internal_entity) { 8357 const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n" 8358 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n" 8359 "<test a='&foo;'/>"; 8360 unsigned int i; 8361 const unsigned int max_alloc_count = 20; 8362 8363 for (i = 0; i < max_alloc_count; i++) { 8364 allocation_count = i; 8365 XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, 8366 NULL); 8367 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8368 != XML_STATUS_ERROR) 8369 break; 8370 /* See comment in test_alloc_parse_xdecl() */ 8371 alloc_teardown(); 8372 alloc_setup(); 8373 } 8374 if (i == 0) 8375 fail("Internal entity worked despite failing allocations"); 8376 else if (i == max_alloc_count) 8377 fail("Internal entity failed at max allocation count"); 8378 } 8379 END_TEST 8380 8381 /* Test the robustness against allocation failure of element handling 8382 * Based on test_dtd_default_handling(). 8383 */ 8384 START_TEST(test_alloc_dtd_default_handling) { 8385 const char *text = "<!DOCTYPE doc [\n" 8386 "<!ENTITY e SYSTEM 'http://example.org/e'>\n" 8387 "<!NOTATION n SYSTEM 'http://example.org/n'>\n" 8388 "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n" 8389 "<!ELEMENT doc (#PCDATA)>\n" 8390 "<!ATTLIST doc a CDATA #IMPLIED>\n" 8391 "<?pi in dtd?>\n" 8392 "<!--comment in dtd-->\n" 8393 "]>\n" 8394 "<doc><![CDATA[text in doc]]></doc>"; 8395 const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>"); 8396 CharData storage; 8397 int i; 8398 const int max_alloc_count = 25; 8399 8400 for (i = 0; i < max_alloc_count; i++) { 8401 allocation_count = i; 8402 dummy_handler_flags = 0; 8403 XML_SetDefaultHandler(g_parser, accumulate_characters); 8404 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, 8405 dummy_end_doctype_handler); 8406 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8407 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 8408 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 8409 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8410 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 8411 XML_SetCommentHandler(g_parser, dummy_comment_handler); 8412 XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler, 8413 dummy_end_cdata_handler); 8414 XML_SetUnparsedEntityDeclHandler(g_parser, 8415 dummy_unparsed_entity_decl_handler); 8416 CharData_Init(&storage); 8417 XML_SetUserData(g_parser, &storage); 8418 XML_SetCharacterDataHandler(g_parser, accumulate_characters); 8419 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8420 != XML_STATUS_ERROR) 8421 break; 8422 /* See comment in test_alloc_parse_xdecl() */ 8423 alloc_teardown(); 8424 alloc_setup(); 8425 } 8426 if (i == 0) 8427 fail("Default DTD parsed despite allocation failures"); 8428 if (i == max_alloc_count) 8429 fail("Default DTD not parsed with maximum alloc count"); 8430 CharData_CheckXMLChars(&storage, expected); 8431 if (dummy_handler_flags 8432 != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG 8433 | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG 8434 | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG 8435 | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG 8436 | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG 8437 | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG)) 8438 fail("Not all handlers were called"); 8439 } 8440 END_TEST 8441 8442 /* Test robustness of XML_SetEncoding() with a failing allocator */ 8443 START_TEST(test_alloc_explicit_encoding) { 8444 int i; 8445 const int max_alloc_count = 5; 8446 8447 for (i = 0; i < max_alloc_count; i++) { 8448 allocation_count = i; 8449 if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK) 8450 break; 8451 } 8452 if (i == 0) 8453 fail("Encoding set despite failing allocator"); 8454 else if (i == max_alloc_count) 8455 fail("Encoding not set at max allocation count"); 8456 } 8457 END_TEST 8458 8459 /* Test robustness of XML_SetBase against a failing allocator */ 8460 START_TEST(test_alloc_set_base) { 8461 const XML_Char *new_base = XCS("/local/file/name.xml"); 8462 int i; 8463 const int max_alloc_count = 5; 8464 8465 for (i = 0; i < max_alloc_count; i++) { 8466 allocation_count = i; 8467 if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK) 8468 break; 8469 } 8470 if (i == 0) 8471 fail("Base set despite failing allocator"); 8472 else if (i == max_alloc_count) 8473 fail("Base not set with max allocation count"); 8474 } 8475 END_TEST 8476 8477 /* Test buffer extension in the face of a duff reallocator */ 8478 START_TEST(test_alloc_realloc_buffer) { 8479 const char *text = get_buffer_test_text; 8480 void *buffer; 8481 int i; 8482 const int max_realloc_count = 10; 8483 8484 /* Get a smallish buffer */ 8485 for (i = 0; i < max_realloc_count; i++) { 8486 reallocation_count = i; 8487 buffer = XML_GetBuffer(g_parser, 1536); 8488 if (buffer == NULL) 8489 fail("1.5K buffer reallocation failed"); 8490 assert(buffer != NULL); 8491 memcpy(buffer, text, strlen(text)); 8492 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) 8493 == XML_STATUS_OK) 8494 break; 8495 /* See comment in test_alloc_parse_xdecl() */ 8496 alloc_teardown(); 8497 alloc_setup(); 8498 } 8499 reallocation_count = -1; 8500 if (i == 0) 8501 fail("Parse succeeded with no reallocation"); 8502 else if (i == max_realloc_count) 8503 fail("Parse failed with max reallocation count"); 8504 } 8505 END_TEST 8506 8507 /* Same test for external entity parsers */ 8508 static int XMLCALL 8509 external_entity_reallocator(XML_Parser parser, const XML_Char *context, 8510 const XML_Char *base, const XML_Char *systemId, 8511 const XML_Char *publicId) { 8512 const char *text = get_buffer_test_text; 8513 XML_Parser ext_parser; 8514 void *buffer; 8515 enum XML_Status status; 8516 8517 UNUSED_P(base); 8518 UNUSED_P(systemId); 8519 UNUSED_P(publicId); 8520 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8521 if (ext_parser == NULL) 8522 fail("Could not create external entity parser"); 8523 8524 reallocation_count = (intptr_t)XML_GetUserData(parser); 8525 buffer = XML_GetBuffer(ext_parser, 1536); 8526 if (buffer == NULL) 8527 fail("Buffer allocation failed"); 8528 assert(buffer != NULL); 8529 memcpy(buffer, text, strlen(text)); 8530 status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE); 8531 reallocation_count = -1; 8532 XML_ParserFree(ext_parser); 8533 return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR; 8534 } 8535 8536 START_TEST(test_alloc_ext_entity_realloc_buffer) { 8537 const char *text = "<!DOCTYPE doc [\n" 8538 " <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n" 8539 "]>\n" 8540 "<doc>&en;</doc>"; 8541 int i; 8542 const int max_realloc_count = 10; 8543 8544 for (i = 0; i < max_realloc_count; i++) { 8545 XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator); 8546 XML_SetUserData(g_parser, (void *)(intptr_t)i); 8547 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8548 == XML_STATUS_OK) 8549 break; 8550 /* See comment in test_alloc_parse_xdecl() */ 8551 alloc_teardown(); 8552 alloc_setup(); 8553 } 8554 if (i == 0) 8555 fail("Succeeded with no reallocations"); 8556 if (i == max_realloc_count) 8557 fail("Failed with max reallocations"); 8558 } 8559 END_TEST 8560 8561 /* Test elements with many attributes are handled correctly */ 8562 START_TEST(test_alloc_realloc_many_attributes) { 8563 const char *text = "<!DOCTYPE doc [\n" 8564 "<!ATTLIST doc za CDATA 'default'>\n" 8565 "<!ATTLIST doc zb CDATA 'def2'>\n" 8566 "<!ATTLIST doc zc CDATA 'def3'>\n" 8567 "]>\n" 8568 "<doc a='1'" 8569 " b='2'" 8570 " c='3'" 8571 " d='4'" 8572 " e='5'" 8573 " f='6'" 8574 " g='7'" 8575 " h='8'" 8576 " i='9'" 8577 " j='10'" 8578 " k='11'" 8579 " l='12'" 8580 " m='13'" 8581 " n='14'" 8582 " p='15'" 8583 " q='16'" 8584 " r='17'" 8585 " s='18'>" 8586 "</doc>"; 8587 int i; 8588 const int max_realloc_count = 10; 8589 8590 for (i = 0; i < max_realloc_count; i++) { 8591 reallocation_count = i; 8592 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8593 != XML_STATUS_ERROR) 8594 break; 8595 /* See comment in test_alloc_parse_xdecl() */ 8596 alloc_teardown(); 8597 alloc_setup(); 8598 } 8599 if (i == 0) 8600 fail("Parse succeeded despite no reallocations"); 8601 if (i == max_realloc_count) 8602 fail("Parse failed at max reallocations"); 8603 } 8604 END_TEST 8605 8606 /* Test handling of a public entity with failing allocator */ 8607 START_TEST(test_alloc_public_entity_value) { 8608 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8609 "<doc></doc>\n"; 8610 char dtd_text[] 8611 = "<!ELEMENT doc EMPTY>\n" 8612 "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n" 8613 "<!ENTITY % " 8614 /* Each line is 64 characters */ 8615 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8616 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8620 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8621 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8623 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8624 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8625 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8626 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8627 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8628 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8629 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8630 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8631 " '%e1;'>\n" 8632 "%e1;\n"; 8633 int i; 8634 const int max_alloc_count = 50; 8635 8636 for (i = 0; i < max_alloc_count; i++) { 8637 allocation_count = i; 8638 dummy_handler_flags = 0; 8639 XML_SetUserData(g_parser, dtd_text); 8640 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8641 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8642 /* Provoke a particular code path */ 8643 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 8644 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8645 != XML_STATUS_ERROR) 8646 break; 8647 /* See comment in test_alloc_parse_xdecl() */ 8648 alloc_teardown(); 8649 alloc_setup(); 8650 } 8651 if (i == 0) 8652 fail("Parsing worked despite failing allocation"); 8653 if (i == max_alloc_count) 8654 fail("Parsing failed at max allocation count"); 8655 if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG) 8656 fail("Entity declaration handler not called"); 8657 } 8658 END_TEST 8659 8660 START_TEST(test_alloc_realloc_subst_public_entity_value) { 8661 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 8662 "<doc></doc>\n"; 8663 char dtd_text[] 8664 = "<!ELEMENT doc EMPTY>\n" 8665 "<!ENTITY % " 8666 /* Each line is 64 characters */ 8667 "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8668 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8669 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8670 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8671 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8672 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8673 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8674 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8675 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8676 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8677 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8678 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8679 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8680 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8681 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8682 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8683 " PUBLIC 'foo' 'bar.ent'>\n" 8684 "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" 8685 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8686 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8687 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8688 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8689 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8690 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8691 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8692 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8693 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8694 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8695 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8696 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8697 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8698 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 8699 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;"; 8700 int i; 8701 const int max_realloc_count = 10; 8702 8703 for (i = 0; i < max_realloc_count; i++) { 8704 reallocation_count = i; 8705 XML_SetUserData(g_parser, dtd_text); 8706 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8707 XML_SetExternalEntityRefHandler(g_parser, external_entity_public); 8708 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8709 != XML_STATUS_ERROR) 8710 break; 8711 /* See comment in test_alloc_parse_xdecl() */ 8712 alloc_teardown(); 8713 alloc_setup(); 8714 } 8715 if (i == 0) 8716 fail("Parsing worked despite failing reallocation"); 8717 if (i == max_realloc_count) 8718 fail("Parsing failed at max reallocation count"); 8719 } 8720 END_TEST 8721 8722 START_TEST(test_alloc_parse_public_doctype) { 8723 const char *text 8724 = "<?xml version='1.0' encoding='utf-8'?>\n" 8725 "<!DOCTYPE doc PUBLIC '" 8726 /* 64 characters per line */ 8727 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 8728 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8729 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8730 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8731 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8732 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8733 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8734 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8735 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8736 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8737 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8738 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8739 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8740 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8741 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8742 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 8743 "' 'test'>\n" 8744 "<doc></doc>"; 8745 int i; 8746 const int max_alloc_count = 25; 8747 8748 for (i = 0; i < max_alloc_count; i++) { 8749 allocation_count = i; 8750 dummy_handler_flags = 0; 8751 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8752 dummy_end_doctype_decl_handler); 8753 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8754 != XML_STATUS_ERROR) 8755 break; 8756 /* See comment in test_alloc_parse_xdecl() */ 8757 alloc_teardown(); 8758 alloc_setup(); 8759 } 8760 if (i == 0) 8761 fail("Parse succeeded despite failing allocator"); 8762 if (i == max_alloc_count) 8763 fail("Parse failed at maximum allocation count"); 8764 if (dummy_handler_flags 8765 != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG 8766 | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG)) 8767 fail("Doctype handler functions not called"); 8768 } 8769 END_TEST 8770 8771 START_TEST(test_alloc_parse_public_doctype_long_name) { 8772 const char *text 8773 = "<?xml version='1.0' encoding='utf-8'?>\n" 8774 "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '" 8775 /* 64 characters per line */ 8776 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8777 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8778 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8779 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8780 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8781 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8782 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8783 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8784 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8785 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8786 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8787 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8788 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8789 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8790 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8791 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 8792 "'>\n" 8793 "<doc></doc>"; 8794 int i; 8795 const int max_alloc_count = 25; 8796 8797 for (i = 0; i < max_alloc_count; i++) { 8798 allocation_count = i; 8799 XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, 8800 dummy_end_doctype_decl_handler); 8801 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8802 != XML_STATUS_ERROR) 8803 break; 8804 /* See comment in test_alloc_parse_xdecl() */ 8805 alloc_teardown(); 8806 alloc_setup(); 8807 } 8808 if (i == 0) 8809 fail("Parse succeeded despite failing allocator"); 8810 if (i == max_alloc_count) 8811 fail("Parse failed at maximum allocation count"); 8812 } 8813 END_TEST 8814 8815 static int XMLCALL 8816 external_entity_alloc(XML_Parser parser, const XML_Char *context, 8817 const XML_Char *base, const XML_Char *systemId, 8818 const XML_Char *publicId) { 8819 const char *text = (const char *)XML_GetUserData(parser); 8820 XML_Parser ext_parser; 8821 int parse_res; 8822 8823 UNUSED_P(base); 8824 UNUSED_P(systemId); 8825 UNUSED_P(publicId); 8826 ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); 8827 if (ext_parser == NULL) 8828 return XML_STATUS_ERROR; 8829 parse_res 8830 = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE); 8831 XML_ParserFree(ext_parser); 8832 return parse_res; 8833 } 8834 8835 /* Test foreign DTD handling */ 8836 START_TEST(test_alloc_set_foreign_dtd) { 8837 const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n" 8838 "<doc>&entity;</doc>"; 8839 char text2[] = "<!ELEMENT doc (#PCDATA)*>"; 8840 int i; 8841 const int max_alloc_count = 25; 8842 8843 for (i = 0; i < max_alloc_count; i++) { 8844 allocation_count = i; 8845 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8846 XML_SetUserData(g_parser, &text2); 8847 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8848 if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) 8849 fail("Could not set foreign DTD"); 8850 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE) 8851 != XML_STATUS_ERROR) 8852 break; 8853 /* See comment in test_alloc_parse_xdecl() */ 8854 alloc_teardown(); 8855 alloc_setup(); 8856 } 8857 if (i == 0) 8858 fail("Parse succeeded despite failing allocator"); 8859 if (i == max_alloc_count) 8860 fail("Parse failed at maximum allocation count"); 8861 } 8862 END_TEST 8863 8864 /* Test based on ibm/valid/P32/ibm32v04.xml */ 8865 START_TEST(test_alloc_attribute_enum_value) { 8866 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8867 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8868 "<animal>This is a \n <a/> \n\nyellow tiger</animal>"; 8869 char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n" 8870 "<!ELEMENT a EMPTY>\n" 8871 "<!ATTLIST animal xml:space (default|preserve) 'preserve'>"; 8872 int i; 8873 const int max_alloc_count = 30; 8874 8875 for (i = 0; i < max_alloc_count; i++) { 8876 allocation_count = i; 8877 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8878 XML_SetUserData(g_parser, dtd_text); 8879 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8880 /* An attribute list handler provokes a different code path */ 8881 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8882 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8883 != XML_STATUS_ERROR) 8884 break; 8885 /* See comment in test_alloc_parse_xdecl() */ 8886 alloc_teardown(); 8887 alloc_setup(); 8888 } 8889 if (i == 0) 8890 fail("Parse succeeded despite failing allocator"); 8891 if (i == max_alloc_count) 8892 fail("Parse failed at maximum allocation count"); 8893 } 8894 END_TEST 8895 8896 /* Test attribute enums sufficient to overflow the string pool */ 8897 START_TEST(test_alloc_realloc_attribute_enum_value) { 8898 const char *text = "<?xml version='1.0' standalone='no'?>\n" 8899 "<!DOCTYPE animal SYSTEM 'test.dtd'>\n" 8900 "<animal>This is a yellow tiger</animal>"; 8901 /* We wish to define a collection of attribute enums that will 8902 * cause the string pool storing them to have to expand. This 8903 * means more than 1024 bytes, including the parentheses and 8904 * separator bars. 8905 */ 8906 char dtd_text[] 8907 = "<!ELEMENT animal (#PCDATA)*>\n" 8908 "<!ATTLIST animal thing " 8909 "(default" 8910 /* Each line is 64 characters */ 8911 "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8912 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8913 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8914 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8915 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8916 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8917 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8918 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8919 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8920 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8921 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8922 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8923 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8924 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8925 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8926 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)" 8927 " 'default'>"; 8928 int i; 8929 const int max_realloc_count = 10; 8930 8931 for (i = 0; i < max_realloc_count; i++) { 8932 reallocation_count = i; 8933 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 8934 XML_SetUserData(g_parser, dtd_text); 8935 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 8936 /* An attribute list handler provokes a different code path */ 8937 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8938 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8939 != XML_STATUS_ERROR) 8940 break; 8941 /* See comment in test_alloc_parse_xdecl() */ 8942 alloc_teardown(); 8943 alloc_setup(); 8944 } 8945 if (i == 0) 8946 fail("Parse succeeded despite failing reallocator"); 8947 if (i == max_realloc_count) 8948 fail("Parse failed at maximum reallocation count"); 8949 } 8950 END_TEST 8951 8952 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */ 8953 START_TEST(test_alloc_realloc_implied_attribute) { 8954 /* Forcing this particular code path is a balancing act. The 8955 * addition of the closing parenthesis and terminal NUL must be 8956 * what pushes the string of enums over the 1024-byte limit, 8957 * otherwise a different code path will pick up the realloc. 8958 */ 8959 const char *text 8960 = "<!DOCTYPE doc [\n" 8961 "<!ELEMENT doc EMPTY>\n" 8962 "<!ATTLIST doc a " 8963 /* Each line is 64 characters */ 8964 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8965 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8966 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8967 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8968 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8969 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8970 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8971 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8972 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8973 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8974 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8975 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8976 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8977 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8978 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 8979 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 8980 " #IMPLIED>\n" 8981 "]><doc/>"; 8982 int i; 8983 const int max_realloc_count = 10; 8984 8985 for (i = 0; i < max_realloc_count; i++) { 8986 reallocation_count = i; 8987 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 8988 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 8989 != XML_STATUS_ERROR) 8990 break; 8991 /* See comment in test_alloc_parse_xdecl() */ 8992 alloc_teardown(); 8993 alloc_setup(); 8994 } 8995 if (i == 0) 8996 fail("Parse succeeded despite failing reallocator"); 8997 if (i == max_realloc_count) 8998 fail("Parse failed at maximum reallocation count"); 8999 } 9000 END_TEST 9001 9002 /* Test attribute enums in a defaulted attribute forcing pool growth */ 9003 START_TEST(test_alloc_realloc_default_attribute) { 9004 /* Forcing this particular code path is a balancing act. The 9005 * addition of the closing parenthesis and terminal NUL must be 9006 * what pushes the string of enums over the 1024-byte limit, 9007 * otherwise a different code path will pick up the realloc. 9008 */ 9009 const char *text 9010 = "<!DOCTYPE doc [\n" 9011 "<!ELEMENT doc EMPTY>\n" 9012 "<!ATTLIST doc a " 9013 /* Each line is 64 characters */ 9014 "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9015 "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9016 "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9017 "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9018 "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9019 "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9020 "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9021 "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9022 "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9023 "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9024 "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9025 "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9026 "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9027 "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9028 "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO" 9029 "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)" 9030 " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'" 9031 ">\n]><doc/>"; 9032 int i; 9033 const int max_realloc_count = 10; 9034 9035 for (i = 0; i < max_realloc_count; i++) { 9036 reallocation_count = i; 9037 XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); 9038 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9039 != XML_STATUS_ERROR) 9040 break; 9041 /* See comment in test_alloc_parse_xdecl() */ 9042 alloc_teardown(); 9043 alloc_setup(); 9044 } 9045 if (i == 0) 9046 fail("Parse succeeded despite failing reallocator"); 9047 if (i == max_realloc_count) 9048 fail("Parse failed at maximum reallocation count"); 9049 } 9050 END_TEST 9051 9052 /* Test long notation name with dodgy allocator */ 9053 START_TEST(test_alloc_notation) { 9054 const char *text 9055 = "<!DOCTYPE doc [\n" 9056 "<!NOTATION " 9057 /* Each line is 64 characters */ 9058 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9059 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9060 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9061 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9062 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9063 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9064 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9065 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9066 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9067 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9068 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9069 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9070 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9071 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9072 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9073 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9074 " SYSTEM 'http://example.org/n'>\n" 9075 "<!ENTITY e SYSTEM 'http://example.org/e' NDATA " 9076 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9077 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9078 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9079 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9080 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9081 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9082 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9083 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9084 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9085 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9086 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9087 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9088 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9089 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9090 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9091 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9092 ">\n" 9093 "<!ELEMENT doc EMPTY>\n" 9094 "]>\n<doc/>"; 9095 int i; 9096 const int max_alloc_count = 20; 9097 9098 for (i = 0; i < max_alloc_count; i++) { 9099 allocation_count = i; 9100 dummy_handler_flags = 0; 9101 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9102 XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); 9103 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9104 != XML_STATUS_ERROR) 9105 break; 9106 /* See comment in test_alloc_parse_xdecl() */ 9107 alloc_teardown(); 9108 alloc_setup(); 9109 } 9110 if (i == 0) 9111 fail("Parse succeeded despite allocation failures"); 9112 if (i == max_alloc_count) 9113 fail("Parse failed at maximum allocation count"); 9114 if (dummy_handler_flags 9115 != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG)) 9116 fail("Entity declaration handler not called"); 9117 } 9118 END_TEST 9119 9120 /* Test public notation with dodgy allocator */ 9121 START_TEST(test_alloc_public_notation) { 9122 const char *text 9123 = "<!DOCTYPE doc [\n" 9124 "<!NOTATION note PUBLIC '" 9125 /* 64 characters per line */ 9126 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9128 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9129 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9130 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9131 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9132 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9133 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9134 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9135 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9136 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9137 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9138 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9139 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9140 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9141 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9142 "' 'foo'>\n" 9143 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9144 "<!ELEMENT doc EMPTY>\n" 9145 "]>\n<doc/>"; 9146 int i; 9147 const int max_alloc_count = 20; 9148 9149 for (i = 0; i < max_alloc_count; i++) { 9150 allocation_count = i; 9151 dummy_handler_flags = 0; 9152 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9153 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9154 != XML_STATUS_ERROR) 9155 break; 9156 /* See comment in test_alloc_parse_xdecl() */ 9157 alloc_teardown(); 9158 alloc_setup(); 9159 } 9160 if (i == 0) 9161 fail("Parse succeeded despite allocation failures"); 9162 if (i == max_alloc_count) 9163 fail("Parse failed at maximum allocation count"); 9164 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9165 fail("Notation handler not called"); 9166 } 9167 END_TEST 9168 9169 /* Test public notation with dodgy allocator */ 9170 START_TEST(test_alloc_system_notation) { 9171 const char *text 9172 = "<!DOCTYPE doc [\n" 9173 "<!NOTATION note SYSTEM '" 9174 /* 64 characters per line */ 9175 "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/" 9176 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9177 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9178 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9179 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9180 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9181 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9182 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9183 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9184 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9185 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9186 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9187 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9188 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9189 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9190 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 9191 "'>\n" 9192 "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n" 9193 "<!ELEMENT doc EMPTY>\n" 9194 "]>\n<doc/>"; 9195 int i; 9196 const int max_alloc_count = 20; 9197 9198 for (i = 0; i < max_alloc_count; i++) { 9199 allocation_count = i; 9200 dummy_handler_flags = 0; 9201 XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); 9202 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9203 != XML_STATUS_ERROR) 9204 break; 9205 /* See comment in test_alloc_parse_xdecl() */ 9206 alloc_teardown(); 9207 alloc_setup(); 9208 } 9209 if (i == 0) 9210 fail("Parse succeeded despite allocation failures"); 9211 if (i == max_alloc_count) 9212 fail("Parse failed at maximum allocation count"); 9213 if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG) 9214 fail("Notation handler not called"); 9215 } 9216 END_TEST 9217 9218 START_TEST(test_alloc_nested_groups) { 9219 const char *text 9220 = "<!DOCTYPE doc [\n" 9221 "<!ELEMENT doc " 9222 /* Sixteen elements per line */ 9223 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9224 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9225 "))))))))))))))))))))))))))))))))>\n" 9226 "<!ELEMENT e EMPTY>" 9227 "]>\n" 9228 "<doc><e/></doc>"; 9229 CharData storage; 9230 int i; 9231 const int max_alloc_count = 20; 9232 9233 for (i = 0; i < max_alloc_count; i++) { 9234 allocation_count = i; 9235 CharData_Init(&storage); 9236 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9237 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9238 XML_SetUserData(g_parser, &storage); 9239 dummy_handler_flags = 0; 9240 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9241 != XML_STATUS_ERROR) 9242 break; 9243 /* See comment in test_alloc_parse_xdecl() */ 9244 alloc_teardown(); 9245 alloc_setup(); 9246 } 9247 9248 if (i == 0) 9249 fail("Parse succeeded despite failing reallocator"); 9250 if (i == max_alloc_count) 9251 fail("Parse failed at maximum reallocation count"); 9252 CharData_CheckXMLChars(&storage, XCS("doce")); 9253 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9254 fail("Element handler not fired"); 9255 } 9256 END_TEST 9257 9258 START_TEST(test_alloc_realloc_nested_groups) { 9259 const char *text 9260 = "<!DOCTYPE doc [\n" 9261 "<!ELEMENT doc " 9262 /* Sixteen elements per line */ 9263 "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?," 9264 "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?" 9265 "))))))))))))))))))))))))))))))))>\n" 9266 "<!ELEMENT e EMPTY>" 9267 "]>\n" 9268 "<doc><e/></doc>"; 9269 CharData storage; 9270 int i; 9271 const int max_realloc_count = 10; 9272 9273 for (i = 0; i < max_realloc_count; i++) { 9274 reallocation_count = i; 9275 CharData_Init(&storage); 9276 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9277 XML_SetStartElementHandler(g_parser, record_element_start_handler); 9278 XML_SetUserData(g_parser, &storage); 9279 dummy_handler_flags = 0; 9280 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9281 != XML_STATUS_ERROR) 9282 break; 9283 /* See comment in test_alloc_parse_xdecl() */ 9284 alloc_teardown(); 9285 alloc_setup(); 9286 } 9287 9288 if (i == 0) 9289 fail("Parse succeeded despite failing reallocator"); 9290 if (i == max_realloc_count) 9291 fail("Parse failed at maximum reallocation count"); 9292 CharData_CheckXMLChars(&storage, XCS("doce")); 9293 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9294 fail("Element handler not fired"); 9295 } 9296 END_TEST 9297 9298 START_TEST(test_alloc_large_group) { 9299 const char *text = "<!DOCTYPE doc [\n" 9300 "<!ELEMENT doc (" 9301 "a1|a2|a3|a4|a5|a6|a7|a8|" 9302 "b1|b2|b3|b4|b5|b6|b7|b8|" 9303 "c1|c2|c3|c4|c5|c6|c7|c8|" 9304 "d1|d2|d3|d4|d5|d6|d7|d8|" 9305 "e1" 9306 ")+>\n" 9307 "]>\n" 9308 "<doc>\n" 9309 "<a1/>\n" 9310 "</doc>\n"; 9311 int i; 9312 const int max_alloc_count = 50; 9313 9314 for (i = 0; i < max_alloc_count; i++) { 9315 allocation_count = i; 9316 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9317 dummy_handler_flags = 0; 9318 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9319 != XML_STATUS_ERROR) 9320 break; 9321 /* See comment in test_alloc_parse_xdecl() */ 9322 alloc_teardown(); 9323 alloc_setup(); 9324 } 9325 if (i == 0) 9326 fail("Parse succeeded despite failing allocator"); 9327 if (i == max_alloc_count) 9328 fail("Parse failed at maximum allocation count"); 9329 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9330 fail("Element handler flag not raised"); 9331 } 9332 END_TEST 9333 9334 START_TEST(test_alloc_realloc_group_choice) { 9335 const char *text = "<!DOCTYPE doc [\n" 9336 "<!ELEMENT doc (" 9337 "a1|a2|a3|a4|a5|a6|a7|a8|" 9338 "b1|b2|b3|b4|b5|b6|b7|b8|" 9339 "c1|c2|c3|c4|c5|c6|c7|c8|" 9340 "d1|d2|d3|d4|d5|d6|d7|d8|" 9341 "e1" 9342 ")+>\n" 9343 "]>\n" 9344 "<doc>\n" 9345 "<a1/>\n" 9346 "<b2 attr='foo'>This is a foo</b2>\n" 9347 "<c3></c3>\n" 9348 "</doc>\n"; 9349 int i; 9350 const int max_realloc_count = 10; 9351 9352 for (i = 0; i < max_realloc_count; i++) { 9353 reallocation_count = i; 9354 XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); 9355 dummy_handler_flags = 0; 9356 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9357 != XML_STATUS_ERROR) 9358 break; 9359 /* See comment in test_alloc_parse_xdecl() */ 9360 alloc_teardown(); 9361 alloc_setup(); 9362 } 9363 if (i == 0) 9364 fail("Parse succeeded despite failing reallocator"); 9365 if (i == max_realloc_count) 9366 fail("Parse failed at maximum reallocation count"); 9367 if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG) 9368 fail("Element handler flag not raised"); 9369 } 9370 END_TEST 9371 9372 START_TEST(test_alloc_pi_in_epilog) { 9373 const char *text = "<doc></doc>\n" 9374 "<?pi in epilog?>"; 9375 int i; 9376 const int max_alloc_count = 15; 9377 9378 for (i = 0; i < max_alloc_count; i++) { 9379 allocation_count = i; 9380 XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); 9381 dummy_handler_flags = 0; 9382 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9383 != XML_STATUS_ERROR) 9384 break; 9385 /* See comment in test_alloc_parse_xdecl() */ 9386 alloc_teardown(); 9387 alloc_setup(); 9388 } 9389 if (i == 0) 9390 fail("Parse completed despite failing allocator"); 9391 if (i == max_alloc_count) 9392 fail("Parse failed at maximum allocation count"); 9393 if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG) 9394 fail("Processing instruction handler not invoked"); 9395 } 9396 END_TEST 9397 9398 START_TEST(test_alloc_comment_in_epilog) { 9399 const char *text = "<doc></doc>\n" 9400 "<!-- comment in epilog -->"; 9401 int i; 9402 const int max_alloc_count = 15; 9403 9404 for (i = 0; i < max_alloc_count; i++) { 9405 allocation_count = i; 9406 XML_SetCommentHandler(g_parser, dummy_comment_handler); 9407 dummy_handler_flags = 0; 9408 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9409 != XML_STATUS_ERROR) 9410 break; 9411 /* See comment in test_alloc_parse_xdecl() */ 9412 alloc_teardown(); 9413 alloc_setup(); 9414 } 9415 if (i == 0) 9416 fail("Parse completed despite failing allocator"); 9417 if (i == max_alloc_count) 9418 fail("Parse failed at maximum allocation count"); 9419 if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG) 9420 fail("Processing instruction handler not invoked"); 9421 } 9422 END_TEST 9423 9424 START_TEST(test_alloc_realloc_long_attribute_value) { 9425 const char *text 9426 = "<!DOCTYPE doc [<!ENTITY foo '" 9427 /* Each line is 64 characters */ 9428 "This entity will be substituted as an attribute value, and is " 9429 "calculated to be exactly long enough that the terminating NUL " 9430 "that the library adds internally will trigger the string pool to" 9431 "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9432 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9433 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9434 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9435 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9436 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9437 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9438 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9439 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9440 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9441 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9442 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9443 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9444 "'>]>\n" 9445 "<doc a='&foo;'></doc>"; 9446 int i; 9447 const int max_realloc_count = 10; 9448 9449 for (i = 0; i < max_realloc_count; i++) { 9450 reallocation_count = i; 9451 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9452 != XML_STATUS_ERROR) 9453 break; 9454 /* See comment in test_alloc_parse_xdecl() */ 9455 alloc_teardown(); 9456 alloc_setup(); 9457 } 9458 if (i == 0) 9459 fail("Parse succeeded despite failing reallocator"); 9460 if (i == max_realloc_count) 9461 fail("Parse failed at maximum reallocation count"); 9462 } 9463 END_TEST 9464 9465 START_TEST(test_alloc_attribute_whitespace) { 9466 const char *text = "<doc a=' '></doc>"; 9467 int i; 9468 const int max_alloc_count = 15; 9469 9470 for (i = 0; i < max_alloc_count; i++) { 9471 allocation_count = i; 9472 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9473 != XML_STATUS_ERROR) 9474 break; 9475 /* See comment in test_alloc_parse_xdecl() */ 9476 alloc_teardown(); 9477 alloc_setup(); 9478 } 9479 if (i == 0) 9480 fail("Parse succeeded despite failing allocator"); 9481 if (i == max_alloc_count) 9482 fail("Parse failed at maximum allocation count"); 9483 } 9484 END_TEST 9485 9486 START_TEST(test_alloc_attribute_predefined_entity) { 9487 const char *text = "<doc a='&'></doc>"; 9488 int i; 9489 const int max_alloc_count = 15; 9490 9491 for (i = 0; i < max_alloc_count; i++) { 9492 allocation_count = i; 9493 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9494 != XML_STATUS_ERROR) 9495 break; 9496 /* See comment in test_alloc_parse_xdecl() */ 9497 alloc_teardown(); 9498 alloc_setup(); 9499 } 9500 if (i == 0) 9501 fail("Parse succeeded despite failing allocator"); 9502 if (i == max_alloc_count) 9503 fail("Parse failed at maximum allocation count"); 9504 } 9505 END_TEST 9506 9507 /* Test that a character reference at the end of a suitably long 9508 * default value for an attribute can trigger pool growth, and recovers 9509 * if the allocator fails on it. 9510 */ 9511 START_TEST(test_alloc_long_attr_default_with_char_ref) { 9512 const char *text 9513 = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '" 9514 /* 64 characters per line */ 9515 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9516 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9517 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9518 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9519 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9520 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9521 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9522 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9523 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9524 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9525 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9526 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9527 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9528 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9529 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9530 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI" 9531 "1'>]>\n" 9532 "<doc/>"; 9533 int i; 9534 const int max_alloc_count = 20; 9535 9536 for (i = 0; i < max_alloc_count; i++) { 9537 allocation_count = i; 9538 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9539 != XML_STATUS_ERROR) 9540 break; 9541 /* See comment in test_alloc_parse_xdecl() */ 9542 alloc_teardown(); 9543 alloc_setup(); 9544 } 9545 if (i == 0) 9546 fail("Parse succeeded despite failing allocator"); 9547 if (i == max_alloc_count) 9548 fail("Parse failed at maximum allocation count"); 9549 } 9550 END_TEST 9551 9552 /* Test that a long character reference substitution triggers a pool 9553 * expansion correctly for an attribute value. 9554 */ 9555 START_TEST(test_alloc_long_attr_value) { 9556 const char *text 9557 = "<!DOCTYPE test [<!ENTITY foo '\n" 9558 /* 64 characters per line */ 9559 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9560 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9561 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9562 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9563 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9564 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9565 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9566 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9567 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9568 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9569 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9570 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9571 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9572 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9573 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9574 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9575 "'>]>\n" 9576 "<test a='&foo;'/>"; 9577 int i; 9578 const int max_alloc_count = 25; 9579 9580 for (i = 0; i < max_alloc_count; i++) { 9581 allocation_count = i; 9582 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9583 != XML_STATUS_ERROR) 9584 break; 9585 /* See comment in test_alloc_parse_xdecl() */ 9586 alloc_teardown(); 9587 alloc_setup(); 9588 } 9589 if (i == 0) 9590 fail("Parse succeeded despite failing allocator"); 9591 if (i == max_alloc_count) 9592 fail("Parse failed at maximum allocation count"); 9593 } 9594 END_TEST 9595 9596 /* Test that an error in a nested parameter entity substitution is 9597 * handled correctly. It seems unlikely that the code path being 9598 * exercised can be reached purely by carefully crafted XML, but an 9599 * allocation error in the right place will definitely do it. 9600 */ 9601 START_TEST(test_alloc_nested_entities) { 9602 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n" 9603 "<doc />"; 9604 ExtFaults test_data 9605 = {"<!ENTITY % pe1 '" 9606 /* 64 characters per line */ 9607 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9608 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9609 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9610 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9611 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9612 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9613 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9614 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9615 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9616 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9617 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9618 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9619 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9620 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9621 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9622 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9623 "'>\n" 9624 "<!ENTITY % pe2 '%pe1;'>\n" 9625 "%pe2;", 9626 "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY}; 9627 9628 /* Causes an allocation error in a nested storeEntityValue() */ 9629 allocation_count = 12; 9630 XML_SetUserData(g_parser, &test_data); 9631 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9632 XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); 9633 expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, 9634 "Entity allocation failure not noted"); 9635 } 9636 END_TEST 9637 9638 START_TEST(test_alloc_realloc_param_entity_newline) { 9639 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9640 "<doc/>"; 9641 char dtd_text[] 9642 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9643 /* 64 characters per line */ 9644 "This default value is carefully crafted so that the carriage " 9645 "return right at the end of the entity string causes an internal " 9646 "string pool to have to grow. This allows us to test the alloc " 9647 "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9648 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9649 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9650 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9651 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9652 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9653 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9654 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9655 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9656 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9657 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9658 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9659 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE" 9660 "\">\n'>" 9661 "%pe;\n"; 9662 int i; 9663 const int max_realloc_count = 5; 9664 9665 for (i = 0; i < max_realloc_count; i++) { 9666 reallocation_count = i; 9667 XML_SetUserData(g_parser, dtd_text); 9668 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9669 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9670 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9671 != XML_STATUS_ERROR) 9672 break; 9673 /* See comment in test_alloc_parse_xdecl() */ 9674 alloc_teardown(); 9675 alloc_setup(); 9676 } 9677 if (i == 0) 9678 fail("Parse succeeded despite failing reallocator"); 9679 if (i == max_realloc_count) 9680 fail("Parse failed at maximum reallocation count"); 9681 } 9682 END_TEST 9683 9684 START_TEST(test_alloc_realloc_ce_extends_pe) { 9685 const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n" 9686 "<doc/>"; 9687 char dtd_text[] 9688 = "<!ENTITY % pe '<!ATTLIST doc att CDATA \"" 9689 /* 64 characters per line */ 9690 "This default value is carefully crafted so that the character " 9691 "entity at the end causes an internal string pool to have to " 9692 "grow. This allows us to test the allocation failure path from " 9693 "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9694 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9695 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9696 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9697 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9698 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9699 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9700 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9701 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9702 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9703 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9704 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 9705 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGQ" 9706 "\">\n'>" 9707 "%pe;\n"; 9708 int i; 9709 const int max_realloc_count = 5; 9710 9711 for (i = 0; i < max_realloc_count; i++) { 9712 reallocation_count = i; 9713 XML_SetUserData(g_parser, dtd_text); 9714 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9715 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9716 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9717 != XML_STATUS_ERROR) 9718 break; 9719 /* See comment in test_alloc_parse_xdecl() */ 9720 alloc_teardown(); 9721 alloc_setup(); 9722 } 9723 if (i == 0) 9724 fail("Parse succeeded despite failing reallocator"); 9725 if (i == max_realloc_count) 9726 fail("Parse failed at maximum reallocation count"); 9727 } 9728 END_TEST 9729 9730 START_TEST(test_alloc_realloc_attributes) { 9731 const char *text = "<!DOCTYPE doc [\n" 9732 " <!ATTLIST doc\n" 9733 " a1 (a|b|c) 'a'\n" 9734 " a2 (foo|bar) #IMPLIED\n" 9735 " a3 NMTOKEN #IMPLIED\n" 9736 " a4 NMTOKENS #IMPLIED\n" 9737 " a5 ID #IMPLIED\n" 9738 " a6 IDREF #IMPLIED\n" 9739 " a7 IDREFS #IMPLIED\n" 9740 " a8 ENTITY #IMPLIED\n" 9741 " a9 ENTITIES #IMPLIED\n" 9742 " a10 CDATA #IMPLIED\n" 9743 " >]>\n" 9744 "<doc>wombat</doc>\n"; 9745 int i; 9746 const int max_realloc_count = 5; 9747 9748 for (i = 0; i < max_realloc_count; i++) { 9749 reallocation_count = i; 9750 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9751 != XML_STATUS_ERROR) 9752 break; 9753 /* See comment in test_alloc_parse_xdecl() */ 9754 alloc_teardown(); 9755 alloc_setup(); 9756 } 9757 9758 if (i == 0) 9759 fail("Parse succeeded despite failing reallocator"); 9760 if (i == max_realloc_count) 9761 fail("Parse failed at maximum reallocation count"); 9762 } 9763 END_TEST 9764 9765 START_TEST(test_alloc_long_doc_name) { 9766 const char *text = 9767 /* 64 characters per line */ 9768 "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr" 9769 "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9770 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9771 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9772 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9773 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9774 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9777 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9778 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9782 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9783 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 9784 " a='1'/>"; 9785 int i; 9786 const int max_alloc_count = 20; 9787 9788 for (i = 0; i < max_alloc_count; i++) { 9789 allocation_count = i; 9790 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9791 != XML_STATUS_ERROR) 9792 break; 9793 /* See comment in test_alloc_parse_xdecl() */ 9794 alloc_teardown(); 9795 alloc_setup(); 9796 } 9797 if (i == 0) 9798 fail("Parsing worked despite failing reallocations"); 9799 else if (i == max_alloc_count) 9800 fail("Parsing failed even at max reallocation count"); 9801 } 9802 END_TEST 9803 9804 START_TEST(test_alloc_long_base) { 9805 const char *text = "<!DOCTYPE doc [\n" 9806 " <!ENTITY e SYSTEM 'foo'>\n" 9807 "]>\n" 9808 "<doc>&e;</doc>"; 9809 char entity_text[] = "Hello world"; 9810 const XML_Char *base = 9811 /* 64 characters per line */ 9812 /* clang-format off */ 9813 XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t") 9814 XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9815 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9816 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9817 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9818 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9819 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9820 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9821 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9822 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9823 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9824 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9825 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9826 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9827 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") 9828 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"); 9829 /* clang-format on */ 9830 int i; 9831 const int max_alloc_count = 25; 9832 9833 for (i = 0; i < max_alloc_count; i++) { 9834 allocation_count = i; 9835 XML_SetUserData(g_parser, entity_text); 9836 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9837 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9838 if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) { 9839 XML_ParserReset(g_parser, NULL); 9840 continue; 9841 } 9842 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9843 != XML_STATUS_ERROR) 9844 break; 9845 /* See comment in test_alloc_parse_xdecl() */ 9846 alloc_teardown(); 9847 alloc_setup(); 9848 } 9849 if (i == 0) 9850 fail("Parsing worked despite failing allocations"); 9851 else if (i == max_alloc_count) 9852 fail("Parsing failed even at max allocation count"); 9853 } 9854 END_TEST 9855 9856 START_TEST(test_alloc_long_public_id) { 9857 const char *text 9858 = "<!DOCTYPE doc [\n" 9859 " <!ENTITY e PUBLIC '" 9860 /* 64 characters per line */ 9861 "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec" 9862 "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9863 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9864 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9865 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9866 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9867 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9868 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9869 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9870 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9871 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9872 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9873 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9874 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9875 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9876 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9877 "' 'bar'>\n" 9878 "]>\n" 9879 "<doc>&e;</doc>"; 9880 char entity_text[] = "Hello world"; 9881 int i; 9882 const int max_alloc_count = 40; 9883 9884 for (i = 0; i < max_alloc_count; i++) { 9885 allocation_count = i; 9886 XML_SetUserData(g_parser, entity_text); 9887 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9888 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9889 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9890 != XML_STATUS_ERROR) 9891 break; 9892 /* See comment in test_alloc_parse_xdecl() */ 9893 alloc_teardown(); 9894 alloc_setup(); 9895 } 9896 if (i == 0) 9897 fail("Parsing worked despite failing allocations"); 9898 else if (i == max_alloc_count) 9899 fail("Parsing failed even at max allocation count"); 9900 } 9901 END_TEST 9902 9903 START_TEST(test_alloc_long_entity_value) { 9904 const char *text 9905 = "<!DOCTYPE doc [\n" 9906 " <!ENTITY e1 '" 9907 /* 64 characters per line */ 9908 "Long entity value that should provoke a string pool to grow whil" 9909 "e setting up to parse the external entity below. xyz0123456789AB" 9910 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9911 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9912 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9913 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9914 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9915 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9916 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9917 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9918 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9920 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9921 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9922 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9923 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9924 "'>\n" 9925 " <!ENTITY e2 SYSTEM 'bar'>\n" 9926 "]>\n" 9927 "<doc>&e2;</doc>"; 9928 char entity_text[] = "Hello world"; 9929 int i; 9930 const int max_alloc_count = 40; 9931 9932 for (i = 0; i < max_alloc_count; i++) { 9933 allocation_count = i; 9934 XML_SetUserData(g_parser, entity_text); 9935 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 9936 XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); 9937 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 9938 != XML_STATUS_ERROR) 9939 break; 9940 /* See comment in test_alloc_parse_xdecl() */ 9941 alloc_teardown(); 9942 alloc_setup(); 9943 } 9944 if (i == 0) 9945 fail("Parsing worked despite failing allocations"); 9946 else if (i == max_alloc_count) 9947 fail("Parsing failed even at max allocation count"); 9948 } 9949 END_TEST 9950 9951 START_TEST(test_alloc_long_notation) { 9952 const char *text 9953 = "<!DOCTYPE doc [\n" 9954 " <!NOTATION note SYSTEM '" 9955 /* 64 characters per line */ 9956 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 9957 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9958 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9959 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9960 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9961 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9962 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9963 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9964 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9965 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9966 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9967 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9968 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9969 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9970 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9971 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9972 "'>\n" 9973 " <!ENTITY e1 SYSTEM 'foo' NDATA " 9974 /* 64 characters per line */ 9975 "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn" 9976 "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9977 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9978 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9979 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9980 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9981 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9982 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9983 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9984 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9985 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9986 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9987 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9988 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9989 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9990 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB" 9991 ">\n" 9992 " <!ENTITY e2 SYSTEM 'bar'>\n" 9993 "]>\n" 9994 "<doc>&e2;</doc>"; 9995 ExtOption options[] 9996 = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}}; 9997 int i; 9998 const int max_alloc_count = 40; 9999 10000 for (i = 0; i < max_alloc_count; i++) { 10001 allocation_count = i; 10002 XML_SetUserData(g_parser, options); 10003 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10004 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10005 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10006 != XML_STATUS_ERROR) 10007 break; 10008 10009 /* See comment in test_alloc_parse_xdecl() */ 10010 alloc_teardown(); 10011 alloc_setup(); 10012 } 10013 if (i == 0) 10014 fail("Parsing worked despite failing allocations"); 10015 else if (i == max_alloc_count) 10016 fail("Parsing failed even at max allocation count"); 10017 } 10018 END_TEST 10019 10020 static void 10021 nsalloc_setup(void) { 10022 XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; 10023 XML_Char ns_sep[2] = {' ', '\0'}; 10024 10025 /* Ensure the parser creation will go through */ 10026 allocation_count = ALLOC_ALWAYS_SUCCEED; 10027 reallocation_count = REALLOC_ALWAYS_SUCCEED; 10028 g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep); 10029 if (g_parser == NULL) 10030 fail("Parser not created"); 10031 } 10032 10033 static void 10034 nsalloc_teardown(void) { 10035 basic_teardown(); 10036 } 10037 10038 /* Test the effects of allocation failure in simple namespace parsing. 10039 * Based on test_ns_default_with_empty_uri() 10040 */ 10041 START_TEST(test_nsalloc_xmlns) { 10042 const char *text = "<doc xmlns='http://example.org/'>\n" 10043 " <e xmlns=''/>\n" 10044 "</doc>"; 10045 unsigned int i; 10046 const unsigned int max_alloc_count = 30; 10047 10048 for (i = 0; i < max_alloc_count; i++) { 10049 allocation_count = i; 10050 /* Exercise more code paths with a default handler */ 10051 XML_SetDefaultHandler(g_parser, dummy_default_handler); 10052 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10053 != XML_STATUS_ERROR) 10054 break; 10055 /* Resetting the parser is insufficient, because some memory 10056 * allocations are cached within the parser. Instead we use 10057 * the teardown and setup routines to ensure that we have the 10058 * right sort of parser back in our hands. 10059 */ 10060 nsalloc_teardown(); 10061 nsalloc_setup(); 10062 } 10063 if (i == 0) 10064 fail("Parsing worked despite failing allocations"); 10065 else if (i == max_alloc_count) 10066 fail("Parsing failed even at maximum allocation count"); 10067 } 10068 END_TEST 10069 10070 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */ 10071 START_TEST(test_nsalloc_parse_buffer) { 10072 const char *text = "<doc>Hello</doc>"; 10073 void *buffer; 10074 10075 /* Try a parse before the start of the world */ 10076 /* (Exercises new code path) */ 10077 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10078 fail("Pre-init XML_ParseBuffer not faulted"); 10079 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER) 10080 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10081 10082 buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */); 10083 if (buffer == NULL) 10084 fail("Could not acquire parse buffer"); 10085 10086 allocation_count = 0; 10087 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR) 10088 fail("Pre-init XML_ParseBuffer not faulted"); 10089 if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY) 10090 fail("Pre-init XML_ParseBuffer faulted for wrong reason"); 10091 10092 /* Now with actual memory allocation */ 10093 allocation_count = ALLOC_ALWAYS_SUCCEED; 10094 if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK) 10095 xml_failure(g_parser); 10096 10097 /* Check that resuming an unsuspended parser is faulted */ 10098 if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR) 10099 fail("Resuming unsuspended parser not faulted"); 10100 if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED) 10101 xml_failure(g_parser); 10102 10103 /* Get the parser into suspended state */ 10104 XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler); 10105 resumable = XML_TRUE; 10106 buffer = XML_GetBuffer(g_parser, (int)strlen(text)); 10107 if (buffer == NULL) 10108 fail("Could not acquire parse buffer"); 10109 assert(buffer != NULL); 10110 memcpy(buffer, text, strlen(text)); 10111 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10112 != XML_STATUS_SUSPENDED) 10113 xml_failure(g_parser); 10114 if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE) 10115 xml_failure(g_parser); 10116 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10117 != XML_STATUS_ERROR) 10118 fail("Suspended XML_ParseBuffer not faulted"); 10119 if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED) 10120 xml_failure(g_parser); 10121 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10122 fail("Suspended XML_GetBuffer not faulted"); 10123 10124 /* Get it going again and complete the world */ 10125 XML_SetCharacterDataHandler(g_parser, NULL); 10126 if (XML_ResumeParser(g_parser) != XML_STATUS_OK) 10127 xml_failure(g_parser); 10128 if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE) 10129 != XML_STATUS_ERROR) 10130 fail("Post-finishing XML_ParseBuffer not faulted"); 10131 if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED) 10132 xml_failure(g_parser); 10133 if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL) 10134 fail("Post-finishing XML_GetBuffer not faulted"); 10135 } 10136 END_TEST 10137 10138 /* Check handling of long prefix names (pool growth) */ 10139 START_TEST(test_nsalloc_long_prefix) { 10140 const char *text 10141 = "<" 10142 /* 64 characters per line */ 10143 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10144 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10145 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10146 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10147 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10148 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10149 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10150 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10151 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10152 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10153 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10154 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10155 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10156 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10157 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10158 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10159 ":foo xmlns:" 10160 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10161 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10162 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10163 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10164 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10165 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10166 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10167 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10168 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10169 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10170 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10171 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10172 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10173 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10174 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10175 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10176 "='http://example.org/'>" 10177 "</" 10178 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10179 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10180 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10181 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10182 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10183 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10184 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10185 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10186 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10187 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10188 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10189 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10190 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10192 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10193 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10194 ":foo>"; 10195 int i; 10196 const int max_alloc_count = 40; 10197 10198 for (i = 0; i < max_alloc_count; i++) { 10199 allocation_count = i; 10200 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10201 != XML_STATUS_ERROR) 10202 break; 10203 /* See comment in test_nsalloc_xmlns() */ 10204 nsalloc_teardown(); 10205 nsalloc_setup(); 10206 } 10207 if (i == 0) 10208 fail("Parsing worked despite failing allocations"); 10209 else if (i == max_alloc_count) 10210 fail("Parsing failed even at max allocation count"); 10211 } 10212 END_TEST 10213 10214 /* Check handling of long uri names (pool growth) */ 10215 START_TEST(test_nsalloc_long_uri) { 10216 const char *text 10217 = "<foo:e xmlns:foo='http://example.org/" 10218 /* 64 characters per line */ 10219 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10221 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10222 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10224 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10225 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10226 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10227 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10228 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10229 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10230 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10231 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10233 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10234 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10235 "' bar:a='12'\n" 10236 "xmlns:bar='http://example.org/" 10237 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10238 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10239 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10240 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10241 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10242 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10243 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10244 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10245 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10246 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10247 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10248 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10249 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10250 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10251 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10252 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/" 10253 "'>" 10254 "</foo:e>"; 10255 int i; 10256 const int max_alloc_count = 40; 10257 10258 for (i = 0; i < max_alloc_count; i++) { 10259 allocation_count = i; 10260 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10261 != XML_STATUS_ERROR) 10262 break; 10263 /* See comment in test_nsalloc_xmlns() */ 10264 nsalloc_teardown(); 10265 nsalloc_setup(); 10266 } 10267 if (i == 0) 10268 fail("Parsing worked despite failing allocations"); 10269 else if (i == max_alloc_count) 10270 fail("Parsing failed even at max allocation count"); 10271 } 10272 END_TEST 10273 10274 /* Test handling of long attribute names with prefixes */ 10275 START_TEST(test_nsalloc_long_attr) { 10276 const char *text 10277 = "<foo:e xmlns:foo='http://example.org/' bar:" 10278 /* 64 characters per line */ 10279 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10280 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10281 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10282 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10283 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10284 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10285 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10286 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10287 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10288 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10289 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10290 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10291 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10292 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10293 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10294 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10295 "='12'\n" 10296 "xmlns:bar='http://example.org/'>" 10297 "</foo:e>"; 10298 int i; 10299 const int max_alloc_count = 40; 10300 10301 for (i = 0; i < max_alloc_count; i++) { 10302 allocation_count = i; 10303 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10304 != XML_STATUS_ERROR) 10305 break; 10306 /* See comment in test_nsalloc_xmlns() */ 10307 nsalloc_teardown(); 10308 nsalloc_setup(); 10309 } 10310 if (i == 0) 10311 fail("Parsing worked despite failing allocations"); 10312 else if (i == max_alloc_count) 10313 fail("Parsing failed even at max allocation count"); 10314 } 10315 END_TEST 10316 10317 /* Test handling of an attribute name with a long namespace prefix */ 10318 START_TEST(test_nsalloc_long_attr_prefix) { 10319 const char *text 10320 = "<foo:e xmlns:foo='http://example.org/' " 10321 /* 64 characters per line */ 10322 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10323 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10324 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10325 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10326 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10327 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10328 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10329 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10330 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10331 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10332 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10333 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10334 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10335 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10336 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10337 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10338 ":a='12'\n" 10339 "xmlns:" 10340 /* 64 characters per line */ 10341 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10342 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10343 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10344 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10345 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10346 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10347 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10348 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10349 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10350 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10351 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10352 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10353 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10354 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10355 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10356 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10357 "='http://example.org/'>" 10358 "</foo:e>"; 10359 const XML_Char *elemstr[] = { 10360 /* clang-format off */ 10361 XCS("http://example.org/ e foo"), 10362 XCS("http://example.org/ a ") 10363 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10364 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10365 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10366 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10367 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10368 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10369 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10370 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10371 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10372 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10373 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10374 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10375 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10376 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10377 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10378 XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ") 10379 /* clang-format on */ 10380 }; 10381 int i; 10382 const int max_alloc_count = 40; 10383 10384 for (i = 0; i < max_alloc_count; i++) { 10385 allocation_count = i; 10386 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10387 XML_SetUserData(g_parser, (void *)elemstr); 10388 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10389 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10390 != XML_STATUS_ERROR) 10391 break; 10392 /* See comment in test_nsalloc_xmlns() */ 10393 nsalloc_teardown(); 10394 nsalloc_setup(); 10395 } 10396 if (i == 0) 10397 fail("Parsing worked despite failing allocations"); 10398 else if (i == max_alloc_count) 10399 fail("Parsing failed even at max allocation count"); 10400 } 10401 END_TEST 10402 10403 /* Test attribute handling in the face of a dodgy reallocator */ 10404 START_TEST(test_nsalloc_realloc_attributes) { 10405 const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n" 10406 " xmlns:bar='http://example.org/'>" 10407 "</foo:e>"; 10408 int i; 10409 const int max_realloc_count = 10; 10410 10411 for (i = 0; i < max_realloc_count; i++) { 10412 reallocation_count = i; 10413 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10414 != XML_STATUS_ERROR) 10415 break; 10416 /* See comment in test_nsalloc_xmlns() */ 10417 nsalloc_teardown(); 10418 nsalloc_setup(); 10419 } 10420 if (i == 0) 10421 fail("Parsing worked despite failing reallocations"); 10422 else if (i == max_realloc_count) 10423 fail("Parsing failed at max reallocation count"); 10424 } 10425 END_TEST 10426 10427 /* Test long element names with namespaces under a failing allocator */ 10428 START_TEST(test_nsalloc_long_element) { 10429 const char *text 10430 = "<foo:thisisalongenoughelementnametotriggerareallocation\n" 10431 " xmlns:foo='http://example.org/' bar:a='12'\n" 10432 " xmlns:bar='http://example.org/'>" 10433 "</foo:thisisalongenoughelementnametotriggerareallocation>"; 10434 const XML_Char *elemstr[] 10435 = {XCS("http://example.org/") 10436 XCS(" thisisalongenoughelementnametotriggerareallocation foo"), 10437 XCS("http://example.org/ a bar")}; 10438 int i; 10439 const int max_alloc_count = 30; 10440 10441 for (i = 0; i < max_alloc_count; i++) { 10442 allocation_count = i; 10443 XML_SetReturnNSTriplet(g_parser, XML_TRUE); 10444 XML_SetUserData(g_parser, (void *)elemstr); 10445 XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker); 10446 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10447 != XML_STATUS_ERROR) 10448 break; 10449 /* See comment in test_nsalloc_xmlns() */ 10450 nsalloc_teardown(); 10451 nsalloc_setup(); 10452 } 10453 if (i == 0) 10454 fail("Parsing worked despite failing reallocations"); 10455 else if (i == max_alloc_count) 10456 fail("Parsing failed at max reallocation count"); 10457 } 10458 END_TEST 10459 10460 /* Test the effects of reallocation failure when reassigning a 10461 * binding. 10462 * 10463 * XML_ParserReset does not free the BINDING structures used by a 10464 * parser, but instead adds them to an internal free list to be reused 10465 * as necessary. Likewise the URI buffers allocated for the binding 10466 * aren't freed, but kept attached to their existing binding. If the 10467 * new binding has a longer URI, it will need reallocation. This test 10468 * provokes that reallocation, and tests the control path if it fails. 10469 */ 10470 START_TEST(test_nsalloc_realloc_binding_uri) { 10471 const char *first = "<doc xmlns='http://example.org/'>\n" 10472 " <e xmlns='' />\n" 10473 "</doc>"; 10474 const char *second 10475 = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n" 10476 " <e xmlns='' />\n" 10477 "</doc>"; 10478 unsigned i; 10479 const unsigned max_realloc_count = 10; 10480 10481 /* First, do a full parse that will leave bindings around */ 10482 if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE) 10483 == XML_STATUS_ERROR) 10484 xml_failure(g_parser); 10485 10486 /* Now repeat with a longer URI and a duff reallocator */ 10487 for (i = 0; i < max_realloc_count; i++) { 10488 XML_ParserReset(g_parser, NULL); 10489 reallocation_count = i; 10490 if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE) 10491 != XML_STATUS_ERROR) 10492 break; 10493 } 10494 if (i == 0) 10495 fail("Parsing worked despite failing reallocation"); 10496 else if (i == max_realloc_count) 10497 fail("Parsing failed at max reallocation count"); 10498 } 10499 END_TEST 10500 10501 /* Check handling of long prefix names (pool growth) */ 10502 START_TEST(test_nsalloc_realloc_long_prefix) { 10503 const char *text 10504 = "<" 10505 /* 64 characters per line */ 10506 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10507 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10508 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10509 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10510 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10511 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10512 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10513 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10514 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10515 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10516 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10517 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10518 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10519 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10520 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10521 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10522 ":foo xmlns:" 10523 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10525 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10526 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10527 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10528 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10529 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10530 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10531 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10533 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10539 "='http://example.org/'>" 10540 "</" 10541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10544 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10545 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10546 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10548 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10549 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10550 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10551 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10552 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10553 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10554 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10555 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10556 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10557 ":foo>"; 10558 int i; 10559 const int max_realloc_count = 12; 10560 10561 for (i = 0; i < max_realloc_count; i++) { 10562 reallocation_count = i; 10563 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10564 != XML_STATUS_ERROR) 10565 break; 10566 /* See comment in test_nsalloc_xmlns() */ 10567 nsalloc_teardown(); 10568 nsalloc_setup(); 10569 } 10570 if (i == 0) 10571 fail("Parsing worked despite failing reallocations"); 10572 else if (i == max_realloc_count) 10573 fail("Parsing failed even at max reallocation count"); 10574 } 10575 END_TEST 10576 10577 /* Check handling of even long prefix names (different code path) */ 10578 START_TEST(test_nsalloc_realloc_longer_prefix) { 10579 const char *text 10580 = "<" 10581 /* 64 characters per line */ 10582 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10583 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10584 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10585 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10586 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10587 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10588 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10589 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10590 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10591 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10592 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10593 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10594 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10595 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10596 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10597 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10598 "Q:foo xmlns:" 10599 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10600 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10601 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10602 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10603 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10604 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10605 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10606 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10607 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10608 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10609 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10610 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10611 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10612 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10613 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10614 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10615 "Q='http://example.org/'>" 10616 "</" 10617 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10618 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10619 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10620 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10621 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10622 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10623 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10624 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10625 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10626 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10627 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10628 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10629 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10630 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10631 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10632 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10633 "Q:foo>"; 10634 int i; 10635 const int max_realloc_count = 12; 10636 10637 for (i = 0; i < max_realloc_count; i++) { 10638 reallocation_count = i; 10639 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10640 != XML_STATUS_ERROR) 10641 break; 10642 /* See comment in test_nsalloc_xmlns() */ 10643 nsalloc_teardown(); 10644 nsalloc_setup(); 10645 } 10646 if (i == 0) 10647 fail("Parsing worked despite failing reallocations"); 10648 else if (i == max_realloc_count) 10649 fail("Parsing failed even at max reallocation count"); 10650 } 10651 END_TEST 10652 10653 START_TEST(test_nsalloc_long_namespace) { 10654 const char *text1 10655 = "<" 10656 /* 64 characters per line */ 10657 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10658 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10659 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10660 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10661 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10662 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10663 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10664 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10665 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10666 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10667 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10668 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10669 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10670 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10671 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10672 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10673 ":e xmlns:" 10674 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10675 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10676 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10677 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10678 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10679 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10680 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10681 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10682 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10683 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10684 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10685 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10686 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10687 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10688 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10689 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10690 "='http://example.org/'>\n"; 10691 const char *text2 10692 = "<" 10693 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10694 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10695 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10696 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10697 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10698 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10699 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10700 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10701 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10702 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10703 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10704 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10705 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10706 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10707 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10708 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10709 ":f " 10710 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10711 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10712 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10713 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10714 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10715 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10716 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10717 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10718 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10719 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10720 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10721 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10723 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10724 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10725 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10726 ":attr='foo'/>\n" 10727 "</" 10728 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10729 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10730 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10731 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10732 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10733 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10734 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10735 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10736 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10737 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10738 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10739 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10740 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10741 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10742 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10743 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10744 ":e>"; 10745 int i; 10746 const int max_alloc_count = 40; 10747 10748 for (i = 0; i < max_alloc_count; i++) { 10749 allocation_count = i; 10750 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 10751 != XML_STATUS_ERROR 10752 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 10753 XML_TRUE) 10754 != XML_STATUS_ERROR) 10755 break; 10756 /* See comment in test_nsalloc_xmlns() */ 10757 nsalloc_teardown(); 10758 nsalloc_setup(); 10759 } 10760 if (i == 0) 10761 fail("Parsing worked despite failing allocations"); 10762 else if (i == max_alloc_count) 10763 fail("Parsing failed even at max allocation count"); 10764 } 10765 END_TEST 10766 10767 /* Using a slightly shorter namespace name provokes allocations in 10768 * slightly different places in the code. 10769 */ 10770 START_TEST(test_nsalloc_less_long_namespace) { 10771 const char *text 10772 = "<" 10773 /* 64 characters per line */ 10774 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10775 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10776 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10777 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10778 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10779 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10780 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10781 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10782 ":e xmlns:" 10783 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10784 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10785 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10786 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10787 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10788 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10789 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10790 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10791 "='http://example.org/'>\n" 10792 "<" 10793 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10794 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10795 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10796 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10797 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10798 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10799 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10800 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10801 ":f " 10802 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10803 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10804 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10805 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10806 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10807 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10808 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10809 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10810 ":att='foo'/>\n" 10811 "</" 10812 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10813 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10814 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10815 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10816 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10817 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10818 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ" 10819 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678" 10820 ":e>"; 10821 int i; 10822 const int max_alloc_count = 40; 10823 10824 for (i = 0; i < max_alloc_count; i++) { 10825 allocation_count = i; 10826 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10827 != XML_STATUS_ERROR) 10828 break; 10829 /* See comment in test_nsalloc_xmlns() */ 10830 nsalloc_teardown(); 10831 nsalloc_setup(); 10832 } 10833 if (i == 0) 10834 fail("Parsing worked despite failing allocations"); 10835 else if (i == max_alloc_count) 10836 fail("Parsing failed even at max allocation count"); 10837 } 10838 END_TEST 10839 10840 START_TEST(test_nsalloc_long_context) { 10841 const char *text 10842 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10843 " <!ATTLIST doc baz ID #REQUIRED>\n" 10844 " <!ENTITY en SYSTEM 'bar'>\n" 10845 "]>\n" 10846 "<doc xmlns='http://example.org/" 10847 /* 64 characters per line */ 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/ABCDEFGHIJKLMNO/" 10861 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10862 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10863 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 10864 "' baz='2'>\n" 10865 "&en;" 10866 "</doc>"; 10867 ExtOption options[] = { 10868 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10869 int i; 10870 const int max_alloc_count = 70; 10871 10872 for (i = 0; i < max_alloc_count; i++) { 10873 allocation_count = i; 10874 XML_SetUserData(g_parser, options); 10875 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10876 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10877 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10878 != XML_STATUS_ERROR) 10879 break; 10880 10881 /* See comment in test_nsalloc_xmlns() */ 10882 nsalloc_teardown(); 10883 nsalloc_setup(); 10884 } 10885 if (i == 0) 10886 fail("Parsing worked despite failing allocations"); 10887 else if (i == max_alloc_count) 10888 fail("Parsing failed even at max allocation count"); 10889 } 10890 END_TEST 10891 10892 /* This function is void; it will throw a fail() on error, so if it 10893 * returns normally it must have succeeded. 10894 */ 10895 static void 10896 context_realloc_test(const char *text) { 10897 ExtOption options[] = { 10898 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 10899 int i; 10900 const int max_realloc_count = 6; 10901 10902 for (i = 0; i < max_realloc_count; i++) { 10903 reallocation_count = i; 10904 XML_SetUserData(g_parser, options); 10905 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 10906 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 10907 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 10908 != XML_STATUS_ERROR) 10909 break; 10910 /* See comment in test_nsalloc_xmlns() */ 10911 nsalloc_teardown(); 10912 nsalloc_setup(); 10913 } 10914 if (i == 0) 10915 fail("Parsing worked despite failing reallocations"); 10916 else if (i == max_realloc_count) 10917 fail("Parsing failed even at max reallocation count"); 10918 } 10919 10920 START_TEST(test_nsalloc_realloc_long_context) { 10921 const char *text 10922 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10923 " <!ENTITY en SYSTEM 'bar'>\n" 10924 "]>\n" 10925 "<doc xmlns='http://example.org/" 10926 /* 64 characters per line */ 10927 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10928 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10929 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10930 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10931 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10932 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10933 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10934 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10935 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10936 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10937 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10938 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10939 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10940 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10941 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10942 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL" 10943 "'>\n" 10944 "&en;" 10945 "</doc>"; 10946 10947 context_realloc_test(text); 10948 } 10949 END_TEST 10950 10951 START_TEST(test_nsalloc_realloc_long_context_2) { 10952 const char *text 10953 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10954 " <!ENTITY en SYSTEM 'bar'>\n" 10955 "]>\n" 10956 "<doc xmlns='http://example.org/" 10957 /* 64 characters per line */ 10958 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10959 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10960 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10961 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10962 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10963 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10964 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10965 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10966 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10967 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10968 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10969 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10970 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10971 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10972 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10973 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK" 10974 "'>\n" 10975 "&en;" 10976 "</doc>"; 10977 10978 context_realloc_test(text); 10979 } 10980 END_TEST 10981 10982 START_TEST(test_nsalloc_realloc_long_context_3) { 10983 const char *text 10984 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 10985 " <!ENTITY en SYSTEM 'bar'>\n" 10986 "]>\n" 10987 "<doc xmlns='http://example.org/" 10988 /* 64 characters per line */ 10989 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10990 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10991 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10992 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10993 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10994 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10995 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10996 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10997 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10998 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 10999 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11000 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11001 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11002 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11003 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11004 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH" 11005 "'>\n" 11006 "&en;" 11007 "</doc>"; 11008 11009 context_realloc_test(text); 11010 } 11011 END_TEST 11012 11013 START_TEST(test_nsalloc_realloc_long_context_4) { 11014 const char *text 11015 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11016 " <!ENTITY en SYSTEM 'bar'>\n" 11017 "]>\n" 11018 "<doc xmlns='http://example.org/" 11019 /* 64 characters per line */ 11020 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11021 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11022 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11023 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11024 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11025 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11026 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11027 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11028 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11029 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11030 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11031 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11032 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11033 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11034 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11035 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO" 11036 "'>\n" 11037 "&en;" 11038 "</doc>"; 11039 11040 context_realloc_test(text); 11041 } 11042 END_TEST 11043 11044 START_TEST(test_nsalloc_realloc_long_context_5) { 11045 const char *text 11046 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11047 " <!ENTITY en SYSTEM 'bar'>\n" 11048 "]>\n" 11049 "<doc xmlns='http://example.org/" 11050 /* 64 characters per line */ 11051 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11052 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11053 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11054 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11055 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11056 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11057 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11058 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11059 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11060 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11061 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11062 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11063 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11064 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11065 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11066 "ABC" 11067 "'>\n" 11068 "&en;" 11069 "</doc>"; 11070 11071 context_realloc_test(text); 11072 } 11073 END_TEST 11074 11075 START_TEST(test_nsalloc_realloc_long_context_6) { 11076 const char *text 11077 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11078 " <!ENTITY en SYSTEM 'bar'>\n" 11079 "]>\n" 11080 "<doc xmlns='http://example.org/" 11081 /* 64 characters per line */ 11082 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11083 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11084 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11085 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11086 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11087 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11088 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11089 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11090 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11091 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11092 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11093 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11094 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11095 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11096 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP" 11097 "'>\n" 11098 "&en;" 11099 "</doc>"; 11100 11101 context_realloc_test(text); 11102 } 11103 END_TEST 11104 11105 START_TEST(test_nsalloc_realloc_long_context_7) { 11106 const char *text 11107 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11108 " <!ENTITY en SYSTEM 'bar'>\n" 11109 "]>\n" 11110 "<doc xmlns='http://example.org/" 11111 /* 64 characters per line */ 11112 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11113 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11114 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11115 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11116 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11117 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11118 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11119 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11120 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11121 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11122 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11123 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11124 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11125 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11126 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11127 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM" 11128 "'>\n" 11129 "&en;" 11130 "</doc>"; 11131 11132 context_realloc_test(text); 11133 } 11134 END_TEST 11135 11136 START_TEST(test_nsalloc_realloc_long_ge_name) { 11137 const char *text 11138 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11139 " <!ENTITY " 11140 /* 64 characters per line */ 11141 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11142 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11143 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11144 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11145 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11146 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11147 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11148 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11149 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11150 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11151 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11152 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11153 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11154 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11155 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11156 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11157 " SYSTEM 'bar'>\n" 11158 "]>\n" 11159 "<doc xmlns='http://example.org/baz'>\n" 11160 "&" 11161 /* 64 characters per line */ 11162 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11163 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11164 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11165 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11166 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11167 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11168 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11169 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11170 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11171 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11172 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11173 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11174 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11175 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11176 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11177 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11178 ";" 11179 "</doc>"; 11180 ExtOption options[] = { 11181 {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}}; 11182 int i; 11183 const int max_realloc_count = 10; 11184 11185 for (i = 0; i < max_realloc_count; i++) { 11186 reallocation_count = i; 11187 XML_SetUserData(g_parser, options); 11188 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11189 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11190 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11191 != XML_STATUS_ERROR) 11192 break; 11193 /* See comment in test_nsalloc_xmlns() */ 11194 nsalloc_teardown(); 11195 nsalloc_setup(); 11196 } 11197 if (i == 0) 11198 fail("Parsing worked despite failing reallocations"); 11199 else if (i == max_realloc_count) 11200 fail("Parsing failed even at max reallocation count"); 11201 } 11202 END_TEST 11203 11204 /* Test that when a namespace is passed through the context mechanism 11205 * to an external entity parser, the parsers handle reallocation 11206 * failures correctly. The prefix is exactly the right length to 11207 * provoke particular uncommon code paths. 11208 */ 11209 START_TEST(test_nsalloc_realloc_long_context_in_dtd) { 11210 const char *text1 11211 = "<!DOCTYPE " 11212 /* 64 characters per line */ 11213 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11214 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11215 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11216 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11217 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11218 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11219 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11220 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11221 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11222 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11223 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11224 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11225 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11226 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11227 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11228 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11229 ":doc [\n" 11230 " <!ENTITY First SYSTEM 'foo/First'>\n" 11231 "]>\n" 11232 "<" 11233 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11234 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11235 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11236 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11237 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11238 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11239 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11240 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11241 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11242 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11243 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11244 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11245 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11246 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11247 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11248 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11249 ":doc xmlns:" 11250 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11251 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11252 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11253 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11254 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11255 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11256 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11257 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11258 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11259 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11260 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11261 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11262 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11263 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11264 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11265 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11266 "='foo/Second'>&First;"; 11267 const char *text2 11268 = "</" 11269 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11270 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11271 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11272 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11273 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11274 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11275 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11276 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11277 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11278 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11279 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11280 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11281 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11282 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11283 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11284 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11285 ":doc>"; 11286 ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}}; 11287 int i; 11288 const int max_realloc_count = 20; 11289 11290 for (i = 0; i < max_realloc_count; i++) { 11291 reallocation_count = i; 11292 XML_SetUserData(g_parser, options); 11293 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11294 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11295 if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE) 11296 != XML_STATUS_ERROR 11297 && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), 11298 XML_TRUE) 11299 != XML_STATUS_ERROR) 11300 break; 11301 /* See comment in test_nsalloc_xmlns() */ 11302 nsalloc_teardown(); 11303 nsalloc_setup(); 11304 } 11305 if (i == 0) 11306 fail("Parsing worked despite failing reallocations"); 11307 else if (i == max_realloc_count) 11308 fail("Parsing failed even at max reallocation count"); 11309 } 11310 END_TEST 11311 11312 START_TEST(test_nsalloc_long_default_in_ext) { 11313 const char *text 11314 = "<!DOCTYPE doc [\n" 11315 " <!ATTLIST e a1 CDATA '" 11316 /* 64 characters per line */ 11317 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11318 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11319 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11320 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11321 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11322 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11323 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11324 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11325 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11326 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11327 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11328 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11329 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11330 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11331 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11332 "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" 11333 "'>\n" 11334 " <!ENTITY x SYSTEM 'foo'>\n" 11335 "]>\n" 11336 "<doc>&x;</doc>"; 11337 ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}}; 11338 int i; 11339 const int max_alloc_count = 50; 11340 11341 for (i = 0; i < max_alloc_count; i++) { 11342 allocation_count = i; 11343 XML_SetUserData(g_parser, options); 11344 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11345 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11346 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11347 != XML_STATUS_ERROR) 11348 break; 11349 11350 /* See comment in test_nsalloc_xmlns() */ 11351 nsalloc_teardown(); 11352 nsalloc_setup(); 11353 } 11354 if (i == 0) 11355 fail("Parsing worked despite failing allocations"); 11356 else if (i == max_alloc_count) 11357 fail("Parsing failed even at max allocation count"); 11358 } 11359 END_TEST 11360 11361 START_TEST(test_nsalloc_long_systemid_in_ext) { 11362 const char *text 11363 = "<!DOCTYPE doc SYSTEM 'foo' [\n" 11364 " <!ENTITY en SYSTEM '" 11365 /* 64 characters per line */ 11366 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11367 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11368 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11369 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11370 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11371 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11372 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11373 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11374 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11375 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11376 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11377 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11378 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11379 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11380 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11381 "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/" 11382 "'>\n" 11383 "]>\n" 11384 "<doc>&en;</doc>"; 11385 ExtOption options[] = { 11386 {XCS("foo"), "<!ELEMENT e EMPTY>"}, 11387 {/* clang-format off */ 11388 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11389 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11390 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11391 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11392 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11393 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11394 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11395 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11396 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11397 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11398 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11399 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11400 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11401 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11402 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/") 11403 XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"), 11404 /* clang-format on */ 11405 "<e/>"}, 11406 {NULL, NULL}}; 11407 int i; 11408 const int max_alloc_count = 55; 11409 11410 for (i = 0; i < max_alloc_count; i++) { 11411 allocation_count = i; 11412 XML_SetUserData(g_parser, options); 11413 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11414 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11415 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11416 != XML_STATUS_ERROR) 11417 break; 11418 11419 /* See comment in test_nsalloc_xmlns() */ 11420 nsalloc_teardown(); 11421 nsalloc_setup(); 11422 } 11423 if (i == 0) 11424 fail("Parsing worked despite failing allocations"); 11425 else if (i == max_alloc_count) 11426 fail("Parsing failed even at max allocation count"); 11427 } 11428 END_TEST 11429 11430 /* Test the effects of allocation failure on parsing an element in a 11431 * namespace. Based on test_nsalloc_long_context. 11432 */ 11433 START_TEST(test_nsalloc_prefixed_element) { 11434 const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n" 11435 " <!ATTLIST pfx:element baz ID #REQUIRED>\n" 11436 " <!ENTITY en SYSTEM 'bar'>\n" 11437 "]>\n" 11438 "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n" 11439 "&en;" 11440 "</pfx:element>"; 11441 ExtOption options[] = { 11442 {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}}; 11443 int i; 11444 const int max_alloc_count = 70; 11445 11446 for (i = 0; i < max_alloc_count; i++) { 11447 allocation_count = i; 11448 XML_SetUserData(g_parser, options); 11449 XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11450 XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); 11451 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) 11452 != XML_STATUS_ERROR) 11453 break; 11454 11455 /* See comment in test_nsalloc_xmlns() */ 11456 nsalloc_teardown(); 11457 nsalloc_setup(); 11458 } 11459 if (i == 0) 11460 fail("Success despite failing allocator"); 11461 else if (i == max_alloc_count) 11462 fail("Failed even at full allocation count"); 11463 } 11464 END_TEST 11465 11466 #if defined(XML_DTD) 11467 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int); 11468 11469 struct AccountingTestCase { 11470 const char *primaryText; 11471 const char *firstExternalText; /* often NULL */ 11472 const char *secondExternalText; /* often NULL */ 11473 const unsigned long long expectedCountBytesIndirectExtra; 11474 XML_Bool singleBytesWanted; 11475 }; 11476 11477 static int 11478 accounting_external_entity_ref_handler(XML_Parser parser, 11479 const XML_Char *context, 11480 const XML_Char *base, 11481 const XML_Char *systemId, 11482 const XML_Char *publicId) { 11483 UNUSED_P(context); 11484 UNUSED_P(base); 11485 UNUSED_P(publicId); 11486 11487 const struct AccountingTestCase *const testCase 11488 = (const struct AccountingTestCase *)XML_GetUserData(parser); 11489 11490 const char *externalText = NULL; 11491 if (xcstrcmp(systemId, XCS("first.ent")) == 0) { 11492 externalText = testCase->firstExternalText; 11493 } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) { 11494 externalText = testCase->secondExternalText; 11495 } else { 11496 assert(! "systemId is neither \"first.ent\" nor \"second.ent\""); 11497 } 11498 assert(externalText); 11499 11500 XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); 11501 assert(entParser); 11502 11503 const XmlParseFunction xmlParseFunction 11504 = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11505 11506 const enum XML_Status status = xmlParseFunction( 11507 entParser, externalText, (int)strlen(externalText), XML_TRUE); 11508 11509 XML_ParserFree(entParser); 11510 return status; 11511 } 11512 11513 START_TEST(test_accounting_precision) { 11514 const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */ 11515 struct AccountingTestCase cases[] = { 11516 {"<e/>", NULL, NULL, 0, 0}, 11517 {"<e></e>", NULL, NULL, 0, 0}, 11518 11519 /* Attributes */ 11520 {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later}, 11521 {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0}, 11522 {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0, 11523 filled_later}, 11524 {"<e k=\"&'><"\" />", NULL, NULL, 11525 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11526 {"<e1 xmlns='https://example.org/'>\n" 11527 " <e2 xmlns=''/>\n" 11528 "</e1>", 11529 NULL, NULL, 0, filled_later}, 11530 11531 /* Text */ 11532 {"<e>text</e>", NULL, NULL, 0, filled_later}, 11533 {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later}, 11534 {"<e>&'><"</e>", NULL, NULL, 11535 sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later}, 11536 {"<e>A)</e>", NULL, NULL, 0, filled_later}, 11537 11538 /* Prolog */ 11539 {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later}, 11540 11541 /* Whitespace */ 11542 {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later}, 11543 {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later}, 11544 {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later}, 11545 11546 /* Comments */ 11547 {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later}, 11548 11549 /* Processing instructions */ 11550 {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>", 11551 NULL, NULL, 0, filled_later}, 11552 {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>", 11553 "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>", 11554 0, filled_later}, 11555 11556 /* CDATA */ 11557 {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later}, 11558 /* The following is the essence of this OSS-Fuzz finding: 11559 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302 11560 https://oss-fuzz.com/testcase-detail/4860575394955264 11561 */ 11562 {"<!DOCTYPE r [\n" 11563 "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n" 11564 "]>\n" 11565 "<r>&e;</r>\n", 11566 NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"), 11567 filled_later}, 11568 11569 /* Conditional sections */ 11570 {"<!DOCTYPE r [\n" 11571 "<!ENTITY % draft 'INCLUDE'>\n" 11572 "<!ENTITY % final 'IGNORE'>\n" 11573 "<!ENTITY % import SYSTEM \"first.ent\">\n" 11574 "%import;\n" 11575 "]>\n" 11576 "<r/>\n", 11577 "<![%draft;[<!--1-->]]>\n" 11578 "<![%final;[<!--22-->]]>", 11579 NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")), 11580 filled_later}, 11581 11582 /* General entities */ 11583 {"<!DOCTYPE root [\n" 11584 "<!ENTITY nine \"123456789\">\n" 11585 "]>\n" 11586 "<root>&nine;</root>", 11587 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11588 {"<!DOCTYPE root [\n" 11589 "<!ENTITY nine \"123456789\">\n" 11590 "]>\n" 11591 "<root k1=\"&nine;\"/>", 11592 NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, 11593 {"<!DOCTYPE root [\n" 11594 "<!ENTITY nine \"123456789\">\n" 11595 "<!ENTITY nine2 \"&nine;&nine;\">\n" 11596 "]>\n" 11597 "<root>&nine2;&nine2;&nine2;</root>", 11598 NULL, NULL, 11599 sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */ 11600 * (strlen("&nine;") + strlen("123456789")), 11601 filled_later}, 11602 {"<!DOCTYPE r [\n" 11603 " <!ENTITY five SYSTEM 'first.ent'>\n" 11604 "]>\n" 11605 "<r>&five;</r>", 11606 "12345", NULL, 0, filled_later}, 11607 11608 /* Parameter entities */ 11609 {"<!DOCTYPE r [\n" 11610 "<!ENTITY % comment \"<!---->\">\n" 11611 "%comment;\n" 11612 "]>\n" 11613 "<r/>", 11614 NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later}, 11615 {"<!DOCTYPE r [\n" 11616 "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n" 11617 "%ninedef;\n" 11618 "]>\n" 11619 "<r>&nine;</r>", 11620 NULL, NULL, 11621 sizeof(XML_Char) 11622 * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")), 11623 filled_later}, 11624 {"<!DOCTYPE r [\n" 11625 "<!ENTITY % comment \"<!--1-->\">\n" 11626 "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n" 11627 "%comment2;\n" 11628 "]>\n" 11629 "<r/>\n", 11630 NULL, NULL, 11631 sizeof(XML_Char) 11632 * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")), 11633 filled_later}, 11634 {"<!DOCTYPE r [\n" 11635 " <!ENTITY % five \"12345\">\n" 11636 " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n" 11637 " %five2def;\n" 11638 "]>\n" 11639 "<r>&five2;</r>", 11640 NULL, NULL, /* from "%five2def;": */ 11641 sizeof(XML_Char) 11642 * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">") 11643 + 2 /* calls to "%five;" */ * strlen("12345") 11644 + /* from "&five2;": */ strlen("[12345][12345]]]]")), 11645 filled_later}, 11646 {"<!DOCTYPE r SYSTEM \"first.ent\">\n" 11647 "<r/>", 11648 "<!ENTITY % comment '<!--1-->'>\n" 11649 "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n" 11650 "%comment2;", 11651 NULL, 11652 sizeof(XML_Char) 11653 * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->") 11654 + 2 /* calls to "%comment;" */ * strlen("<!---->")), 11655 filled_later}, 11656 {"<!DOCTYPE r SYSTEM 'first.ent'>\n" 11657 "<r/>", 11658 "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n" 11659 "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n" 11660 "%e2;\n", 11661 "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"), 11662 filled_later}, 11663 { 11664 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11665 "<r/>", 11666 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11667 "<!ENTITY % e2 '%e1;'>", 11668 "<?xml version='1.0' encoding='utf-8'?>\n" 11669 "hello\n" 11670 "xml" /* without trailing newline! */, 11671 0, 11672 filled_later, 11673 }, 11674 { 11675 "<!DOCTYPE r SYSTEM 'first.ent'>\n" 11676 "<r/>", 11677 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11678 "<!ENTITY % e2 '%e1;'>", 11679 "<?xml version='1.0' encoding='utf-8'?>\n" 11680 "hello\n" 11681 "xml\n" /* with trailing newline! */, 11682 0, 11683 filled_later, 11684 }, 11685 {"<!DOCTYPE doc SYSTEM 'first.ent'>\n" 11686 "<doc></doc>\n", 11687 "<!ELEMENT doc EMPTY>\n" 11688 "<!ENTITY % e1 SYSTEM 'second.ent'>\n" 11689 "<!ENTITY % e2 '%e1;'>\n" 11690 "%e1;\n", 11691 "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */, 11692 strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later}, 11693 {"<!DOCTYPE r [\n" 11694 " <!ENTITY five SYSTEM 'first.ent'>\n" 11695 "]>\n" 11696 "<r>&five;</r>", 11697 "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later}, 11698 }; 11699 11700 const size_t countCases = sizeof(cases) / sizeof(cases[0]); 11701 size_t u = 0; 11702 for (; u < countCases; u++) { 11703 size_t v = 0; 11704 for (; v < 2; v++) { 11705 const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE; 11706 const unsigned long long expectedCountBytesDirect 11707 = strlen(cases[u].primaryText); 11708 const unsigned long long expectedCountBytesIndirect 11709 = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText) 11710 : 0) 11711 + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText) 11712 : 0) 11713 + cases[u].expectedCountBytesIndirectExtra; 11714 11715 XML_Parser parser = XML_ParserCreate(NULL); 11716 XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); 11717 if (cases[u].firstExternalText) { 11718 XML_SetExternalEntityRefHandler(parser, 11719 accounting_external_entity_ref_handler); 11720 XML_SetUserData(parser, (void *)&cases[u]); 11721 cases[u].singleBytesWanted = singleBytesWanted; 11722 } 11723 11724 const XmlParseFunction xmlParseFunction 11725 = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; 11726 11727 enum XML_Status status 11728 = xmlParseFunction(parser, cases[u].primaryText, 11729 (int)strlen(cases[u].primaryText), XML_TRUE); 11730 if (status != XML_STATUS_OK) { 11731 _xml_failure(parser, __FILE__, __LINE__); 11732 } 11733 11734 const unsigned long long actualCountBytesDirect 11735 = testingAccountingGetCountBytesDirect(parser); 11736 const unsigned long long actualCountBytesIndirect 11737 = testingAccountingGetCountBytesIndirect(parser); 11738 11739 XML_ParserFree(parser); 11740 11741 if (actualCountBytesDirect != expectedCountBytesDirect) { 11742 fprintf( 11743 stderr, 11744 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11745 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11746 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11747 expectedCountBytesDirect, actualCountBytesDirect); 11748 fail("Count of direct bytes is off"); 11749 } 11750 11751 if (actualCountBytesIndirect != expectedCountBytesIndirect) { 11752 fprintf( 11753 stderr, 11754 "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( 11755 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n", 11756 u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", 11757 expectedCountBytesIndirect, actualCountBytesIndirect); 11758 fail("Count of indirect bytes is off"); 11759 } 11760 } 11761 } 11762 } 11763 END_TEST 11764 11765 START_TEST(test_billion_laughs_attack_protection_api) { 11766 XML_Parser parserWithoutParent = XML_ParserCreate(NULL); 11767 XML_Parser parserWithParent 11768 = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL); 11769 if (parserWithoutParent == NULL) 11770 fail("parserWithoutParent is NULL"); 11771 if (parserWithParent == NULL) 11772 fail("parserWithParent is NULL"); 11773 11774 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases 11775 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f) 11776 == XML_TRUE) 11777 fail("Call with NULL parser is NOT supposed to succeed"); 11778 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent, 11779 123.0f) 11780 == XML_TRUE) 11781 fail("Call with non-root parser is NOT supposed to succeed"); 11782 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11783 parserWithoutParent, NAN) 11784 == XML_TRUE) 11785 fail("Call with NaN limit is NOT supposed to succeed"); 11786 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11787 parserWithoutParent, -1.0f) 11788 == XML_TRUE) 11789 fail("Call with negative limit is NOT supposed to succeed"); 11790 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11791 parserWithoutParent, 0.9f) 11792 == XML_TRUE) 11793 fail("Call with positive limit <1.0 is NOT supposed to succeed"); 11794 11795 // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases 11796 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11797 parserWithoutParent, 1.0f) 11798 == XML_FALSE) 11799 fail("Call with positive limit >=1.0 is supposed to succeed"); 11800 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11801 parserWithoutParent, 123456.789f) 11802 == XML_FALSE) 11803 fail("Call with positive limit >=1.0 is supposed to succeed"); 11804 if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( 11805 parserWithoutParent, INFINITY) 11806 == XML_FALSE) 11807 fail("Call with positive limit >=1.0 is supposed to succeed"); 11808 11809 // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases 11810 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123) 11811 == XML_TRUE) 11812 fail("Call with NULL parser is NOT supposed to succeed"); 11813 if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent, 11814 123) 11815 == XML_TRUE) 11816 fail("Call with non-root parser is NOT supposed to succeed"); 11817 11818 // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases 11819 if (XML_SetBillionLaughsAttackProtectionActivationThreshold( 11820 parserWithoutParent, 123) 11821 == XML_FALSE) 11822 fail("Call with non-NULL parentless parser is supposed to succeed"); 11823 11824 XML_ParserFree(parserWithParent); 11825 XML_ParserFree(parserWithoutParent); 11826 } 11827 END_TEST 11828 11829 START_TEST(test_helper_unsigned_char_to_printable) { 11830 // Smoke test 11831 unsigned char uc = 0; 11832 for (; uc < (unsigned char)-1; uc++) { 11833 const char *const printable = unsignedCharToPrintable(uc); 11834 if (printable == NULL) 11835 fail("unsignedCharToPrintable returned NULL"); 11836 if (strlen(printable) < (size_t)1) 11837 fail("unsignedCharToPrintable returned empty string"); 11838 } 11839 11840 // Two concrete samples 11841 if (strcmp(unsignedCharToPrintable('A'), "A") != 0) 11842 fail("unsignedCharToPrintable result mistaken"); 11843 if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0) 11844 fail("unsignedCharToPrintable result mistaken"); 11845 } 11846 END_TEST 11847 #endif // defined(XML_DTD) 11848 11849 static Suite * 11850 make_suite(void) { 11851 Suite *s = suite_create("basic"); 11852 TCase *tc_basic = tcase_create("basic tests"); 11853 TCase *tc_namespace = tcase_create("XML namespaces"); 11854 TCase *tc_misc = tcase_create("miscellaneous tests"); 11855 TCase *tc_alloc = tcase_create("allocation tests"); 11856 TCase *tc_nsalloc = tcase_create("namespace allocation tests"); 11857 #if defined(XML_DTD) 11858 TCase *tc_accounting = tcase_create("accounting tests"); 11859 #endif 11860 11861 suite_add_tcase(s, tc_basic); 11862 tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown); 11863 tcase_add_test(tc_basic, test_nul_byte); 11864 tcase_add_test(tc_basic, test_u0000_char); 11865 tcase_add_test(tc_basic, test_siphash_self); 11866 tcase_add_test(tc_basic, test_siphash_spec); 11867 tcase_add_test(tc_basic, test_bom_utf8); 11868 tcase_add_test(tc_basic, test_bom_utf16_be); 11869 tcase_add_test(tc_basic, test_bom_utf16_le); 11870 tcase_add_test(tc_basic, test_nobom_utf16_le); 11871 tcase_add_test(tc_basic, test_illegal_utf8); 11872 tcase_add_test(tc_basic, test_utf8_auto_align); 11873 tcase_add_test(tc_basic, test_utf16); 11874 tcase_add_test(tc_basic, test_utf16_le_epilog_newline); 11875 tcase_add_test(tc_basic, test_not_utf16); 11876 tcase_add_test(tc_basic, test_bad_encoding); 11877 tcase_add_test(tc_basic, test_latin1_umlauts); 11878 tcase_add_test(tc_basic, test_long_utf8_character); 11879 tcase_add_test(tc_basic, test_long_latin1_attribute); 11880 tcase_add_test(tc_basic, test_long_ascii_attribute); 11881 /* Regression test for SF bug #491986. */ 11882 tcase_add_test(tc_basic, test_danish_latin1); 11883 /* Regression test for SF bug #514281. */ 11884 tcase_add_test(tc_basic, test_french_charref_hexidecimal); 11885 tcase_add_test(tc_basic, test_french_charref_decimal); 11886 tcase_add_test(tc_basic, test_french_latin1); 11887 tcase_add_test(tc_basic, test_french_utf8); 11888 tcase_add_test(tc_basic, test_utf8_false_rejection); 11889 tcase_add_test(tc_basic, test_line_number_after_parse); 11890 tcase_add_test(tc_basic, test_column_number_after_parse); 11891 tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers); 11892 tcase_add_test(tc_basic, test_line_number_after_error); 11893 tcase_add_test(tc_basic, test_column_number_after_error); 11894 tcase_add_test(tc_basic, test_really_long_lines); 11895 tcase_add_test(tc_basic, test_really_long_encoded_lines); 11896 tcase_add_test(tc_basic, test_end_element_events); 11897 tcase_add_test(tc_basic, test_attr_whitespace_normalization); 11898 tcase_add_test(tc_basic, test_xmldecl_misplaced); 11899 tcase_add_test(tc_basic, test_xmldecl_invalid); 11900 tcase_add_test(tc_basic, test_xmldecl_missing_attr); 11901 tcase_add_test(tc_basic, test_xmldecl_missing_value); 11902 tcase_add_test(tc_basic, test_unknown_encoding_internal_entity); 11903 tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity); 11904 tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset); 11905 tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset); 11906 tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone); 11907 tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset); 11908 tcase_add_test(tc_basic, test_not_standalone_handler_reject); 11909 tcase_add_test(tc_basic, test_not_standalone_handler_accept); 11910 tcase_add_test(tc_basic, 11911 test_wfc_undeclared_entity_with_external_subset_standalone); 11912 tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone); 11913 tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs); 11914 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding); 11915 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler); 11916 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom); 11917 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding); 11918 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2); 11919 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse); 11920 tcase_add_test__ifdef_xml_dtd(tc_basic, 11921 test_ext_entity_invalid_suspended_parse); 11922 tcase_add_test(tc_basic, test_dtd_default_handling); 11923 tcase_add_test(tc_basic, test_dtd_attr_handling); 11924 tcase_add_test(tc_basic, test_empty_ns_without_namespaces); 11925 tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces); 11926 tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls); 11927 tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls); 11928 tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls); 11929 tcase_add_test(tc_basic, test_good_cdata_ascii); 11930 tcase_add_test(tc_basic, test_good_cdata_utf16); 11931 tcase_add_test(tc_basic, test_good_cdata_utf16_le); 11932 tcase_add_test(tc_basic, test_long_cdata_utf16); 11933 tcase_add_test(tc_basic, test_multichar_cdata_utf16); 11934 tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair); 11935 tcase_add_test(tc_basic, test_bad_cdata); 11936 tcase_add_test(tc_basic, test_bad_cdata_utf16); 11937 tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls); 11938 tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls); 11939 tcase_add_test(tc_basic, test_memory_allocation); 11940 tcase_add_test(tc_basic, test_default_current); 11941 tcase_add_test(tc_basic, test_dtd_elements); 11942 tcase_add_test(tc_basic, test_dtd_elements_nesting); 11943 tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd); 11944 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone); 11945 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd); 11946 tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype); 11947 tcase_add_test__ifdef_xml_dtd(tc_basic, 11948 test_foreign_dtd_without_external_subset); 11949 tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd); 11950 tcase_add_test(tc_basic, test_set_base); 11951 tcase_add_test(tc_basic, test_attributes); 11952 tcase_add_test(tc_basic, test_reset_in_entity); 11953 tcase_add_test(tc_basic, test_resume_invalid_parse); 11954 tcase_add_test(tc_basic, test_resume_resuspended); 11955 tcase_add_test(tc_basic, test_cdata_default); 11956 tcase_add_test(tc_basic, test_subordinate_reset); 11957 tcase_add_test(tc_basic, test_subordinate_suspend); 11958 tcase_add_test(tc_basic, test_subordinate_xdecl_suspend); 11959 tcase_add_test(tc_basic, test_subordinate_xdecl_abort); 11960 tcase_add_test(tc_basic, test_explicit_encoding); 11961 tcase_add_test(tc_basic, test_trailing_cr); 11962 tcase_add_test(tc_basic, test_ext_entity_trailing_cr); 11963 tcase_add_test(tc_basic, test_trailing_rsqb); 11964 tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb); 11965 tcase_add_test(tc_basic, test_ext_entity_good_cdata); 11966 tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters); 11967 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter); 11968 tcase_add_test(tc_basic, test_empty_parse); 11969 tcase_add_test(tc_basic, test_get_buffer_1); 11970 tcase_add_test(tc_basic, test_get_buffer_2); 11971 #if defined(XML_CONTEXT_BYTES) 11972 tcase_add_test(tc_basic, test_get_buffer_3_overflow); 11973 #endif 11974 tcase_add_test(tc_basic, test_byte_info_at_end); 11975 tcase_add_test(tc_basic, test_byte_info_at_error); 11976 tcase_add_test(tc_basic, test_byte_info_at_cdata); 11977 tcase_add_test(tc_basic, test_predefined_entities); 11978 tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd); 11979 tcase_add_test(tc_basic, test_not_predefined_entities); 11980 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section); 11981 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16); 11982 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be); 11983 tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section); 11984 tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values); 11985 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone); 11986 tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort); 11987 tcase_add_test(tc_basic, test_bad_public_doctype); 11988 tcase_add_test(tc_basic, test_attribute_enum_value); 11989 tcase_add_test(tc_basic, test_predefined_entity_redefinition); 11990 tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing); 11991 tcase_add_test(tc_basic, test_public_notation_no_sysid); 11992 tcase_add_test(tc_basic, test_nested_groups); 11993 tcase_add_test(tc_basic, test_group_choice); 11994 tcase_add_test(tc_basic, test_standalone_parameter_entity); 11995 tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity); 11996 tcase_add_test__ifdef_xml_dtd(tc_basic, 11997 test_recursive_external_parameter_entity); 11998 tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd); 11999 tcase_add_test(tc_basic, test_suspend_xdecl); 12000 tcase_add_test(tc_basic, test_abort_epilog); 12001 tcase_add_test(tc_basic, test_abort_epilog_2); 12002 tcase_add_test(tc_basic, test_suspend_epilog); 12003 tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag); 12004 tcase_add_test(tc_basic, test_unfinished_epilog); 12005 tcase_add_test(tc_basic, test_partial_char_in_epilog); 12006 tcase_add_test(tc_basic, test_hash_collision); 12007 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity); 12008 tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error); 12009 tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity); 12010 tcase_add_test(tc_basic, test_restart_on_error); 12011 tcase_add_test(tc_basic, test_reject_lt_in_attribute_value); 12012 tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value); 12013 tcase_add_test(tc_basic, test_trailing_cr_in_att_value); 12014 tcase_add_test(tc_basic, test_standalone_internal_entity); 12015 tcase_add_test(tc_basic, test_skipped_external_entity); 12016 tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity); 12017 tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity); 12018 tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr); 12019 tcase_add_test(tc_basic, test_invalid_character_entity); 12020 tcase_add_test(tc_basic, test_invalid_character_entity_2); 12021 tcase_add_test(tc_basic, test_invalid_character_entity_3); 12022 tcase_add_test(tc_basic, test_invalid_character_entity_4); 12023 tcase_add_test(tc_basic, test_pi_handled_in_default); 12024 tcase_add_test(tc_basic, test_comment_handled_in_default); 12025 tcase_add_test(tc_basic, test_pi_yml); 12026 tcase_add_test(tc_basic, test_pi_xnl); 12027 tcase_add_test(tc_basic, test_pi_xmm); 12028 tcase_add_test(tc_basic, test_utf16_pi); 12029 tcase_add_test(tc_basic, test_utf16_be_pi); 12030 tcase_add_test(tc_basic, test_utf16_be_comment); 12031 tcase_add_test(tc_basic, test_utf16_le_comment); 12032 tcase_add_test(tc_basic, test_missing_encoding_conversion_fn); 12033 tcase_add_test(tc_basic, test_failing_encoding_conversion_fn); 12034 tcase_add_test(tc_basic, test_unknown_encoding_success); 12035 tcase_add_test(tc_basic, test_unknown_encoding_bad_name); 12036 tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2); 12037 tcase_add_test(tc_basic, test_unknown_encoding_long_name_1); 12038 tcase_add_test(tc_basic, test_unknown_encoding_long_name_2); 12039 tcase_add_test(tc_basic, test_invalid_unknown_encoding); 12040 tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok); 12041 tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail); 12042 tcase_add_test(tc_basic, test_unknown_encoding_invalid_length); 12043 tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit); 12044 tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate); 12045 tcase_add_test(tc_basic, test_unknown_encoding_invalid_high); 12046 tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value); 12047 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom); 12048 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom); 12049 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2); 12050 tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2); 12051 tcase_add_test(tc_basic, test_ext_entity_utf16_be); 12052 tcase_add_test(tc_basic, test_ext_entity_utf16_le); 12053 tcase_add_test(tc_basic, test_ext_entity_utf16_unknown); 12054 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom); 12055 tcase_add_test(tc_basic, test_utf8_in_cdata_section); 12056 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2); 12057 tcase_add_test(tc_basic, test_utf8_in_start_tags); 12058 tcase_add_test(tc_basic, test_trailing_spaces_in_elements); 12059 tcase_add_test(tc_basic, test_utf16_attribute); 12060 tcase_add_test(tc_basic, test_utf16_second_attr); 12061 tcase_add_test(tc_basic, test_attr_after_solidus); 12062 tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe); 12063 tcase_add_test(tc_basic, test_bad_attr_desc_keyword); 12064 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16); 12065 tcase_add_test(tc_basic, test_bad_doctype); 12066 tcase_add_test(tc_basic, test_bad_doctype_utf8); 12067 tcase_add_test(tc_basic, test_bad_doctype_utf16); 12068 tcase_add_test(tc_basic, test_bad_doctype_plus); 12069 tcase_add_test(tc_basic, test_bad_doctype_star); 12070 tcase_add_test(tc_basic, test_bad_doctype_query); 12071 tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore); 12072 tcase_add_test(tc_basic, test_entity_in_utf16_be_attr); 12073 tcase_add_test(tc_basic, test_entity_in_utf16_le_attr); 12074 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be); 12075 tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le); 12076 tcase_add_test(tc_basic, test_short_doctype); 12077 tcase_add_test(tc_basic, test_short_doctype_2); 12078 tcase_add_test(tc_basic, test_short_doctype_3); 12079 tcase_add_test(tc_basic, test_long_doctype); 12080 tcase_add_test(tc_basic, test_bad_entity); 12081 tcase_add_test(tc_basic, test_bad_entity_2); 12082 tcase_add_test(tc_basic, test_bad_entity_3); 12083 tcase_add_test(tc_basic, test_bad_entity_4); 12084 tcase_add_test(tc_basic, test_bad_notation); 12085 tcase_add_test(tc_basic, test_default_doctype_handler); 12086 tcase_add_test(tc_basic, test_empty_element_abort); 12087 12088 suite_add_tcase(s, tc_namespace); 12089 tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown); 12090 tcase_add_test(tc_namespace, test_return_ns_triplet); 12091 tcase_add_test(tc_namespace, test_ns_tagname_overwrite); 12092 tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet); 12093 tcase_add_test(tc_namespace, test_start_ns_clears_start_element); 12094 tcase_add_test__ifdef_xml_dtd(tc_namespace, 12095 test_default_ns_from_ext_subset_and_ext_ge); 12096 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1); 12097 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2); 12098 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3); 12099 tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4); 12100 tcase_add_test(tc_namespace, test_ns_unbound_prefix); 12101 tcase_add_test(tc_namespace, test_ns_default_with_empty_uri); 12102 tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes); 12103 tcase_add_test(tc_namespace, test_ns_duplicate_hashes); 12104 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute); 12105 tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element); 12106 tcase_add_test(tc_namespace, test_ns_parser_reset); 12107 tcase_add_test(tc_namespace, test_ns_long_element); 12108 tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts); 12109 tcase_add_test(tc_namespace, test_ns_extend_uri_buffer); 12110 tcase_add_test(tc_namespace, test_ns_reserved_attributes); 12111 tcase_add_test(tc_namespace, test_ns_reserved_attributes_2); 12112 tcase_add_test(tc_namespace, test_ns_extremely_long_prefix); 12113 tcase_add_test(tc_namespace, test_ns_unknown_encoding_success); 12114 tcase_add_test(tc_namespace, test_ns_double_colon); 12115 tcase_add_test(tc_namespace, test_ns_double_colon_element); 12116 tcase_add_test(tc_namespace, test_ns_bad_attr_leafname); 12117 tcase_add_test(tc_namespace, test_ns_bad_element_leafname); 12118 tcase_add_test(tc_namespace, test_ns_utf16_leafname); 12119 tcase_add_test(tc_namespace, test_ns_utf16_element_leafname); 12120 tcase_add_test(tc_namespace, test_ns_utf16_doctype); 12121 tcase_add_test(tc_namespace, test_ns_invalid_doctype); 12122 tcase_add_test(tc_namespace, test_ns_double_colon_doctype); 12123 tcase_add_test(tc_namespace, test_ns_separator_in_uri); 12124 12125 suite_add_tcase(s, tc_misc); 12126 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); 12127 tcase_add_test(tc_misc, test_misc_alloc_create_parser); 12128 tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding); 12129 tcase_add_test(tc_misc, test_misc_null_parser); 12130 tcase_add_test(tc_misc, test_misc_error_string); 12131 tcase_add_test(tc_misc, test_misc_version); 12132 tcase_add_test(tc_misc, test_misc_features); 12133 tcase_add_test(tc_misc, test_misc_attribute_leak); 12134 tcase_add_test(tc_misc, test_misc_utf16le); 12135 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1); 12136 tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2); 12137 tcase_add_test__ifdef_xml_dtd( 12138 tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317); 12139 12140 suite_add_tcase(s, tc_alloc); 12141 tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); 12142 tcase_add_test(tc_alloc, test_alloc_parse_xdecl); 12143 tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2); 12144 tcase_add_test(tc_alloc, test_alloc_parse_pi); 12145 tcase_add_test(tc_alloc, test_alloc_parse_pi_2); 12146 tcase_add_test(tc_alloc, test_alloc_parse_pi_3); 12147 tcase_add_test(tc_alloc, test_alloc_parse_comment); 12148 tcase_add_test(tc_alloc, test_alloc_parse_comment_2); 12149 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser); 12150 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser); 12151 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts); 12152 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity); 12153 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding); 12154 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity); 12155 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling); 12156 tcase_add_test(tc_alloc, test_alloc_explicit_encoding); 12157 tcase_add_test(tc_alloc, test_alloc_set_base); 12158 tcase_add_test(tc_alloc, test_alloc_realloc_buffer); 12159 tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer); 12160 tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes); 12161 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value); 12162 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12163 test_alloc_realloc_subst_public_entity_value); 12164 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype); 12165 tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name); 12166 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd); 12167 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value); 12168 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12169 test_alloc_realloc_attribute_enum_value); 12170 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute); 12171 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute); 12172 tcase_add_test(tc_alloc, test_alloc_notation); 12173 tcase_add_test(tc_alloc, test_alloc_public_notation); 12174 tcase_add_test(tc_alloc, test_alloc_system_notation); 12175 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups); 12176 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups); 12177 tcase_add_test(tc_alloc, test_alloc_large_group); 12178 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice); 12179 tcase_add_test(tc_alloc, test_alloc_pi_in_epilog); 12180 tcase_add_test(tc_alloc, test_alloc_comment_in_epilog); 12181 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12182 test_alloc_realloc_long_attribute_value); 12183 tcase_add_test(tc_alloc, test_alloc_attribute_whitespace); 12184 tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity); 12185 tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref); 12186 tcase_add_test(tc_alloc, test_alloc_long_attr_value); 12187 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities); 12188 tcase_add_test__ifdef_xml_dtd(tc_alloc, 12189 test_alloc_realloc_param_entity_newline); 12190 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe); 12191 tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes); 12192 tcase_add_test(tc_alloc, test_alloc_long_doc_name); 12193 tcase_add_test(tc_alloc, test_alloc_long_base); 12194 tcase_add_test(tc_alloc, test_alloc_long_public_id); 12195 tcase_add_test(tc_alloc, test_alloc_long_entity_value); 12196 tcase_add_test(tc_alloc, test_alloc_long_notation); 12197 12198 suite_add_tcase(s, tc_nsalloc); 12199 tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown); 12200 tcase_add_test(tc_nsalloc, test_nsalloc_xmlns); 12201 tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer); 12202 tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix); 12203 tcase_add_test(tc_nsalloc, test_nsalloc_long_uri); 12204 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr); 12205 tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix); 12206 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes); 12207 tcase_add_test(tc_nsalloc, test_nsalloc_long_element); 12208 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri); 12209 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix); 12210 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix); 12211 tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace); 12212 tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace); 12213 tcase_add_test(tc_nsalloc, test_nsalloc_long_context); 12214 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context); 12215 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2); 12216 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3); 12217 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4); 12218 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5); 12219 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6); 12220 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7); 12221 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name); 12222 tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd); 12223 tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext); 12224 tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext); 12225 tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element); 12226 12227 #if defined(XML_DTD) 12228 suite_add_tcase(s, tc_accounting); 12229 tcase_add_test(tc_accounting, test_accounting_precision); 12230 tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); 12231 tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); 12232 #endif 12233 12234 return s; 12235 } 12236 12237 int 12238 main(int argc, char *argv[]) { 12239 int i, nf; 12240 int verbosity = CK_NORMAL; 12241 Suite *s = make_suite(); 12242 SRunner *sr = srunner_create(s); 12243 12244 /* run the tests for internal helper functions */ 12245 testhelper_is_whitespace_normalized(); 12246 12247 for (i = 1; i < argc; ++i) { 12248 char *opt = argv[i]; 12249 if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0) 12250 verbosity = CK_VERBOSE; 12251 else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0) 12252 verbosity = CK_SILENT; 12253 else { 12254 fprintf(stderr, "runtests: unknown option '%s'\n", opt); 12255 return 2; 12256 } 12257 } 12258 if (verbosity != CK_SILENT) 12259 printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion()); 12260 srunner_run_all(sr, verbosity); 12261 nf = srunner_ntests_failed(sr); 12262 srunner_free(sr); 12263 12264 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 12265 } 12266