summaryrefslogtreecommitdiff
path: root/tests/basic_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/basic_tests.c')
-rw-r--r--tests/basic_tests.c79
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);