diff --git a/expat/tests/basic_tests.c b/expat/tests/basic_tests.c index a7ccdd94..da23d9cb 100644 --- a/expat/tests/basic_tests.c +++ b/expat/tests/basic_tests.c @@ -4852,7 +4852,64 @@ START_TEST(test_empty_element_abort) { } END_TEST -TCase * +/* Regression test for GH issue #612: unfinished m_declAttributeType + * allocation in ->m_tempPool can corrupt following allocation. + */ +START_TEST(test_pool_integrity_with_unfinished_attr) { + const char *text = "\n" + "\n" + "\n" + "%entp;\n" + "]>\n" + "\n"; + const XML_Char *expected = XCS("COMMENT"); + CharData storage; + + CharData_Init(&storage); + XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(g_parser, external_entity_unfinished_attlist); + XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); + XML_SetCommentHandler(g_parser, accumulate_comment); + XML_SetUserData(g_parser, &storage); + if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) + == XML_STATUS_ERROR) + xml_failure(g_parser); + CharData_CheckXMLChars(&storage, expected); +} +END_TEST + +START_TEST(test_nested_entity_suspend) { + const char *const text = "'>\n" + " &e1;'>\n" + " &e2;'>\n" + "]>\n" + "&e3;"; + const XML_Char *const expected = XCS("start") XCS("e3 head") XCS("e2 head") + XCS("e1") XCS("e2 tail") XCS("e3 tail") XCS("end"); + CharData storage; + XML_Parser parser = XML_ParserCreate(NULL); + ParserPlusStorage parserPlusStorage = {parser, &storage}; + + CharData_Init(&storage); + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetCommentHandler(parser, accumulate_and_suspend_comment_handler); + XML_SetUserData(parser, &parserPlusStorage); + + enum XML_Status status = XML_Parse(parser, text, (int)strlen(text), XML_TRUE); + while (status == XML_STATUS_SUSPENDED) { + status = XML_ResumeParser(parser); + } + if (status != XML_STATUS_OK) + xml_failure(parser); + + CharData_CheckXMLChars(&storage, expected); + XML_ParserFree(parser); +} +END_TEST + +void make_basic_test_case(Suite *s) { TCase *tc_basic = tcase_create("basic tests"); @@ -5086,6 +5143,7 @@ make_basic_test_case(Suite *s) { tcase_add_test(tc_basic, test_bad_notation); tcase_add_test(tc_basic, test_default_doctype_handler); tcase_add_test(tc_basic, test_empty_element_abort); - - return tc_basic; /* TEMPORARY: this will become a void function */ + tcase_add_test__ifdef_xml_dtd(tc_basic, + test_pool_integrity_with_unfinished_attr); + tcase_add_test(tc_basic, test_nested_entity_suspend); } diff --git a/expat/tests/basic_tests.h b/expat/tests/basic_tests.h index ed1ae8b1..2530e665 100644 --- a/expat/tests/basic_tests.h +++ b/expat/tests/basic_tests.h @@ -47,7 +47,7 @@ extern "C" { #ifndef XML_BASIC_TESTS_H # define XML_BASIC_TESTS_H -extern TCase *make_basic_test_case(Suite *s); +extern void make_basic_test_case(Suite *s); #endif /* XML_BASIC_TESTS_H */ diff --git a/expat/tests/handlers.c b/expat/tests/handlers.c index e1c47f97..5f0d3c1b 100644 --- a/expat/tests/handlers.c +++ b/expat/tests/handlers.c @@ -1071,6 +1071,33 @@ external_entity_faulter2(XML_Parser parser, const XML_Char *context, return XML_STATUS_ERROR; } +int XMLCALL +external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) { + const char *text = "\n" + "\n" + "\n"; + XML_Parser ext_parser; + + UNUSED_P(base); + UNUSED_P(publicId); + if (systemId == NULL) + return XML_STATUS_OK; + + ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); + if (ext_parser == NULL) + fail("Could not create external entity parser"); + + if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) + == XML_STATUS_ERROR) + xml_failure(ext_parser); + + XML_ParserFree(ext_parser); + return XML_STATUS_OK; +} + /* NotStandalone handlers */ int XMLCALL @@ -1405,3 +1432,10 @@ checking_default_handler(void *userData, const XML_Char *s, int len) { } } } + +void XMLCALL +accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) { + ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData; + accumulate_comment(parserPlusStorage->storage, data); + XML_StopParser(parserPlusStorage->parser, XML_TRUE); +} diff --git a/expat/tests/handlers.h b/expat/tests/handlers.h index d22e31f1..5308e9cf 100644 --- a/expat/tests/handlers.h +++ b/expat/tests/handlers.h @@ -316,6 +316,12 @@ extern int XMLCALL external_entity_faulter2(XML_Parser parser, const XML_Char *systemId, const XML_Char *publicId); +extern int XMLCALL external_entity_unfinished_attlist(XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + /* NotStandalone handlers */ extern int XMLCALL reject_not_standalone_handler(void *userData); @@ -444,6 +450,14 @@ typedef struct default_check { void XMLCALL checking_default_handler(void *userData, const XML_Char *s, int len); +typedef struct { + XML_Parser parser; + CharData *storage; +} ParserPlusStorage; + +extern void XMLCALL +accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data); + #endif /* XML_HANDLERS_H */ #ifdef __cplusplus diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c index 69cb2db4..d46d7804 100644 --- a/expat/tests/runtests.c +++ b/expat/tests/runtests.c @@ -74,102 +74,6 @@ XML_Parser g_parser = NULL; -/* Regression test for GH issue #612: unfinished m_declAttributeType - * allocation in ->m_tempPool can corrupt following allocation. - */ -static int XMLCALL -external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId) { - const char *text = "\n" - "\n" - "\n"; - XML_Parser ext_parser; - - UNUSED_P(base); - UNUSED_P(publicId); - if (systemId == NULL) - return XML_STATUS_OK; - - ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); - if (ext_parser == NULL) - fail("Could not create external entity parser"); - - if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE) - == XML_STATUS_ERROR) - xml_failure(ext_parser); - - XML_ParserFree(ext_parser); - return XML_STATUS_OK; -} - -START_TEST(test_pool_integrity_with_unfinished_attr) { - const char *text = "\n" - "\n" - "\n" - "%entp;\n" - "]>\n" - "\n"; - const XML_Char *expected = XCS("COMMENT"); - CharData storage; - - CharData_Init(&storage); - XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); - XML_SetExternalEntityRefHandler(g_parser, external_entity_unfinished_attlist); - XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler); - XML_SetCommentHandler(g_parser, accumulate_comment); - XML_SetUserData(g_parser, &storage); - if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE) - == XML_STATUS_ERROR) - xml_failure(g_parser); - CharData_CheckXMLChars(&storage, expected); -} -END_TEST - -typedef struct { - XML_Parser parser; - CharData *storage; -} ParserPlusStorage; - -static void XMLCALL -accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) { - ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData; - accumulate_comment(parserPlusStorage->storage, data); - XML_StopParser(parserPlusStorage->parser, XML_TRUE); -} - -START_TEST(test_nested_entity_suspend) { - const char *const text = "'>\n" - " &e1;'>\n" - " &e2;'>\n" - "]>\n" - "&e3;"; - const XML_Char *const expected = XCS("start") XCS("e3 head") XCS("e2 head") - XCS("e1") XCS("e2 tail") XCS("e3 tail") XCS("end"); - CharData storage; - XML_Parser parser = XML_ParserCreate(NULL); - ParserPlusStorage parserPlusStorage = {parser, &storage}; - - CharData_Init(&storage); - XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); - XML_SetCommentHandler(parser, accumulate_and_suspend_comment_handler); - XML_SetUserData(parser, &parserPlusStorage); - - enum XML_Status status = XML_Parse(parser, text, (int)strlen(text), XML_TRUE); - while (status == XML_STATUS_SUSPENDED) { - status = XML_ResumeParser(parser); - } - if (status != XML_STATUS_OK) - xml_failure(parser); - - CharData_CheckXMLChars(&storage, expected); - XML_ParserFree(parser); -} -END_TEST - /* * Namespaces tests. */ @@ -5423,7 +5327,7 @@ END_TEST static Suite * make_suite(void) { Suite *s = suite_create("basic"); - TCase *tc_basic = make_basic_test_case(s); + make_basic_test_case(s); TCase *tc_namespace = tcase_create("XML namespaces"); TCase *tc_misc = tcase_create("miscellaneous tests"); TCase *tc_alloc = tcase_create("allocation tests"); @@ -5432,10 +5336,6 @@ make_suite(void) { TCase *tc_accounting = tcase_create("accounting tests"); #endif - tcase_add_test__ifdef_xml_dtd(tc_basic, - test_pool_integrity_with_unfinished_attr); - tcase_add_test(tc_basic, test_nested_entity_suspend); - suite_add_tcase(s, tc_namespace); tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown); tcase_add_test(tc_namespace, test_return_ns_triplet);