diff options
Diffstat (limited to 'tests/basic_tests.c')
| -rw-r--r-- | tests/basic_tests.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/tests/basic_tests.c b/tests/basic_tests.c index 308adf6cbce0..e6829516ca79 100644 --- a/tests/basic_tests.c +++ b/tests/basic_tests.c @@ -23,6 +23,7 @@ Copyright (c) 2026 Francesco Bertolaccini Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com> Copyright (c) 2026 Kartik Kenchi <netliomax25@gmail.com> + Copyright (c) 2026 Zeyou Liu <zeyouliu@tencent.com> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -2809,6 +2810,79 @@ START_TEST(test_duplicate_id_attribute_multiple_attlistdecl) { } END_TEST +static void XMLCALL +check_second_attr_normalization(void *userData, const XML_Char *name, + const XML_Char **atts) { + int *const seen_second = userData; + UNUSED_P(name); + + for (size_t i = 0; atts[i] != NULL; i += 2) { + const XML_Char *const key = atts[i]; + const XML_Char *const value = atts[i + 1]; + if (xcstrcmp(key, XCS("second")) != 0) + continue; + *seen_second = 1; + /* Attribute "second" is not of type CDATA, so leading, trailing and + * repeated whitespace is to be normalized away. */ + if (xcstrcmp(value, XCS("a b")) != 0) + fail("Attribute of non-CDATA type was not whitespace-normalized"); + } +} + +static int XMLCALL +external_entity_attr_checker(XML_Parser parser, const XML_Char *context, + const XML_Char *base, const XML_Char *systemId, + const XML_Char *publicId) { + const char *const text = "<tag second=' a b '/>"; + UNUSED_P(base); + UNUSED_P(systemId); + UNUSED_P(publicId); + + XML_Parser 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_OK) + xml_failure(ext_parser); + + XML_ParserFree(ext_parser); + return XML_STATUS_OK; +} + +START_TEST(test_default_attr_index_after_dtd_copy) { + /* Function storeAtts resolves member .attIndex of structure + * NAME_AND_DEFAULT_ATTRIBUTE to tell whether an attribute value needs + * whitespace normalization, so function dtdCopy needs to carry that index + * over to the copy. Attribute "first" is declared before attribute + * "second" so that a mixed-up index resolves to the wrong declaration. + */ + const char *text = "<!DOCTYPE doc [\n" + " <!ENTITY e SYSTEM 'entity.ent'>\n" + " <!ELEMENT doc ANY>\n" + " <!ELEMENT tag EMPTY>\n" + " <!ATTLIST tag first CDATA #IMPLIED>\n" + " <!ATTLIST tag second NMTOKENS #IMPLIED>\n" + "]>\n" + "<doc>&e;</doc>\n"; + int seen_second = 0; + + XML_Parser parser = XML_ParserCreate(NULL); + assert_true(parser != NULL); + XML_SetUserData(parser, &seen_second); + XML_SetExternalEntityRefHandler(parser, external_entity_attr_checker); + XML_SetStartElementHandler(parser, check_second_attr_normalization); + + if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE) + != XML_STATUS_OK) + xml_failure(parser); + if (! seen_second) + fail("Attribute \"second\" has not been reported"); + + XML_ParserFree(parser); +} +END_TEST + /* Test reset works correctly in the middle of processing an internal * entity. Exercises some obscure code in XML_ParserReset(). */ @@ -3440,6 +3514,8 @@ START_TEST(test_buffer_can_grow_to_max) { maxbuf = maxbuf / 2; fprintf(stderr, "Reducing maxbuf to %d...\n", maxbuf); } +#else + UNUSED_P(maxbuf); #endif for (int i = 0; i < num_prefixes; ++i) { @@ -3463,6 +3539,8 @@ START_TEST(test_buffer_can_grow_to_max) { // The limit should be consistent; no prefix should allow us to // reach above the max buffer size. assert_true(XML_GetBuffer(parser, maxbuf + 1) == NULL); +#else + UNUSED_P(maxbuf); #endif XML_ParserFree(parser); @@ -6737,6 +6815,7 @@ make_basic_test_case(Suite *s) { tcase_add_test(tc_basic, test_duplicate_cdata_attribute_multiple_attlistdecl_3); tcase_add_test(tc_basic, test_duplicate_id_attribute_multiple_attlistdecl); + tcase_add_test__if_xml_ge(tc_basic, test_default_attr_index_after_dtd_copy); tcase_add_test__if_xml_ge(tc_basic, test_reset_in_entity); tcase_add_test(tc_basic, test_resume_invalid_parse); tcase_add_test(tc_basic, test_resume_resuspended); |
