Compare commits
No commits in common. "c8" and "c9-beta" have entirely different histories.
@ -1,635 +0,0 @@
|
||||
From 88e9daef8fdaea58da12044cd16f5c9c1f201bfa Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
|
||||
Date: Fri, 13 Mar 2026 13:26:45 +0100
|
||||
Subject: [PATCH 1/6] Make "counting_start_element_handler" count default attrs
|
||||
|
||||
---
|
||||
expat/tests/runtests.c | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c
|
||||
index 4a0a2e3f..c66656e0 100644
|
||||
--- a/expat/tests/runtests.c
|
||||
+++ b/expat/tests/runtests.c
|
||||
@@ -3045,6 +3045,7 @@ typedef struct attrInfo {
|
||||
typedef struct elementInfo {
|
||||
const XML_Char *name;
|
||||
int attr_count;
|
||||
+ int default_attr_count;
|
||||
const XML_Char *id_name;
|
||||
AttrInfo *attributes;
|
||||
} ElementInfo;
|
||||
@@ -3089,7 +3090,7 @@ counting_start_element_handler(void *userData, const XML_Char *name,
|
||||
fail("ID does not have the correct name");
|
||||
return;
|
||||
}
|
||||
- for (i = 0; i < info->attr_count; i++) {
|
||||
+ for (i = 0; i < info->attr_count + info->default_attr_count; i++) {
|
||||
attr = info->attributes;
|
||||
while (attr->name != NULL) {
|
||||
if (! xcstrcmp(atts[0], attr->name))
|
||||
@@ -3122,9 +3123,9 @@ START_TEST(test_attributes) {
|
||||
{XCS("id"), XCS("one")},
|
||||
{NULL, NULL}};
|
||||
AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
|
||||
- ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
|
||||
- {XCS("tag"), 1, NULL, NULL},
|
||||
- {NULL, 0, NULL, NULL}};
|
||||
+ ElementInfo info[] = {{XCS("doc"), 3, 0, XCS("id"), NULL},
|
||||
+ {XCS("tag"), 1, 0, NULL, NULL},
|
||||
+ {NULL, 0, 0, NULL, NULL}};
|
||||
info[0].attributes = doc_info;
|
||||
info[1].attributes = tag_info;
|
||||
|
||||
@@ -7111,7 +7112,7 @@ START_TEST(test_deep_nested_attribute_entity) {
|
||||
(long unsigned)(N_LINES - 1));
|
||||
|
||||
AttrInfo doc_info[] = {{XCS("name"), XCS("deepText")}, {NULL, NULL}};
|
||||
- ElementInfo info[] = {{XCS("foo"), 1, NULL, NULL}, {NULL, 0, NULL, NULL}};
|
||||
+ ElementInfo info[] = {{XCS("foo"), 1, 0, NULL, NULL}, {NULL, 0, 0, NULL, NULL}};
|
||||
info[0].attributes = doc_info;
|
||||
|
||||
XML_SetStartElementHandler(g_parser, counting_start_element_handler);
|
||||
--
|
||||
2.52.0
|
||||
|
||||
|
||||
From 04796d5b0e71cc37a4bfa0031270d7bee6e0128a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
|
||||
Date: Fri, 13 Mar 2026 13:27:31 +0100
|
||||
Subject: [PATCH 2/6] test(attlist): Cover duplicate attribute names
|
||||
|
||||
Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
|
||||
---
|
||||
expat/tests/runtests.c | 315 +++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 302 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c
|
||||
index c66656e0..13583e0a 100644
|
||||
--- a/expat/tests/runtests.c
|
||||
+++ b/expat/tests/runtests.c
|
||||
@@ -3059,7 +3059,9 @@ typedef struct StructParserAndElementInfo {
|
||||
static void XMLCALL
|
||||
counting_start_element_handler(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts) {
|
||||
- ElementInfo *info = (ElementInfo *)userData;
|
||||
+ ParserAndElementInfo *const parserAndElementInfos
|
||||
+ = (ParserAndElementInfo *)userData;
|
||||
+ ElementInfo *info = parserAndElementInfos->info;
|
||||
AttrInfo *attr;
|
||||
int count, id, i;
|
||||
|
||||
@@ -3076,17 +3078,17 @@ counting_start_element_handler(void *userData, const XML_Char *name,
|
||||
* is possibly a little unexpected, but it is what the
|
||||
* documentation in expat.h tells us to expect.
|
||||
*/
|
||||
- count = XML_GetSpecifiedAttributeCount(g_parser);
|
||||
+ count = XML_GetSpecifiedAttributeCount(parserAndElementInfos->parser);
|
||||
if (info->attr_count * 2 != count) {
|
||||
fail("Not got expected attribute count");
|
||||
return;
|
||||
}
|
||||
- id = XML_GetIdAttributeIndex(g_parser);
|
||||
+ id = XML_GetIdAttributeIndex(parserAndElementInfos->parser);
|
||||
if (id == -1 && info->id_name != NULL) {
|
||||
fail("ID not present");
|
||||
return;
|
||||
}
|
||||
- if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
|
||||
+ if (id != -1 && xcstrcmp(atts[id], info->id_name) != 0) {
|
||||
fail("ID does not have the correct name");
|
||||
return;
|
||||
}
|
||||
@@ -3101,7 +3103,7 @@ counting_start_element_handler(void *userData, const XML_Char *name,
|
||||
fail("Attribute not recognised");
|
||||
return;
|
||||
}
|
||||
- if (xcstrcmp(atts[1], attr->value)) {
|
||||
+ if (xcstrcmp(atts[1], attr->value) != 0) {
|
||||
fail("Attribute has wrong value");
|
||||
return;
|
||||
}
|
||||
@@ -3123,20 +3125,296 @@ START_TEST(test_attributes) {
|
||||
{XCS("id"), XCS("one")},
|
||||
{NULL, NULL}};
|
||||
AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
|
||||
- ElementInfo info[] = {{XCS("doc"), 3, 0, XCS("id"), NULL},
|
||||
- {XCS("tag"), 1, 0, NULL, NULL},
|
||||
+ ElementInfo info[] = {{XCS("doc"), 3, 0, XCS("id"), doc_info},
|
||||
+ {XCS("tag"), 1, 0, NULL, tag_info},
|
||||
{NULL, 0, 0, NULL, NULL}};
|
||||
- info[0].attributes = doc_info;
|
||||
- info[1].attributes = tag_info;
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ g_parser,
|
||||
+ info,
|
||||
+ };
|
||||
|
||||
XML_SetStartElementHandler(g_parser, counting_start_element_handler);
|
||||
- XML_SetUserData(g_parser, info);
|
||||
+ XML_SetUserData(g_parser, &parserAndElementInfos);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
+START_TEST(test_duplicate_cdata_attribute) {
|
||||
+ /*
|
||||
+ https://www.w3.org/TR/xml/#attdecls
|
||||
+
|
||||
+ Test the following statement from the linked specification:
|
||||
+ When more than one definition is provided for the same attribute of a given
|
||||
+ element type, the first declaration is binding and later declarations are
|
||||
+ ignored.
|
||||
+ */
|
||||
+
|
||||
+ const char *text
|
||||
+ = "<!DOCTYPE doc [\n"
|
||||
+ " <!ATTLIST doc attribute CDATA 'expected' attribute CDATA 'ignored'>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc/>\n";
|
||||
+ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected")}, {NULL, NULL}};
|
||||
+ ElementInfo info[]
|
||||
+ = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(parser != NULL);
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ parser,
|
||||
+ info,
|
||||
+ };
|
||||
+
|
||||
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
+ XML_SetUserData(parser, &parserAndElementInfos);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ != XML_STATUS_OK)
|
||||
+ xml_failure(parser);
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+START_TEST(test_duplicate_id_attribute_1) {
|
||||
+ /*
|
||||
+ https://www.w3.org/TR/xml/#attdecls
|
||||
+
|
||||
+ Test the following statement from the linked specification:
|
||||
+ When more than one definition is provided for the same attribute of a given
|
||||
+ element type, the first declaration is binding and later declarations are
|
||||
+ ignored.
|
||||
+ */
|
||||
+
|
||||
+ const char *text
|
||||
+ = "<!DOCTYPE doc [\n"
|
||||
+ " <!ATTLIST doc identifier CDATA 'expected' identifier ID #REQUIRED>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc/>\n";
|
||||
+ AttrInfo doc_info[] = {{XCS("identifier"), XCS("expected")}, {NULL, NULL}};
|
||||
+ ElementInfo info[]
|
||||
+ = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(parser != NULL);
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ parser,
|
||||
+ info,
|
||||
+ };
|
||||
+
|
||||
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
+ XML_SetUserData(parser, &parserAndElementInfos);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ != XML_STATUS_OK)
|
||||
+ xml_failure(parser);
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+START_TEST(test_duplicate_id_attribute_2) {
|
||||
+ /*
|
||||
+ https://www.w3.org/TR/xml/#attdecls
|
||||
+
|
||||
+ Test the following statement from the linked specification:
|
||||
+ When more than one definition is provided for the same attribute of a given
|
||||
+ element type, the first declaration is binding and later declarations are
|
||||
+ ignored.
|
||||
+ */
|
||||
+
|
||||
+ const char *text
|
||||
+ = "<!DOCTYPE doc [\n"
|
||||
+ " <!ATTLIST doc identifier ID #REQUIRED identifier CDATA 'unexpected'>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc/>\n";
|
||||
+ AttrInfo doc_info[] = {{NULL, NULL}};
|
||||
+
|
||||
+ ElementInfo info[]
|
||||
+ = {{XCS("doc"), 0, 0, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(parser != NULL);
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ parser,
|
||||
+ info,
|
||||
+ };
|
||||
+
|
||||
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
+ XML_SetUserData(parser, &parserAndElementInfos);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ != XML_STATUS_OK)
|
||||
+ xml_failure(parser);
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl) {
|
||||
+ /*
|
||||
+ https://www.w3.org/TR/xml/#attdecls
|
||||
+
|
||||
+ Test the following statement from the linked specification:
|
||||
+ When more than one AttlistDecl is provided for a given element type,
|
||||
+ the contents of all those provided are merged.
|
||||
+ */
|
||||
+ const char *text = "<!DOCTYPE doc [\n"
|
||||
+ " <!ATTLIST doc attribute CDATA 'expected'>\n"
|
||||
+ " <!ATTLIST doc attribute CDATA 'ignored'>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc/>\n";
|
||||
+ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected")}, {NULL, NULL}};
|
||||
+ ElementInfo info[]
|
||||
+ = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(parser != NULL);
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ parser,
|
||||
+ info,
|
||||
+ };
|
||||
+
|
||||
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
+ XML_SetUserData(parser, &parserAndElementInfos);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ != XML_STATUS_OK)
|
||||
+ xml_failure(parser);
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl_2) {
|
||||
+ /*
|
||||
+ https://www.w3.org/TR/xml/#attdecls
|
||||
+
|
||||
+ Test the following statement from the linked specification:
|
||||
+ When more than one AttlistDecl is provided for a given element type,
|
||||
+ the contents of all those provided are merged.
|
||||
+ */
|
||||
+ const char *text = "<!DOCTYPE doc [\n"
|
||||
+ " <!ATTLIST doc attribute CDATA 'expected_doc'>\n"
|
||||
+ " <!ATTLIST tag attribute CDATA 'expected_tag'>\n"
|
||||
+ " <!ATTLIST doc attribute CDATA 'ignored_doc'>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc><tag></tag></doc>\n";
|
||||
+ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected_doc")}, {NULL, NULL}};
|
||||
+ AttrInfo tag_info[] = {{XCS("attribute"), XCS("expected_tag")}, {NULL, NULL}};
|
||||
+ ElementInfo info[] = {{XCS("doc"), 0, 1, NULL, doc_info},
|
||||
+ {XCS("tag"), 0, 1, NULL, tag_info},
|
||||
+ {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(parser != NULL);
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ parser,
|
||||
+ info,
|
||||
+ };
|
||||
+
|
||||
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
+ XML_SetUserData(parser, &parserAndElementInfos);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ != XML_STATUS_OK)
|
||||
+ xml_failure(parser);
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl_3) {
|
||||
+ /*
|
||||
+ https://www.w3.org/TR/xml/#attdecls
|
||||
+
|
||||
+ Test the following statement from the linked specification:
|
||||
+ When more than one AttlistDecl is provided for a given element type,
|
||||
+ the contents of all those provided are merged.
|
||||
+ */
|
||||
+ const char *text
|
||||
+ = "<!DOCTYPE doc [\n"
|
||||
+ " <!ATTLIST doc attribute CDATA 'expected_doc'>\n"
|
||||
+ " <!ATTLIST tag attribute CDATA 'expected_tag'>\n"
|
||||
+ " <!ATTLIST doc second_attribute CDATA 'second_expected_doc' attribute CDATA 'ignored_doc'>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc><tag></tag></doc>\n";
|
||||
+ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected_doc")},
|
||||
+ {XCS("second_attribute"), XCS("second_expected_doc")},
|
||||
+ {NULL, NULL}};
|
||||
+ AttrInfo tag_info[] = {{XCS("attribute"), XCS("expected_tag")}, {NULL, NULL}};
|
||||
+ ElementInfo info[] = {{XCS("doc"), 0, 2, NULL, doc_info},
|
||||
+ {XCS("tag"), 0, 1, NULL, tag_info},
|
||||
+ {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(parser != NULL);
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ parser,
|
||||
+ info,
|
||||
+ };
|
||||
+
|
||||
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
+ XML_SetUserData(parser, &parserAndElementInfos);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ != XML_STATUS_OK)
|
||||
+ xml_failure(parser);
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+START_TEST(test_duplicate_id_attribute_multiple_attlistdecl) {
|
||||
+ /*
|
||||
+ https://www.w3.org/TR/xml/#attdecls
|
||||
+
|
||||
+ Test the following statement from the linked specification:
|
||||
+ When more than one AttlistDecl is provided for a given element type,
|
||||
+ the contents of all those provided are merged.
|
||||
+ */
|
||||
+ const char *text = "<!DOCTYPE doc [\n"
|
||||
+ " <!ATTLIST doc identifier ID #REQUIRED>\n"
|
||||
+ " <!ATTLIST tag identifier CDATA 'identifier_tag'>\n"
|
||||
+ " <!ATTLIST doc identifier CDATA 'ignored'>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc identifier='doc_identity'><tag></tag></doc>\n";
|
||||
+ AttrInfo doc_info[]
|
||||
+ = {{XCS("identifier"), XCS("doc_identity")}, {NULL, NULL}};
|
||||
+ AttrInfo tag_info[]
|
||||
+ = {{XCS("identifier"), XCS("identifier_tag")}, {NULL, NULL}};
|
||||
+ ElementInfo info[] = {{XCS("doc"), 1, 0, XCS("identifier"), doc_info},
|
||||
+ {XCS("tag"), 0, 1, NULL, tag_info},
|
||||
+ {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(parser != NULL);
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {
|
||||
+ parser,
|
||||
+ info,
|
||||
+ };
|
||||
+
|
||||
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
+ XML_SetUserData(parser, &parserAndElementInfos);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ != XML_STATUS_OK)
|
||||
+ xml_failure(parser);
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
/* Test reset works correctly in the middle of processing an internal
|
||||
* entity. Exercises some obscure code in XML_ParserReset().
|
||||
*/
|
||||
@@ -7112,11 +7390,13 @@ START_TEST(test_deep_nested_attribute_entity) {
|
||||
(long unsigned)(N_LINES - 1));
|
||||
|
||||
AttrInfo doc_info[] = {{XCS("name"), XCS("deepText")}, {NULL, NULL}};
|
||||
- ElementInfo info[] = {{XCS("foo"), 1, 0, NULL, NULL}, {NULL, 0, 0, NULL, NULL}};
|
||||
- info[0].attributes = doc_info;
|
||||
+ ElementInfo info[]
|
||||
+ = {{XCS("foo"), 1, 0, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
|
||||
+
|
||||
+ ParserAndElementInfo parserAndElementInfos = {g_parser, info};
|
||||
|
||||
XML_SetStartElementHandler(g_parser, counting_start_element_handler);
|
||||
- XML_SetUserData(g_parser, &info);
|
||||
+ XML_SetUserData(g_parser, &parserAndElementInfos);
|
||||
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
@@ -13625,6 +13905,15 @@ make_suite(void) {
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
|
||||
tcase_add_test(tc_basic, test_set_base);
|
||||
tcase_add_test(tc_basic, test_attributes);
|
||||
+ tcase_add_test(tc_basic, test_duplicate_cdata_attribute);
|
||||
+ tcase_add_test(tc_basic, test_duplicate_id_attribute_1);
|
||||
+ tcase_add_test(tc_basic, test_duplicate_id_attribute_2);
|
||||
+ tcase_add_test(tc_basic, test_duplicate_cdata_attribute_multiple_attlistdecl);
|
||||
+ tcase_add_test(tc_basic,
|
||||
+ test_duplicate_cdata_attribute_multiple_attlistdecl_2);
|
||||
+ 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(tc_basic, test_reset_in_entity);
|
||||
tcase_add_test(tc_basic, test_resume_invalid_parse);
|
||||
tcase_add_test(tc_basic, test_resume_resuspended);
|
||||
--
|
||||
2.52.0
|
||||
|
||||
|
||||
From 58d4b742fd88c9789e4a5e68de02164145f9c593 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Pipping <sebastian@pipping.org>
|
||||
Date: Mon, 13 Apr 2026 01:34:03 +0200
|
||||
Subject: [PATCH 3/6] tests: Make counting_start_element_handler enforce
|
||||
complete attribute lists
|
||||
|
||||
---
|
||||
expat/tests/runtests.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c
|
||||
index 13583e0a..659ed030 100644
|
||||
--- a/expat/tests/runtests.c
|
||||
+++ b/expat/tests/runtests.c
|
||||
@@ -3110,6 +3110,9 @@ counting_start_element_handler(void *userData, const XML_Char *name,
|
||||
/* Remember, two entries in atts per attribute (see above) */
|
||||
atts += 2;
|
||||
}
|
||||
+
|
||||
+ // Self-test that the test case's list of expected attributes is complete
|
||||
+ assert_true(atts[0] == NULL);
|
||||
}
|
||||
|
||||
START_TEST(test_attributes) {
|
||||
--
|
||||
2.52.0
|
||||
|
||||
|
||||
From 2f13a612e82242af9954508240c6edfaf7cb0721 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Pipping <sebastian@pipping.org>
|
||||
Date: Sun, 8 Mar 2026 22:14:41 +0100
|
||||
Subject: [PATCH 4/6] lib: Extract a constant for upcoming reuse
|
||||
|
||||
---
|
||||
expat/lib/xmlparse.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index cba41f4b..ac9512e9 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -7528,8 +7528,9 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
|
||||
oldE->prefix->name, 0);
|
||||
for (i = 0; i < newE->nDefaultAtts; i++) {
|
||||
+ const XML_Char *const attributeName = oldE->defaultAtts[i].id->name;
|
||||
newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
|
||||
- oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
|
||||
+ oldParser, &(newDtd->attributeIds), attributeName, 0);
|
||||
newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
|
||||
if (oldE->defaultAtts[i].value) {
|
||||
newE->defaultAtts[i].value
|
||||
--
|
||||
2.52.0
|
||||
|
||||
|
||||
From 8211c5affe00c6d92025f34ae7ffbc0f78426692 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Pipping <sebastian@pipping.org>
|
||||
Date: Sun, 8 Mar 2026 23:05:49 +0100
|
||||
Subject: [PATCH 5/6] lib: Introduce ELEMENT_TYPE.defaultAttsNames
|
||||
|
||||
---
|
||||
expat/lib/xmlparse.c | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index ac9512e9..d8e7335d 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -368,6 +368,7 @@ typedef struct {
|
||||
int nDefaultAtts;
|
||||
int allocDefaultAtts;
|
||||
DEFAULT_ATTRIBUTE *defaultAtts;
|
||||
+ HASH_TABLE defaultAttsNames;
|
||||
} ELEMENT_TYPE;
|
||||
|
||||
typedef struct {
|
||||
@@ -3756,6 +3757,8 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
sizeof(ELEMENT_TYPE));
|
||||
if (! elementType)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
+ if (! elementType->defaultAttsNames.parser)
|
||||
+ hashTableInit(&(elementType->defaultAttsNames), parser);
|
||||
if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
@@ -7369,6 +7372,7 @@ dtdReset(DTD *p, XML_Parser parser) {
|
||||
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
|
||||
if (! e)
|
||||
break;
|
||||
+ hashTableDestroy(&(e->defaultAttsNames));
|
||||
if (e->allocDefaultAtts != 0)
|
||||
FREE(parser, e->defaultAtts);
|
||||
}
|
||||
@@ -7410,6 +7414,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser) {
|
||||
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
|
||||
if (! e)
|
||||
break;
|
||||
+ hashTableDestroy(&(e->defaultAttsNames));
|
||||
if (e->allocDefaultAtts != 0)
|
||||
FREE(parser, e->defaultAtts);
|
||||
}
|
||||
@@ -7503,6 +7508,10 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
sizeof(ELEMENT_TYPE));
|
||||
if (! newE)
|
||||
return 0;
|
||||
+
|
||||
+ if (! newE->defaultAttsNames.parser)
|
||||
+ hashTableInit(&(newE->defaultAttsNames), parser);
|
||||
+
|
||||
if (oldE->nDefaultAtts) {
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
@@ -7539,6 +7548,12 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
return 0;
|
||||
} else
|
||||
newE->defaultAtts[i].value = NULL;
|
||||
+
|
||||
+ NAMED *const nameAddedOrFound = (NAMED *)lookup(
|
||||
+ parser, &(newE->defaultAttsNames), attributeName, sizeof(NAMED));
|
||||
+ if (! nameAddedOrFound) {
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8263,6 +8278,8 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
|
||||
sizeof(ELEMENT_TYPE));
|
||||
if (! ret)
|
||||
return NULL;
|
||||
+ if (! ret->defaultAttsNames.parser)
|
||||
+ hashTableInit(&(ret->defaultAttsNames), getRootParserOf(parser, NULL));
|
||||
if (ret->name != name)
|
||||
poolDiscard(&dtd->pool);
|
||||
else {
|
||||
--
|
||||
2.52.0
|
||||
|
||||
|
||||
From 756dfc0850eb52005366da45859b1bb80a80466e Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Pipping <sebastian@pipping.org>
|
||||
Date: Sun, 8 Mar 2026 23:06:29 +0100
|
||||
Subject: [PATCH 6/6] lib: Leverage ELEMENT_TYPE.defaultAttsNames for attribute
|
||||
collision detection
|
||||
|
||||
.. to resolve quadratic runtime behavior
|
||||
---
|
||||
expat/lib/xmlparse.c | 14 ++++++++++----
|
||||
1 file changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index d8e7335d..d7d815e8 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -7009,10 +7009,10 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
|
||||
if (value || isId) {
|
||||
/* The handling of default attributes gets messed up if we have
|
||||
a default which duplicates a non-default. */
|
||||
- int i;
|
||||
- for (i = 0; i < type->nDefaultAtts; i++)
|
||||
- if (attId == type->defaultAtts[i].id)
|
||||
- return 1;
|
||||
+ NAMED *const nameFound
|
||||
+ = (NAMED *)lookup(parser, &(type->defaultAttsNames), attId->name, 0);
|
||||
+ if (nameFound)
|
||||
+ return 1;
|
||||
if (isId && ! type->idAtt && ! attId->xmlns)
|
||||
type->idAtt = attId;
|
||||
}
|
||||
@@ -7059,6 +7059,12 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
|
||||
att->isCdata = isCdata;
|
||||
if (! isCdata)
|
||||
attId->maybeTokenized = XML_TRUE;
|
||||
+
|
||||
+ NAMED *const nameAddedOrFound = (NAMED *)lookup(
|
||||
+ parser, &(type->defaultAttsNames), attId->name, sizeof(NAMED));
|
||||
+ if (! nameAddedOrFound)
|
||||
+ return 0;
|
||||
+
|
||||
type->nDefaultAtts += 1;
|
||||
return 1;
|
||||
}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,288 +0,0 @@
|
||||
From b5b73d23072fd277b3816b45c027238260467947 Mon Sep 17 00:00:00 2001
|
||||
From: Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:01:02 -0700
|
||||
Subject: [PATCH 1/5] lib: Remove reuse of `m_groupSize` to count
|
||||
`m_scaffIndex` allocation
|
||||
|
||||
The sizes of the two arrays `m_groupConnector` and `scaffIndex` need to
|
||||
vary independently. This change is a step towards allowing this.
|
||||
|
||||
Anthropic: ANT-2026-00037
|
||||
Anthropic: ANT-2026-03621
|
||||
Anthropic: ANT-2026-03867
|
||||
Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
|
||||
---
|
||||
expat/lib/xmlparse.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index d7d815e8..3b5e90b1 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -398,6 +398,7 @@ typedef struct {
|
||||
unsigned scaffCount;
|
||||
int scaffLevel;
|
||||
int *scaffIndex;
|
||||
+ size_t scaffIndexSize;
|
||||
} DTD;
|
||||
|
||||
enum EntityType {
|
||||
@@ -5812,6 +5813,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
if (new_scaff_index == NULL)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
dtd->scaffIndex = new_scaff_index;
|
||||
+ dtd->scaffIndexSize = parser->m_groupSize;
|
||||
}
|
||||
} else {
|
||||
parser->m_groupConnector
|
||||
@@ -7358,6 +7360,7 @@ dtdCreate(XML_Parser parser) {
|
||||
|
||||
p->in_eldecl = XML_FALSE;
|
||||
p->scaffIndex = NULL;
|
||||
+ p->scaffIndexSize = 0;
|
||||
p->scaffold = NULL;
|
||||
p->scaffLevel = 0;
|
||||
p->scaffSize = 0;
|
||||
@@ -7399,6 +7402,7 @@ dtdReset(DTD *p, XML_Parser parser) {
|
||||
|
||||
FREE(parser, p->scaffIndex);
|
||||
p->scaffIndex = NULL;
|
||||
+ p->scaffIndexSize = 0;
|
||||
FREE(parser, p->scaffold);
|
||||
p->scaffold = NULL;
|
||||
|
||||
@@ -7586,6 +7590,7 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
newDtd->scaffSize = oldDtd->scaffSize;
|
||||
newDtd->scaffLevel = oldDtd->scaffLevel;
|
||||
newDtd->scaffIndex = oldDtd->scaffIndex;
|
||||
+ newDtd->scaffIndexSize = oldDtd->scaffIndexSize;
|
||||
|
||||
return 1;
|
||||
} /* End dtdCopy */
|
||||
@@ -8090,6 +8095,7 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
|
||||
if (! dtd->scaffIndex)
|
||||
return -1;
|
||||
+ dtd->scaffIndexSize = parser->m_groupSize;
|
||||
dtd->scaffIndex[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
From af2f86e32624be829ddc0ce7168d18f921bdef4e Mon Sep 17 00:00:00 2001
|
||||
From: Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:01:02 -0700
|
||||
Subject: [PATCH 2/5] lib: doProlog: Fix out-of-bound scaffolding index store
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The scaffold backing array is reallocated using the caller parser’s
|
||||
per-parser `m_groupSize`, but the DTD struct (which carries
|
||||
`scaffIndex`) is shared between a parent parser and any external
|
||||
parameter-entity sub-parser created via
|
||||
`XML_ExternalEntityParserCreate(parent, NULL, …)`. A sub-parser whose
|
||||
group nesting is shallower than the parent’s can `REALLOC` the shared
|
||||
`scaffIndex` down to its own size; when the parent resumes and parses a
|
||||
deeper element content model, its bounds check passes (its private
|
||||
`m_groupSize` is still large enough), the doubling-grow path is skipped,
|
||||
and the next write lands past the shrunken buffer.
|
||||
|
||||
Anthropic: ANT-2026-00037
|
||||
Anthropic: ANT-2026-03621
|
||||
Anthropic: ANT-2026-03867
|
||||
Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
|
||||
Reported-by: Trail of Bits, in collaboration with Anthropic
|
||||
---
|
||||
expat/lib/xmlparse.c | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index 3b5e90b1..317b08e0 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -5830,6 +5830,21 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
if (myindex < 0)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
assert(dtd->scaffIndex != NULL);
|
||||
+ if ((size_t)dtd->scaffLevel >= dtd->scaffIndexSize) {
|
||||
+ /* Detect and prevent integer overflow */
|
||||
+ if (dtd->scaffIndexSize > SIZE_MAX / 2 / sizeof(int)) {
|
||||
+ return XML_ERROR_NO_MEMORY;
|
||||
+ }
|
||||
+ assert(dtd->scaffIndexSize > 0);
|
||||
+ const size_t new_size = dtd->scaffIndexSize * 2;
|
||||
+ int *const new_scaff_index
|
||||
+ = REALLOC(parser, dtd->scaffIndex, new_size * sizeof(int));
|
||||
+ if (new_scaff_index == NULL) {
|
||||
+ return XML_ERROR_NO_MEMORY;
|
||||
+ }
|
||||
+ dtd->scaffIndex = new_scaff_index;
|
||||
+ dtd->scaffIndexSize = new_size;
|
||||
+ }
|
||||
dtd->scaffIndex[dtd->scaffLevel] = myindex;
|
||||
dtd->scaffLevel++;
|
||||
dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
|
||||
|
||||
From 8b1debf703fadb5e11074f98f33a8bd10b561f3e Mon Sep 17 00:00:00 2001
|
||||
From: Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:01:02 -0700
|
||||
Subject: [PATCH 3/5] tests: Add a test case for scaffolding array limits in
|
||||
shared DTDs
|
||||
|
||||
This test case provokes the bug fixed in the previous commit.
|
||||
|
||||
Anthropic: ANT-2026-00037
|
||||
Anthropic: ANT-2026-03621
|
||||
Anthropic: ANT-2026-03867
|
||||
Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
|
||||
Reported-by: Trail of Bits, in collaboration with Anthropic
|
||||
---
|
||||
expat/tests/runtests.c | 30 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 30 insertions(+)
|
||||
|
||||
diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c
|
||||
index 659ed030..c760733d 100644
|
||||
--- a/expat/tests/runtests.c
|
||||
+++ b/expat/tests/runtests.c
|
||||
@@ -5681,6 +5681,34 @@ START_TEST(test_skipped_external_entity) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
+START_TEST(test_scaff_index_shared_across_external_entity_parser) {
|
||||
+ const char text[]
|
||||
+ = "<!DOCTYPE doc [\n"
|
||||
+ "<!ELEMENT a "
|
||||
+ "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((b))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>\n"
|
||||
+ "<!ENTITY % e SYSTEM 'ext'>\n"
|
||||
+ "%e;\n"
|
||||
+ "<!ELEMENT c "
|
||||
+ "(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((d)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>\n"
|
||||
+ "]>\n"
|
||||
+ "<doc/>";
|
||||
+ ExtOption options[]
|
||||
+ = {{XCS("ext"),
|
||||
+ "<!ELEMENT x "
|
||||
+ "((((((((((((((((((((((((((((((((y))))))))))))))))))))))))))))))))>"},
|
||||
+ {NULL, NULL}};
|
||||
+
|
||||
+ XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
+ XML_SetUserData(g_parser, options);
|
||||
+ XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
|
||||
+ XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
|
||||
+
|
||||
+ if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
+ == XML_STATUS_ERROR)
|
||||
+ xml_failure(g_parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
/* Test a different form of unknown external entity */
|
||||
typedef struct ext_hdlr_data {
|
||||
const char *parse_text;
|
||||
@@ -13988,6 +14016,8 @@ make_suite(void) {
|
||||
tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
|
||||
tcase_add_test(tc_basic, test_standalone_internal_entity);
|
||||
tcase_add_test(tc_basic, test_skipped_external_entity);
|
||||
+ tcase_add_test__ifdef_xml_dtd(
|
||||
+ tc_basic, test_scaff_index_shared_across_external_entity_parser);
|
||||
tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
|
||||
tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
|
||||
|
||||
From 4ab78126be566310e293adef807a9b919e90f8df Mon Sep 17 00:00:00 2001
|
||||
From: Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:01:02 -0700
|
||||
Subject: [PATCH 4/5] lib: Remove unnecessary `scaffIndex` expansion
|
||||
|
||||
Following the previous changes, all locations that append entries to
|
||||
`scaffIndex` handle expanding the array if it is not already large
|
||||
enough. So this extra expansion code is no longer necessary. In some
|
||||
cases such as processing siblings with alternating scaffolding counts,
|
||||
this logic would actually _shrink_ the array only to then later
|
||||
re-expand it.
|
||||
|
||||
Anthropic: ANT-2026-00037
|
||||
Anthropic: ANT-2026-03621
|
||||
Anthropic: ANT-2026-03867
|
||||
Co-authored-by: Alessandro Gario <alessandro.gario@trailofbits.com>
|
||||
---
|
||||
expat/lib/xmlparse.c | 18 ------------------
|
||||
1 file changed, 18 deletions(-)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index 317b08e0..80fcb968 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -5797,24 +5797,6 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
parser->m_groupConnector = new_connector;
|
||||
}
|
||||
|
||||
- if (dtd->scaffIndex) {
|
||||
- /* Detect and prevent integer overflow.
|
||||
- * The preprocessor guard addresses the "always false" warning
|
||||
- * from -Wtype-limits on platforms where
|
||||
- * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
-#if UINT_MAX >= SIZE_MAX
|
||||
- if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
|
||||
- return XML_ERROR_NO_MEMORY;
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
- int *const new_scaff_index = (int *)REALLOC(
|
||||
- parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
|
||||
- if (new_scaff_index == NULL)
|
||||
- return XML_ERROR_NO_MEMORY;
|
||||
- dtd->scaffIndex = new_scaff_index;
|
||||
- dtd->scaffIndexSize = parser->m_groupSize;
|
||||
- }
|
||||
} else {
|
||||
parser->m_groupConnector
|
||||
= (char *)MALLOC(parser, parser->m_groupSize = 32);
|
||||
|
||||
From 9a4202e63b9a89e2e1ec14996934ff98697c6721 Mon Sep 17 00:00:00 2001
|
||||
From: Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
Date: Thu, 4 Jun 2026 17:01:02 -0700
|
||||
Subject: [PATCH 5/5] lib: Remove indented scoping of `new_connector` local
|
||||
|
||||
Following the previous change, the lifetime of `new_connector` as
|
||||
constrained by this introduced scope was identical to the parent scope.
|
||||
---
|
||||
expat/lib/xmlparse.c | 23 ++++++++++-------------
|
||||
1 file changed, 10 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index 80fcb968..5c255c00 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -5782,21 +5782,18 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
case XML_ROLE_GROUP_OPEN:
|
||||
if (parser->m_prologState.level >= parser->m_groupSize) {
|
||||
if (parser->m_groupSize) {
|
||||
- {
|
||||
- /* Detect and prevent integer overflow */
|
||||
- if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
|
||||
- return XML_ERROR_NO_MEMORY;
|
||||
- }
|
||||
-
|
||||
- char *const new_connector = (char *)REALLOC(
|
||||
- parser, parser->m_groupConnector, parser->m_groupSize *= 2);
|
||||
- if (new_connector == NULL) {
|
||||
- parser->m_groupSize /= 2;
|
||||
- return XML_ERROR_NO_MEMORY;
|
||||
- }
|
||||
- parser->m_groupConnector = new_connector;
|
||||
+ /* Detect and prevent integer overflow */
|
||||
+ if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
|
||||
+ return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
+ char *const new_connector = (char *)REALLOC(
|
||||
+ parser, parser->m_groupConnector, parser->m_groupSize *= 2);
|
||||
+ if (new_connector == NULL) {
|
||||
+ parser->m_groupSize /= 2;
|
||||
+ return XML_ERROR_NO_MEMORY;
|
||||
+ }
|
||||
+ parser->m_groupConnector = new_connector;
|
||||
} else {
|
||||
parser->m_groupConnector
|
||||
= (char *)MALLOC(parser, parser->m_groupSize = 32);
|
||||
176
SPECS/expat.spec
176
SPECS/expat.spec
@ -1,11 +1,10 @@
|
||||
%global unversion 2_5_0
|
||||
|
||||
Summary: An XML parser library
|
||||
Name: expat
|
||||
Version: %(echo %{unversion} | sed 's/_/./g')
|
||||
Release: 2%{?dist}.2
|
||||
Source: https://github.com/libexpat/libexpat/archive/R_%{unversion}.tar.gz#/expat-%{version}.tar.gz
|
||||
Version: 2.5.0
|
||||
Release: 6%{?dist}
|
||||
Source: https://github.com/libexpat/libexpat/archive/R_2_5_0.tar.gz#/expat-%{version}.tar.gz
|
||||
URL: https://libexpat.github.io/
|
||||
VCS: git:https://github.com/libexpat/libexpat.git
|
||||
License: MIT
|
||||
BuildRequires: autoconf, libtool, xmlto, gcc-c++
|
||||
BuildRequires: make
|
||||
@ -23,17 +22,8 @@ Patch4: expat-2.5.0-CVE-2024-45492.patch
|
||||
Patch5: expat-2.5.0-CVE-2024-50602.patch
|
||||
# https://issues.redhat.com/browse/RHEL-57489
|
||||
Patch6: expat-2.5.0-CVE-2024-8176.patch
|
||||
# https://issues.redhat.com/browse/RHEL-114618
|
||||
# https://issues.redhat.com/browse/RHEL-114643
|
||||
Patch7: expat-2.5.0-CVE-2025-59375.patch
|
||||
# https://issues.redhat.com/browse/RHEL-177979
|
||||
# https://github.com/libexpat/libexpat/pull/1216
|
||||
Patch8: expat-2.5.0-CVE-2026-45186.patch
|
||||
# https://issues.redhat.com/browse/RHEL-220979
|
||||
# https://github.com/libexpat/libexpat/pull/1246
|
||||
Patch9: expat-2.5.0-CVE-2026-50219.patch
|
||||
# https://issues.redhat.com/browse/RHEL-221012
|
||||
# https://github.com/libexpat/libexpat/pull/1272
|
||||
Patch10: expat-2.5.0-CVE-2026-56132.patch
|
||||
|
||||
%description
|
||||
This is expat, the C library for parsing XML, written by James Clark. Expat
|
||||
@ -60,7 +50,7 @@ The expat-static package contains the static version of the expat library.
|
||||
Install it if you need to link statically with expat.
|
||||
|
||||
%prep
|
||||
%setup -q -n libexpat-R_%{unversion}/expat
|
||||
%setup -q -n libexpat-R_2_5_0/expat
|
||||
pushd ..
|
||||
%patch0 -p1 -b .CVE-2023-52425
|
||||
%patch1 -p1 -b .CVE-2024-28757
|
||||
@ -70,9 +60,6 @@ pushd ..
|
||||
%patch5 -p1 -b .CVE-2024-50602
|
||||
%patch6 -p1 -b .CVE-2024-8176
|
||||
%patch7 -p1 -b .CVE-2025-59375
|
||||
%patch8 -p1 -b .CVE-2026-45186
|
||||
%patch9 -p1 -b .CVE-2026-50219
|
||||
%patch10 -p1 -b .CVE-2026-56132
|
||||
popd
|
||||
|
||||
sed -i 's/install-data-hook/do-nothing-please/' lib/Makefile.am
|
||||
@ -82,21 +69,21 @@ sed -i 's/install-data-hook/do-nothing-please/' lib/Makefile.am
|
||||
export CFLAGS="$RPM_OPT_FLAGS -fPIC"
|
||||
export DOCBOOK_TO_MAN="xmlto man --skip-validation"
|
||||
%configure
|
||||
make %{?_smp_mflags}
|
||||
%make_build
|
||||
|
||||
%install
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
%make_install
|
||||
|
||||
rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
|
||||
|
||||
%check
|
||||
bash -c "for i in {1..500000}; do printf AAAAAAAAAAAAAAAAAAAA >> achars.txt; done"
|
||||
for testfile in ../testdata/largefiles/aaaaaa_*; do
|
||||
first_part="$(sed 's/\(.*\)ACHARS.*/\1/g' $testfile)"
|
||||
second_part="$(sed 's/.*ACHARS\(.*\)/\1/g' $testfile)"
|
||||
printf "$first_part" > "$testfile"
|
||||
cat achars.txt >> "$testfile"
|
||||
printf "$second_part" >> "$testfile"
|
||||
first_part="$(sed 's/\(.*\)ACHARS.*/\1/g' $testfile)"
|
||||
second_part="$(sed 's/.*ACHARS\(.*\)/\1/g' $testfile)"
|
||||
printf "$first_part" > "$testfile"
|
||||
cat achars.txt >> "$testfile"
|
||||
printf "$second_part" >> "$testfile"
|
||||
done
|
||||
|
||||
make check
|
||||
@ -104,7 +91,6 @@ make check
|
||||
%ldconfig_scriptlets
|
||||
|
||||
%files
|
||||
%{!?_licensedir:%global license %%doc}
|
||||
%doc AUTHORS Changes
|
||||
%license COPYING
|
||||
%{_bindir}/*
|
||||
@ -122,73 +108,50 @@ make check
|
||||
%{_libdir}/lib*.a
|
||||
|
||||
%changelog
|
||||
* Fri Jul 31 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.5.0-2.2
|
||||
- Fix CVE-2026-56132: out-of-bound scaffolding index store in doProlog
|
||||
- Resolves: RHEL-221012
|
||||
|
||||
* Fri Jul 31 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.5.0-2.1
|
||||
- Fix CVE-2026-50219
|
||||
- Resolves: RHEL-220979
|
||||
|
||||
* Thu May 28 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.5.0-2
|
||||
- Fix CVE-2026-45186
|
||||
- Resolves: RHEL-177979
|
||||
|
||||
* Wed Nov 19 2025 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-1
|
||||
- Rebase to version 2.5.0
|
||||
* Tue Dec 02 2025 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-6
|
||||
- Fix CVE-2025-59375
|
||||
- Resolves: RHEL-114618
|
||||
- Resolves: RHEL-114643
|
||||
|
||||
* Mon Apr 07 2025 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-17
|
||||
* Mon Mar 31 2025 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-5
|
||||
- Fix CVE-2024-8176
|
||||
- Resolves: RHEL-57477
|
||||
- Resolves: RHEL-57489
|
||||
|
||||
* Fri Nov 08 2024 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-16
|
||||
* Thu Nov 07 2024 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-4
|
||||
- Fix CVE-2024-50602
|
||||
- Resolves: RHEL-65062
|
||||
- Resolves: RHEL-65066
|
||||
|
||||
* Wed Sep 11 2024 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-15
|
||||
- Rebuild for test reconfiguration
|
||||
* Wed Oct 09 2024 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-3
|
||||
- Fix CVE-2024-45490, CVE-2024-45491, CVE-2024-45492
|
||||
- Resolves: RHEL-56761
|
||||
- Resolves: RHEL-57520
|
||||
- Resolves: RHEL-57511
|
||||
|
||||
* Wed Sep 11 2024 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-14
|
||||
- Fix multiple CVEs
|
||||
- Fix CVE-2024-45492 integer overflow
|
||||
- Fix CVE-2024-45491 Integer Overflow or Wraparound
|
||||
- Fix CVE-2024-45490 Negative Length Parsing Vulnerability
|
||||
- Resolves: RHEL-57505
|
||||
- Resolves: RHEL-57493
|
||||
- Resolves: RHEL-56751
|
||||
* Tue Feb 13 2024 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-2
|
||||
- Fix parsing of large tokens
|
||||
- Reject direct parameter entity recursion
|
||||
- Resolves: RHEL-29699
|
||||
- Resolves: RHEL-29696
|
||||
|
||||
* Tue Mar 26 2024 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-13
|
||||
- Fix wrongly exposed variables
|
||||
- Resolves: RHEL-29321
|
||||
|
||||
* Thu Mar 21 2024 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-12
|
||||
- CVE-2023-52425 expat: parsing large tokens can trigger a denial of service
|
||||
- Resolves: RHEL-29321
|
||||
|
||||
* Mon Nov 14 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-11
|
||||
- CVE-2022-43680 expat: use-after free caused by overeager destruction of a shared DTD in XML_ExternalEntityParserCreate
|
||||
* Thu Nov 10 2022 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-1
|
||||
- Rebase to version 2.5.0
|
||||
- Resolves: CVE-2022-43680
|
||||
|
||||
* Fri Sep 30 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-10
|
||||
- Ensure raw tagnames are safe exiting internalEntityParser
|
||||
* Thu Sep 29 2022 Tomas Korbar <tkorbar@redhat.com> - 2.4.9-1
|
||||
- Rebase to version 2.4.9
|
||||
- Resolves: CVE-2022-40674
|
||||
|
||||
* Fri May 06 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-9
|
||||
- Fix multiple CVEs
|
||||
- Resolves: CVE-2022-25314
|
||||
* Tue Apr 26 2022 Tomas Korbar <tkorbar@redhat.com> - 2.4.7-1
|
||||
- Rebase to version 2.4.7
|
||||
- Resolves: rhbz#2067201
|
||||
- Resolves: CVE-2022-25313
|
||||
- Resolves: CVE-2022-25314
|
||||
- Resolves: CVE-2022-25236
|
||||
|
||||
* Mon Mar 14 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-8
|
||||
- Improve patch for CVE-2022-25236
|
||||
* Mon Mar 14 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.10-11
|
||||
- Improve fix for CVE-2022-25236
|
||||
- Related: CVE-2022-25236
|
||||
|
||||
* Fri Mar 04 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-7
|
||||
- Fix patch for CVE-2022-25235
|
||||
- Resolves: CVE-2022-25235
|
||||
|
||||
* Thu Mar 03 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-6
|
||||
* Mon Feb 28 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.10-10
|
||||
- Fix multiple CVEs
|
||||
- CVE-2022-25236 expat: namespace-separator characters in "xmlns[:prefix]" attribute values can lead to arbitrary code execution
|
||||
- CVE-2022-25235 expat: malformed 2- and 3-byte UTF-8 sequences can lead to arbitrary code execution
|
||||
@ -197,20 +160,25 @@ make check
|
||||
- Resolves: CVE-2022-25235
|
||||
- Resolves: CVE-2022-25315
|
||||
|
||||
* Fri Feb 14 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-5
|
||||
- Fix multiple CVEs
|
||||
* Thu Feb 10 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.10-9
|
||||
- CVE-2022-23852 expat: integer overflow in function XML_GetBuffer
|
||||
- Resolves: CVE-2022-23852
|
||||
|
||||
* Thu Feb 10 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.10-8
|
||||
- CVE-2021-45960 expat: Large number of prefixed XML attributes on a single tag can crash libexpat
|
||||
- Resolves: CVE-2021-45960
|
||||
|
||||
* Wed Feb 09 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.10-7
|
||||
- CVE-2021-46143 expat: Integer overflow in doProlog in xmlparse.c
|
||||
- Resolves: CVE-2021-46143
|
||||
|
||||
* Wed Feb 09 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.10-6
|
||||
- CVE-2022-22827 Integer overflow in storeAtts in xmlparse.c
|
||||
- CVE-2022-22826 Integer overflow in nextScaffoldPart in xmlparse.c
|
||||
- CVE-2022-22825 Integer overflow in lookup in xmlparse.c
|
||||
- CVE-2022-22824 Integer overflow in defineAttribute in xmlparse.c
|
||||
- CVE-2022-22823 Integer overflow in build_model in xmlparse.c
|
||||
- CVE-2022-22822 Integer overflow in addBinding in xmlparse.c
|
||||
- Resolves: CVE-2022-23852
|
||||
- Resolves: CVE-2021-45960
|
||||
- Resolves: CVE-2021-46143
|
||||
- Resolves: CVE-2022-22827
|
||||
- Resolves: CVE-2022-22826
|
||||
- Resolves: CVE-2022-22825
|
||||
@ -218,8 +186,46 @@ make check
|
||||
- Resolves: CVE-2022-22823
|
||||
- Resolves: CVE-2022-22822
|
||||
|
||||
* Fri Apr 24 2020 Joe Orton <jorton@redhat.com> - 2.2.5-4
|
||||
- add security fixes for CVE-2018-20843, CVE-2019-15903
|
||||
* Mon Feb 07 2022 Tomas Korbar <tkorbar@redhat.com> - 2.2.10-5
|
||||
- CVE-2022-23990 expat: integer overflow in the doProlog function
|
||||
- Resolve: rhbz#2050503
|
||||
|
||||
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 2.2.10-4
|
||||
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
|
||||
Related: rhbz#1991688
|
||||
|
||||
* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 2.2.10-3
|
||||
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
|
||||
|
||||
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.10-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
|
||||
|
||||
* Fri Nov 13 2020 Joe Orton <jorton@redhat.com> - 2.2.10-1
|
||||
- update to 2.2.10 (#1884940)
|
||||
|
||||
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.8-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||
|
||||
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.8-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
||||
|
||||
* Mon Sep 16 2019 Joe Orton <jorton@redhat.com> - 2.2.8-1
|
||||
- update to 2.2.8 (#1752167)
|
||||
|
||||
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.7-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
* Thu Jun 27 2019 Joe Orton <jorton@redhat.com> - 2.2.7-1
|
||||
- update to 2.2.7 (#1723724, #1722224)
|
||||
|
||||
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.6-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||
|
||||
* Wed Aug 15 2018 Joe Orton <jorton@redhat.com> - 2.2.6-1
|
||||
- update to 2.2.6
|
||||
|
||||
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.5-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||
|
||||
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.5-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||
|
||||
Loading…
Reference in New Issue
Block a user