/* Tests in the "allocation" test case for the Expat test suite __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 2001-2006 Fred L. Drake, Jr. Copyright (c) 2003 Greg Stein Copyright (c) 2005-2007 Steven Solie Copyright (c) 2005-2012 Karl Waclawek Copyright (c) 2016-2023 Sebastian Pipping Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Joe Orton Copyright (c) 2017 José Gutiérrez de la Concha Copyright (c) 2018 Marco Maggi Copyright (c) 2019 David Loffredo Copyright (c) 2020 Tim Gates Copyright (c) 2021 Donghee Na Copyright (c) 2023 Sony Corporation / Snild Dolkow Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if defined(NDEBUG) # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif #include #include #include "expat.h" #include "common.h" #include "minicheck.h" #include "dummy.h" #include "handlers.h" #include "alloc_tests.h" static void alloc_setup(void) { XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; /* Ensure the parser creation will go through */ g_allocation_count = ALLOC_ALWAYS_SUCCEED; g_reallocation_count = REALLOC_ALWAYS_SUCCEED; g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); if (g_parser == NULL) fail("Parser not created"); } static void alloc_teardown(void) { basic_teardown(); } /* Test the effects of allocation failures on xml declaration processing */ START_TEST(test_alloc_parse_xdecl) { const char *text = "\n" "Hello, world"; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* Resetting the parser is insufficient, because some memory * allocations are cached within the parser. Instead we use * the teardown and setup routines to ensure that we have the * right sort of parser back in our hands. */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed with max allocations"); } END_TEST /* As above, but with an encoding big enough to cause storing the * version information to expand the string pool being used. */ START_TEST(test_alloc_parse_xdecl_2) { const char *text = "" "Hello, world"; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler); XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed with max allocations"); } END_TEST /* Test the effects of allocation failures on a straightforward parse */ START_TEST(test_alloc_parse_pi) { const char *text = "\n" "\n" "" "Hello, world" ""; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed with max allocations"); } END_TEST START_TEST(test_alloc_parse_pi_2) { const char *text = "\n" "" "Hello, world" "\n" ""; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed with max allocations"); } END_TEST START_TEST(test_alloc_parse_pi_3) { const char *text = ""; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed with max allocations"); } END_TEST START_TEST(test_alloc_parse_comment) { const char *text = "\n" "" "Hi"; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetCommentHandler(g_parser, dummy_comment_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed with max allocations"); } END_TEST START_TEST(test_alloc_parse_comment_2) { const char *text = "\n" "" "Hello, world" "" ""; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetCommentHandler(g_parser, dummy_comment_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed with max allocations"); } END_TEST /* Test that external parser creation running out of memory is * correctly reported. Based on the external entity test cases. */ START_TEST(test_alloc_create_external_parser) { const char *text = "\n" "\n" "&entity;"; char foo_text[] = ""; XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetUserData(g_parser, foo_text); XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) { fail("External parser allocator returned success incorrectly"); } } END_TEST /* More external parser memory allocation testing */ START_TEST(test_alloc_run_external_parser) { const char *text = "\n" "\n" "&entity;"; char foo_text[] = ""; unsigned int i; const unsigned int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetUserData(g_parser, foo_text); XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader); g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing ignored failing allocator"); else if (i == max_alloc_count) fail("Parsing failed with allocation count 10"); } END_TEST /* Test that running out of memory in dtdCopy is correctly reported. * Based on test_default_ns_from_ext_subset_and_ext_ge() */ START_TEST(test_alloc_dtd_copy_default_atts) { const char *text = "\n" "\n" "]>\n" "\n" "&en;\n" ""; int callno = 0; XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler); XML_SetUserData(g_parser, &callno); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_ERROR) xml_failure(g_parser); } END_TEST /* Test more external entity allocation failure paths */ START_TEST(test_alloc_external_entity) { const char *text = "\n" "\n" "]>\n" "\n" "&en;\n" ""; int i; const int alloc_test_max_repeats = 50; int callno = 0; for (i = 0; i < alloc_test_max_repeats; i++) { g_allocation_count = -1; XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2); callno = 0; XML_SetUserData(g_parser, &callno); g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_OK) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } g_allocation_count = -1; if (i == 0) fail("External entity parsed despite duff allocator"); if (i == alloc_test_max_repeats) fail("External entity not parsed at max allocation count"); } END_TEST /* Test more allocation failure paths */ START_TEST(test_alloc_ext_entity_set_encoding) { const char *text = "\n" "]>\n" "&en;"; int i; const int max_allocation_count = 30; for (i = 0; i < max_allocation_count; i++) { XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc_set_encoding); g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_OK) break; g_allocation_count = -1; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Encoding check succeeded despite failing allocator"); if (i == max_allocation_count) fail("Encoding failed at max allocation count"); } END_TEST /* Test the effects of allocation failure in internal entities. * Based on test_unknown_encoding_internal_entity */ START_TEST(test_alloc_internal_entity) { const char *text = "\n" "]>\n" ""; unsigned int i; const unsigned int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler, NULL); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Internal entity worked despite failing allocations"); else if (i == max_alloc_count) fail("Internal entity failed at max allocation count"); } END_TEST /* Test the robustness against allocation failure of element handling * Based on test_dtd_default_handling(). */ START_TEST(test_alloc_dtd_default_handling) { const char *text = "\n" "\n" "\n" "\n" "\n" "\n" "\n" "]>\n" ""; const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\ntext in doc"); CharData storage; int i; const int max_alloc_count = 25; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; init_dummy_handlers(); XML_SetDefaultHandler(g_parser, accumulate_characters); XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler, dummy_end_doctype_handler); XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); XML_SetCommentHandler(g_parser, dummy_comment_handler); XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler, dummy_end_cdata_handler); XML_SetUnparsedEntityDeclHandler(g_parser, dummy_unparsed_entity_decl_handler); CharData_Init(&storage); XML_SetUserData(g_parser, &storage); XML_SetCharacterDataHandler(g_parser, accumulate_characters); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Default DTD parsed despite allocation failures"); if (i == max_alloc_count) fail("Default DTD not parsed with maximum alloc count"); CharData_CheckXMLChars(&storage, expected); if (get_dummy_handler_flags() != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG)) fail("Not all handlers were called"); } END_TEST /* Test robustness of XML_SetEncoding() with a failing allocator */ START_TEST(test_alloc_explicit_encoding) { int i; const int max_alloc_count = 5; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK) break; } if (i == 0) fail("Encoding set despite failing allocator"); else if (i == max_alloc_count) fail("Encoding not set at max allocation count"); } END_TEST /* Test robustness of XML_SetBase against a failing allocator */ START_TEST(test_alloc_set_base) { const XML_Char *new_base = XCS("/local/file/name.xml"); int i; const int max_alloc_count = 5; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK) break; } if (i == 0) fail("Base set despite failing allocator"); else if (i == max_alloc_count) fail("Base not set with max allocation count"); } END_TEST /* Test buffer extension in the face of a duff reallocator */ START_TEST(test_alloc_realloc_buffer) { const char *text = get_buffer_test_text; void *buffer; int i; const int max_realloc_count = 10; /* Get a smallish buffer */ for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; buffer = XML_GetBuffer(g_parser, 1536); if (buffer == NULL) fail("1.5K buffer reallocation failed"); assert(buffer != NULL); memcpy(buffer, text, strlen(text)); if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE) == XML_STATUS_OK) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } g_reallocation_count = -1; if (i == 0) fail("Parse succeeded with no reallocation"); else if (i == max_realloc_count) fail("Parse failed with max reallocation count"); } END_TEST /* Same test for external entity parsers */ START_TEST(test_alloc_ext_entity_realloc_buffer) { const char *text = "\n" "]>\n" "&en;"; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator); XML_SetUserData(g_parser, &i); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) == XML_STATUS_OK) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Succeeded with no reallocations"); if (i == max_realloc_count) fail("Failed with max reallocations"); } END_TEST /* Test elements with many attributes are handled correctly */ START_TEST(test_alloc_realloc_many_attributes) { const char *text = "\n" "\n" "\n" "]>\n" "" ""; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite no reallocations"); if (i == max_realloc_count) fail("Parse failed at max reallocations"); } END_TEST /* Test handling of a public entity with failing allocator */ START_TEST(test_alloc_public_entity_value) { const char *text = "\n" "\n"; char dtd_text[] = "\n" "\n" "\n" "%e1;\n"; int i; const int max_alloc_count = 50; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; init_dummy_handlers(); XML_SetUserData(g_parser, dtd_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_public); /* Provoke a particular code path */ XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing worked despite failing allocation"); if (i == max_alloc_count) fail("Parsing failed at max allocation count"); if (get_dummy_handler_flags() != DUMMY_ENTITY_DECL_HANDLER_FLAG) fail("Entity declaration handler not called"); } END_TEST START_TEST(test_alloc_realloc_subst_public_entity_value) { const char *text = "\n" "\n"; char dtd_text[] = "\n" "\n" "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP" "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;"; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; XML_SetUserData(g_parser, dtd_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_public); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing worked despite failing reallocation"); if (i == max_realloc_count) fail("Parsing failed at max reallocation count"); } END_TEST START_TEST(test_alloc_parse_public_doctype) { const char *text = "\n" "\n" ""; int i; const int max_alloc_count = 25; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; init_dummy_handlers(); XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, dummy_end_doctype_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); if (get_dummy_handler_flags() != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG)) fail("Doctype handler functions not called"); } END_TEST START_TEST(test_alloc_parse_public_doctype_long_name) { const char *text = "\n" "\n" ""; int i; const int max_alloc_count = 25; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler, dummy_end_doctype_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); } END_TEST /* Test foreign DTD handling */ START_TEST(test_alloc_set_foreign_dtd) { const char *text1 = "\n" "&entity;"; char text2[] = ""; int i; const int max_alloc_count = 25; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetUserData(g_parser, &text2); XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE) fail("Could not set foreign DTD"); if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); } END_TEST /* Test based on ibm/valid/P32/ibm32v04.xml */ START_TEST(test_alloc_attribute_enum_value) { const char *text = "\n" "\n" "This is a \n \n\nyellow tiger"; char dtd_text[] = "\n" "\n" ""; int i; const int max_alloc_count = 30; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); XML_SetUserData(g_parser, dtd_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); /* An attribute list handler provokes a different code path */ XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); } END_TEST /* Test attribute enums sufficient to overflow the string pool */ START_TEST(test_alloc_realloc_attribute_enum_value) { const char *text = "\n" "\n" "This is a yellow tiger"; /* We wish to define a collection of attribute enums that will * cause the string pool storing them to have to expand. This * means more than 1024 bytes, including the parentheses and * separator bars. */ char dtd_text[] = "\n" ""; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); XML_SetUserData(g_parser, dtd_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); /* An attribute list handler provokes a different code path */ XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); } END_TEST /* Test attribute enums in a #IMPLIED attribute forcing pool growth */ START_TEST(test_alloc_realloc_implied_attribute) { /* Forcing this particular code path is a balancing act. The * addition of the closing parenthesis and terminal NUL must be * what pushes the string of enums over the 1024-byte limit, * otherwise a different code path will pick up the realloc. */ const char *text = "\n" "\n" "]>"; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); } END_TEST /* Test attribute enums in a defaulted attribute forcing pool growth */ START_TEST(test_alloc_realloc_default_attribute) { /* Forcing this particular code path is a balancing act. The * addition of the closing parenthesis and terminal NUL must be * what pushes the string of enums over the 1024-byte limit, * otherwise a different code path will pick up the realloc. */ const char *text = "\n" "\n]>"; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); } END_TEST /* Test long notation name with dodgy allocator */ START_TEST(test_alloc_notation) { const char *text = "\n" "\n" "\n" "]>\n"; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; init_dummy_handlers(); XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite allocation failures"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); if (get_dummy_handler_flags() != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG)) fail("Entity declaration handler not called"); } END_TEST /* Test public notation with dodgy allocator */ START_TEST(test_alloc_public_notation) { const char *text = "\n" "\n" "\n" "]>\n"; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; init_dummy_handlers(); XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite allocation failures"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); if (get_dummy_handler_flags() != DUMMY_NOTATION_DECL_HANDLER_FLAG) fail("Notation handler not called"); } END_TEST /* Test public notation with dodgy allocator */ START_TEST(test_alloc_system_notation) { const char *text = "\n" "\n" "\n" "]>\n"; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; init_dummy_handlers(); XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite allocation failures"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); if (get_dummy_handler_flags() != DUMMY_NOTATION_DECL_HANDLER_FLAG) fail("Notation handler not called"); } END_TEST START_TEST(test_alloc_nested_groups) { const char *text = "\n" "" "]>\n" ""; CharData storage; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; CharData_Init(&storage); XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); XML_SetStartElementHandler(g_parser, record_element_start_handler); XML_SetUserData(g_parser, &storage); init_dummy_handlers(); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_alloc_count) fail("Parse failed at maximum reallocation count"); CharData_CheckXMLChars(&storage, XCS("doce")); if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG) fail("Element handler not fired"); } END_TEST START_TEST(test_alloc_realloc_nested_groups) { const char *text = "\n" "" "]>\n" ""; CharData storage; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; CharData_Init(&storage); XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); XML_SetStartElementHandler(g_parser, record_element_start_handler); XML_SetUserData(g_parser, &storage); init_dummy_handlers(); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); CharData_CheckXMLChars(&storage, XCS("doce")); if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG) fail("Element handler not fired"); } END_TEST START_TEST(test_alloc_large_group) { const char *text = "\n" "]>\n" "\n" "\n" "\n"; int i; const int max_alloc_count = 50; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); init_dummy_handlers(); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG) fail("Element handler flag not raised"); } END_TEST START_TEST(test_alloc_realloc_group_choice) { const char *text = "\n" "]>\n" "\n" "\n" "This is a foo\n" "\n" "\n"; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler); init_dummy_handlers(); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG) fail("Element handler flag not raised"); } END_TEST START_TEST(test_alloc_pi_in_epilog) { const char *text = "\n" ""; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler); init_dummy_handlers(); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse completed despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); if (get_dummy_handler_flags() != DUMMY_PI_HANDLER_FLAG) fail("Processing instruction handler not invoked"); } END_TEST START_TEST(test_alloc_comment_in_epilog) { const char *text = "\n" ""; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetCommentHandler(g_parser, dummy_comment_handler); init_dummy_handlers(); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse completed despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); if (get_dummy_handler_flags() != DUMMY_COMMENT_HANDLER_FLAG) fail("Processing instruction handler not invoked"); } END_TEST START_TEST(test_alloc_realloc_long_attribute_value) { const char *text = "]>\n" ""; int i; const int max_realloc_count = 10; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); } END_TEST START_TEST(test_alloc_attribute_whitespace) { const char *text = ""; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); } END_TEST START_TEST(test_alloc_attribute_predefined_entity) { const char *text = ""; int i; const int max_alloc_count = 15; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); } END_TEST /* Test that a character reference at the end of a suitably long * default value for an attribute can trigger pool growth, and recovers * if the allocator fails on it. */ START_TEST(test_alloc_long_attr_default_with_char_ref) { const char *text = "]>\n" ""; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); } END_TEST /* Test that a long character reference substitution triggers a pool * expansion correctly for an attribute value. */ START_TEST(test_alloc_long_attr_value) { const char *text = "]>\n" ""; int i; const int max_alloc_count = 25; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing allocator"); if (i == max_alloc_count) fail("Parse failed at maximum allocation count"); } END_TEST /* Test that an error in a nested parameter entity substitution is * handled correctly. It seems unlikely that the code path being * exercised can be reached purely by carefully crafted XML, but an * allocation error in the right place will definitely do it. */ START_TEST(test_alloc_nested_entities) { const char *text = "\n" ""; ExtFaults test_data = {"\n" "\n" "", "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY}; /* Causes an allocation error in a nested storeEntityValue() */ g_allocation_count = 12; XML_SetUserData(g_parser, &test_data); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter); expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, "Entity allocation failure not noted"); } END_TEST START_TEST(test_alloc_realloc_param_entity_newline) { const char *text = "\n" ""; char dtd_text[] = "\n'>" "%pe;\n"; int i; const int max_realloc_count = 5; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; XML_SetUserData(g_parser, dtd_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); } END_TEST START_TEST(test_alloc_realloc_ce_extends_pe) { const char *text = "\n" ""; char dtd_text[] = "\n'>" "%pe;\n"; int i; const int max_realloc_count = 5; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; XML_SetUserData(g_parser, dtd_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); } END_TEST START_TEST(test_alloc_realloc_attributes) { const char *text = "]>\n" "wombat\n"; int i; const int max_realloc_count = 5; for (i = 0; i < max_realloc_count; i++) { g_reallocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parse succeeded despite failing reallocator"); if (i == max_realloc_count) fail("Parse failed at maximum reallocation count"); } END_TEST START_TEST(test_alloc_long_doc_name) { const char *text = /* 64 characters per line */ ""; int i; const int max_alloc_count = 20; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing worked despite failing reallocations"); else if (i == max_alloc_count) fail("Parsing failed even at max reallocation count"); } END_TEST START_TEST(test_alloc_long_base) { const char *text = "\n" "]>\n" "&e;"; char entity_text[] = "Hello world"; const XML_Char *base = /* 64 characters per line */ /* clang-format off */ XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t") XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/") XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"); /* clang-format on */ int i; const int max_alloc_count = 25; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetUserData(g_parser, entity_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) { XML_ParserReset(g_parser, NULL); continue; } if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing worked despite failing allocations"); else if (i == max_alloc_count) fail("Parsing failed even at max allocation count"); } END_TEST START_TEST(test_alloc_long_public_id) { const char *text = "\n" "]>\n" "&e;"; char entity_text[] = "Hello world"; int i; const int max_alloc_count = 40; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetUserData(g_parser, entity_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing worked despite failing allocations"); else if (i == max_alloc_count) fail("Parsing failed even at max allocation count"); } END_TEST START_TEST(test_alloc_long_entity_value) { const char *text = "\n" " \n" "]>\n" "&e2;"; char entity_text[] = "Hello world"; int i; const int max_alloc_count = 40; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetUserData(g_parser, entity_text); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing worked despite failing allocations"); else if (i == max_alloc_count) fail("Parsing failed even at max allocation count"); } END_TEST START_TEST(test_alloc_long_notation) { const char *text = "\n" " \n" " \n" "]>\n" "&e2;"; ExtOption options[] = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}}; int i; const int max_alloc_count = 40; for (i = 0; i < max_alloc_count; i++) { g_allocation_count = i; XML_SetUserData(g_parser, options); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) break; /* See comment in test_alloc_parse_xdecl() */ alloc_teardown(); alloc_setup(); } if (i == 0) fail("Parsing worked despite failing allocations"); else if (i == max_alloc_count) fail("Parsing failed even at max allocation count"); } END_TEST START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) { const char *const text = ""; XML_SetExternalEntityRefHandler( g_parser, external_entity_parser_create_alloc_fail_handler); XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR) fail("Call to parse was expected to fail"); if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) fail("Call to parse was expected to fail from the external entity handler"); XML_ParserReset(g_parser, NULL); } END_TEST void make_alloc_test_case(Suite *s) { TCase *tc_alloc = tcase_create("allocation tests"); suite_add_tcase(s, tc_alloc); tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); tcase_add_test(tc_alloc, test_alloc_parse_xdecl); tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2); tcase_add_test(tc_alloc, test_alloc_parse_pi); tcase_add_test(tc_alloc, test_alloc_parse_pi_2); tcase_add_test(tc_alloc, test_alloc_parse_pi_3); tcase_add_test(tc_alloc, test_alloc_parse_comment); tcase_add_test(tc_alloc, test_alloc_parse_comment_2); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling); tcase_add_test(tc_alloc, test_alloc_explicit_encoding); tcase_add_test(tc_alloc, test_alloc_set_base); tcase_add_test(tc_alloc, test_alloc_realloc_buffer); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_ext_entity_realloc_buffer); tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_subst_public_entity_value); tcase_add_test(tc_alloc, test_alloc_parse_public_doctype); tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attribute_enum_value); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_notation); tcase_add_test(tc_alloc, test_alloc_public_notation); tcase_add_test(tc_alloc, test_alloc_system_notation); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups); tcase_add_test(tc_alloc, test_alloc_large_group); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice); tcase_add_test(tc_alloc, test_alloc_pi_in_epilog); tcase_add_test(tc_alloc, test_alloc_comment_in_epilog); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_long_attribute_value); tcase_add_test(tc_alloc, test_alloc_attribute_whitespace); tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity); tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_attr_value); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_param_entity_newline); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe); tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes); tcase_add_test(tc_alloc, test_alloc_long_doc_name); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_base); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_public_id); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_entity_value); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_notation); tcase_add_test__ifdef_xml_dtd( tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail); }