Compare commits
No commits in common. "c8" and "c9s-plans-gating-update" have entirely different histories.
c8
...
c9s-plans-
@ -1 +0,0 @@
|
||||
03d9882ede56aa48919fbf50fe17614630257a82 SOURCES/expat-2.5.0.tar.gz
|
||||
1
.fmf/version
Normal file
1
.fmf/version
Normal file
@ -0,0 +1 @@
|
||||
1
|
||||
24
.gitignore
vendored
24
.gitignore
vendored
@ -1 +1,23 @@
|
||||
SOURCES/expat-2.5.0.tar.gz
|
||||
expat-1.95.8.tar.gz
|
||||
i386
|
||||
*.rpm
|
||||
clog
|
||||
expat-2.0.1.tar.gz
|
||||
/results_expat
|
||||
/expat-2.?.?
|
||||
/expat-2.1.0.tar.gz
|
||||
/expat-2.1.1.tar.bz2
|
||||
/expat-2.2.0.tar.bz2
|
||||
/expat-2.2.1.tar.gz
|
||||
/expat-2.2.2.tar.gz
|
||||
/libexpat-R_*
|
||||
/expat-2.2.3.tar.gz
|
||||
/expat-2.2.4.tar.gz
|
||||
/expat-2.2.5.tar.gz
|
||||
/expat-2.2.6.tar.gz
|
||||
/expat-2.2.7.tar.gz
|
||||
/expat-2.2.8.tar.gz
|
||||
/expat-2.2.10.tar.gz
|
||||
/expat-2.4.7.tar.gz
|
||||
/expat-2.4.9.tar.gz
|
||||
/expat-2.5.0.tar.gz
|
||||
|
||||
@ -1,129 +0,0 @@
|
||||
commit 05d87eb116ddde35bfa4e4c1d2ec7bcbda38c09b
|
||||
Author: Tomas Korbar <tkorbar@redhat.com>
|
||||
Date: Wed Sep 11 13:48:58 2024 +0200
|
||||
|
||||
Fix CVE-2024-45490
|
||||
|
||||
https://github.com/libexpat/libexpat/pull/890
|
||||
|
||||
diff --git a/expat/doc/reference.html b/expat/doc/reference.html
|
||||
index a10f3cb..d618bd8 100644
|
||||
--- a/expat/doc/reference.html
|
||||
+++ b/expat/doc/reference.html
|
||||
@@ -1098,7 +1098,9 @@ containing part (or perhaps all) of the document. The number of bytes of s
|
||||
that are part of the document is indicated by <code>len</code>. This means
|
||||
that <code>s</code> doesn't have to be null terminated. It also means that
|
||||
if <code>len</code> is larger than the number of bytes in the block of
|
||||
-memory that <code>s</code> points at, then a memory fault is likely. The
|
||||
+memory that <code>s</code> points at, then a memory fault is likely.
|
||||
+Negative values for <code>len</code> are rejected since Expat 2.2.1.
|
||||
+The
|
||||
<code>isFinal</code> parameter informs the parser that this is the last
|
||||
piece of the document. Frequently, the last piece is empty (i.e.
|
||||
<code>len</code> is zero.)
|
||||
@@ -1114,11 +1116,17 @@ XML_ParseBuffer(XML_Parser p,
|
||||
int isFinal);
|
||||
</pre>
|
||||
<div class="fcndef">
|
||||
+<p>
|
||||
This is just like <code><a href= "#XML_Parse" >XML_Parse</a></code>,
|
||||
except in this case Expat provides the buffer. By obtaining the
|
||||
buffer from Expat with the <code><a href= "#XML_GetBuffer"
|
||||
>XML_GetBuffer</a></code> function, the application can avoid double
|
||||
copying of the input.
|
||||
+</p>
|
||||
+
|
||||
+<p>
|
||||
+Negative values for <code>len</code> are rejected since Expat 2.6.3.
|
||||
+</p>
|
||||
</div>
|
||||
|
||||
<h4 id="XML_GetBuffer">XML_GetBuffer</h4>
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index 0896b16..f54e258 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -1998,6 +1998,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
|
||||
|
||||
if (parser == NULL)
|
||||
return XML_STATUS_ERROR;
|
||||
+
|
||||
+ if (len < 0) {
|
||||
+ parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
|
||||
+ return XML_STATUS_ERROR;
|
||||
+ }
|
||||
+
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
case XML_SUSPENDED:
|
||||
parser->m_errorCode = XML_ERROR_SUSPENDED;
|
||||
diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c
|
||||
index 93adc45..ed88f9f 100644
|
||||
--- a/expat/tests/runtests.c
|
||||
+++ b/expat/tests/runtests.c
|
||||
@@ -3856,6 +3856,57 @@ START_TEST(test_empty_parse) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
+/* Test XML_Parse for len < 0 */
|
||||
+START_TEST(test_negative_len_parse) {
|
||||
+ const char *const doc = "<root/>";
|
||||
+ for (int isFinal = 0; isFinal < 2; isFinal++) {
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+
|
||||
+ if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
|
||||
+ fail("There was not supposed to be any initial parse error.");
|
||||
+
|
||||
+ const enum XML_Status status = XML_Parse(parser, doc, -1, isFinal);
|
||||
+
|
||||
+ if (status != XML_STATUS_ERROR)
|
||||
+ fail("Negative len was expected to fail the parse but did not.");
|
||||
+
|
||||
+ if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
|
||||
+ fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+ }
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+/* Test XML_ParseBuffer for len < 0 */
|
||||
+START_TEST(test_negative_len_parse_buffer) {
|
||||
+ const char *const doc = "<root/>";
|
||||
+ for (int isFinal = 0; isFinal < 2; isFinal++) {
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+
|
||||
+ if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
|
||||
+ fail("There was not supposed to be any initial parse error.");
|
||||
+
|
||||
+ void *const buffer = XML_GetBuffer(parser, (int)strlen(doc));
|
||||
+
|
||||
+ if (buffer == NULL)
|
||||
+ fail("XML_GetBuffer failed.");
|
||||
+
|
||||
+ memcpy(buffer, doc, strlen(doc));
|
||||
+
|
||||
+ const enum XML_Status status = XML_ParseBuffer(parser, -1, isFinal);
|
||||
+
|
||||
+ if (status != XML_STATUS_ERROR)
|
||||
+ fail("Negative len was expected to fail the parse but did not.");
|
||||
+
|
||||
+ if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
|
||||
+ fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
|
||||
+
|
||||
+ XML_ParserFree(parser);
|
||||
+ }
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
/* Test odd corners of the XML_GetBuffer interface */
|
||||
static enum XML_Status
|
||||
get_feature(enum XML_FeatureEnum feature_id, long *presult) {
|
||||
@@ -12937,6 +12988,8 @@ make_suite(void) {
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
|
||||
tcase_add_test(tc_basic, test_empty_parse);
|
||||
+ tcase_add_test(tc_basic, test_negative_len_parse);
|
||||
+ tcase_add_test(tc_basic, test_negative_len_parse_buffer);
|
||||
tcase_add_test(tc_basic, test_get_buffer_1);
|
||||
tcase_add_test(tc_basic, test_get_buffer_2);
|
||||
#if defined(XML_CONTEXT_BYTES)
|
||||
@ -1,31 +0,0 @@
|
||||
From 8e439a9947e9dc80a395c0c7456545d8d9d9e421 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Pipping <sebastian@pipping.org>
|
||||
Date: Mon, 19 Aug 2024 22:34:13 +0200
|
||||
Subject: [PATCH] lib: Detect integer overflow in dtdCopy
|
||||
|
||||
Reported by TaiYou
|
||||
---
|
||||
expat/lib/xmlparse.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index 91682c188..e2327bdcf 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -7016,6 +7016,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
if (! newE)
|
||||
return 0;
|
||||
if (oldE->nDefaultAtts) {
|
||||
+ /* Detect and prevent integer overflow.
|
||||
+ * The preprocessor guard addresses the "always false" warning
|
||||
+ * from -Wtype-limits on platforms where
|
||||
+ * sizeof(int) < sizeof(size_t), e.g. on x86_64. */
|
||||
+#if UINT_MAX >= SIZE_MAX
|
||||
+ if ((size_t)oldE->nDefaultAtts
|
||||
+ > ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+#endif
|
||||
newE->defaultAtts
|
||||
= ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
|
||||
if (! newE->defaultAtts) {
|
||||
@ -1,30 +0,0 @@
|
||||
From 9bf0f2c16ee86f644dd1432507edff94c08dc232 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Pipping <sebastian@pipping.org>
|
||||
Date: Mon, 19 Aug 2024 22:37:16 +0200
|
||||
Subject: [PATCH] lib: Detect integer overflow in function nextScaffoldPart
|
||||
|
||||
Reported by TaiYou
|
||||
---
|
||||
expat/lib/xmlparse.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index 91682c188..f737575ea 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -7558,6 +7558,15 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
int next;
|
||||
|
||||
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 -1;
|
||||
+ }
|
||||
+#endif
|
||||
dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
|
||||
if (! dtd->scaffIndex)
|
||||
return -1;
|
||||
@ -1,108 +0,0 @@
|
||||
commit 38905b99bb78a6a691ed8358f30030116783656c
|
||||
Author: Tomas Korbar <tkorbar@redhat.com>
|
||||
Date: Thu Nov 7 15:00:46 2024 +0100
|
||||
|
||||
Fix CVE-2024-50602
|
||||
|
||||
See https://github.com/libexpat/libexpat/pull/915
|
||||
|
||||
diff --git a/expat/lib/expat.h b/expat/lib/expat.h
|
||||
index 842dd70..69b0ba1 100644
|
||||
--- a/expat/lib/expat.h
|
||||
+++ b/expat/lib/expat.h
|
||||
@@ -128,7 +128,9 @@ enum XML_Error {
|
||||
/* Added in 2.3.0. */
|
||||
XML_ERROR_NO_BUFFER,
|
||||
/* Added in 2.4.0. */
|
||||
- XML_ERROR_AMPLIFICATION_LIMIT_BREACH
|
||||
+ XML_ERROR_AMPLIFICATION_LIMIT_BREACH,
|
||||
+ /* Added in 2.6.4. */
|
||||
+ XML_ERROR_NOT_STARTED,
|
||||
};
|
||||
|
||||
enum XML_Content_Type {
|
||||
diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
|
||||
index e0c2873..8b2af91 100644
|
||||
--- a/expat/lib/xmlparse.c
|
||||
+++ b/expat/lib/xmlparse.c
|
||||
@@ -2193,6 +2193,9 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
|
||||
if (parser == NULL)
|
||||
return XML_STATUS_ERROR;
|
||||
switch (parser->m_parsingStatus.parsing) {
|
||||
+ case XML_INITIALIZED:
|
||||
+ parser->m_errorCode = XML_ERROR_NOT_STARTED;
|
||||
+ return XML_STATUS_ERROR;
|
||||
case XML_SUSPENDED:
|
||||
if (resumable) {
|
||||
parser->m_errorCode = XML_ERROR_SUSPENDED;
|
||||
@@ -2203,7 +2206,7 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
|
||||
case XML_FINISHED:
|
||||
parser->m_errorCode = XML_ERROR_FINISHED;
|
||||
return XML_STATUS_ERROR;
|
||||
- default:
|
||||
+ case XML_PARSING:
|
||||
if (resumable) {
|
||||
#ifdef XML_DTD
|
||||
if (parser->m_isParamEntity) {
|
||||
@@ -2214,6 +2217,9 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
|
||||
parser->m_parsingStatus.parsing = XML_SUSPENDED;
|
||||
} else
|
||||
parser->m_parsingStatus.parsing = XML_FINISHED;
|
||||
+ break;
|
||||
+ default:
|
||||
+ assert(0);
|
||||
}
|
||||
return XML_STATUS_OK;
|
||||
}
|
||||
@@ -2478,6 +2484,9 @@ XML_ErrorString(enum XML_Error code) {
|
||||
case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
|
||||
return XML_L(
|
||||
"limit on input amplification factor (from DTD and entities) breached");
|
||||
+ /* Added in 2.6.4. */
|
||||
+ case XML_ERROR_NOT_STARTED:
|
||||
+ return XML_L("parser not started");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
diff --git a/expat/tests/runtests.c b/expat/tests/runtests.c
|
||||
index ed88f9f..5769aa0 100644
|
||||
--- a/expat/tests/runtests.c
|
||||
+++ b/expat/tests/runtests.c
|
||||
@@ -8711,6 +8711,28 @@ START_TEST(test_misc_tag_mismatch_reset_leak) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
+START_TEST(test_misc_resumeparser_not_crashing) {
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ XML_GetBuffer(parser, 1);
|
||||
+ XML_StopParser(parser, /*resumable=*/XML_TRUE);
|
||||
+ XML_ResumeParser(parser); // could crash here, previously
|
||||
+ XML_ParserFree(parser);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
+START_TEST(test_misc_stopparser_rejects_unstarted_parser) {
|
||||
+ const XML_Bool cases[] = {XML_TRUE, XML_FALSE};
|
||||
+ for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
+ const XML_Bool resumable = cases[i];
|
||||
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_NONE);
|
||||
+ assert_true(XML_StopParser(parser, resumable) == XML_STATUS_ERROR);
|
||||
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_NOT_STARTED);
|
||||
+ XML_ParserFree(parser);
|
||||
+ }
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
static void
|
||||
alloc_setup(void) {
|
||||
XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
|
||||
@@ -13176,6 +13198,8 @@ make_suite(void) {
|
||||
tcase_add_test__ifdef_xml_dtd(
|
||||
tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
|
||||
tcase_add_test(tc_misc, test_misc_tag_mismatch_reset_leak);
|
||||
+ tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
|
||||
+ tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
|
||||
|
||||
suite_add_tcase(s, tc_alloc);
|
||||
tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
@ -13,21 +13,6 @@ BuildRequires: make
|
||||
Patch0: expat-2.5.0-CVE-2023-52425.patch
|
||||
# https://issues.redhat.com/browse/RHEL-28700
|
||||
Patch1: expat-2.5.0-CVE-2024-28757.patch
|
||||
# https://issues.redhat.com/browse/RHEL-56761
|
||||
Patch2: expat-2.5.0-CVE-2024-45490.patch
|
||||
# https://issues.redhat.com/browse/RHEL-57520
|
||||
Patch3: expat-2.5.0-CVE-2024-45491.patch
|
||||
# https://issues.redhat.com/browse/RHEL-57511
|
||||
Patch4: expat-2.5.0-CVE-2024-45492.patch
|
||||
# https://issues.redhat.com/browse/RHEL-65066
|
||||
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
|
||||
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
|
||||
|
||||
%description
|
||||
This is expat, the C library for parsing XML, written by James Clark. Expat
|
||||
@ -58,13 +43,6 @@ Install it if you need to link statically with expat.
|
||||
pushd ..
|
||||
%patch0 -p1 -b .CVE-2023-52425
|
||||
%patch1 -p1 -b .CVE-2024-28757
|
||||
%patch2 -p1 -b .CVE-2024-45490
|
||||
%patch3 -p1 -b .CVE-2024-45491
|
||||
%patch4 -p1 -b .CVE-2024-45492
|
||||
%patch5 -p1 -b .CVE-2024-50602
|
||||
%patch6 -p1 -b .CVE-2024-8176
|
||||
%patch7 -p1 -b .CVE-2025-59375
|
||||
%patch8 -p1 -b .CVE-2026-45186
|
||||
popd
|
||||
|
||||
sed -i 's/install-data-hook/do-nothing-please/' lib/Makefile.am
|
||||
@ -74,21 +52,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
|
||||
@ -96,7 +74,6 @@ make check
|
||||
%ldconfig_scriptlets
|
||||
|
||||
%files
|
||||
%{!?_licensedir:%global license %%doc}
|
||||
%doc AUTHORS Changes
|
||||
%license COPYING
|
||||
%{_bindir}/*
|
||||
@ -114,65 +91,32 @@ make check
|
||||
%{_libdir}/lib*.a
|
||||
|
||||
%changelog
|
||||
* Thu May 28 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.5.0-2
|
||||
- Fix CVE-2026-45186
|
||||
- Resolves: RHEL-177979
|
||||
* 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
|
||||
|
||||
* Wed Nov 19 2025 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-1
|
||||
* Thu Nov 10 2022 Tomas Korbar <tkorbar@redhat.com> - 2.5.0-1
|
||||
- Rebase to version 2.5.0
|
||||
- Fix CVE-2025-59375
|
||||
- Resolves: RHEL-114618
|
||||
|
||||
* Mon Apr 07 2025 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-17
|
||||
- Fix CVE-2024-8176
|
||||
- Resolves: RHEL-57477
|
||||
|
||||
* Fri Nov 08 2024 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-16
|
||||
- Fix CVE-2024-50602
|
||||
- Resolves: RHEL-65062
|
||||
|
||||
* Wed Sep 11 2024 Tomas Korbar <tkorbar@redhat.com> - 2.2.5-15
|
||||
- Rebuild for test reconfiguration
|
||||
|
||||
* 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 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
|
||||
- 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
|
||||
@ -181,20 +125,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
|
||||
@ -202,8 +151,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
|
||||
25
gating.yaml
Normal file
25
gating.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
--- !Policy
|
||||
product_versions:
|
||||
- fedora-*
|
||||
decision_context: bodhi_update_push_testing
|
||||
subject_type: koji_build
|
||||
rules:
|
||||
- !PassingTestCaseRule {test_case_name: fedora-ci.koji-build./plans/tier1-public.functional}
|
||||
|
||||
#Rawhide
|
||||
--- !Policy
|
||||
product_versions:
|
||||
- fedora-*
|
||||
decision_context: bodhi_update_push_stable
|
||||
subject_type: koji_build
|
||||
rules:
|
||||
- !PassingTestCaseRule {test_case_name: fedora-ci.koji-build./plans/tier1-public.functional}
|
||||
|
||||
#gating rhel
|
||||
--- !Policy
|
||||
product_versions:
|
||||
- rhel-*
|
||||
decision_context: osci_compose_gate
|
||||
rules:
|
||||
- !PassingTestCaseRule {test_case_name: osci.brew-build./plans/tier1-public.functional}
|
||||
- !PassingTestCaseRule {test_case_name: osci.brew-build./plans/tier1-internal.functional}
|
||||
36
plans.fmf
Normal file
36
plans.fmf
Normal file
@ -0,0 +1,36 @@
|
||||
/tier1-internal:
|
||||
plan:
|
||||
import:
|
||||
url: https://src.fedoraproject.org/tests/expat.git
|
||||
name: /plans/tier1/internal
|
||||
|
||||
/tier1-public:
|
||||
plan:
|
||||
import:
|
||||
url: https://src.fedoraproject.org/tests/expat.git
|
||||
name: /plans/tier1/public
|
||||
|
||||
/tier2-tier3-internal:
|
||||
plan:
|
||||
import:
|
||||
url: https://src.fedoraproject.org/tests/expat.git
|
||||
name: /plans/tier2-tier3/internal
|
||||
|
||||
/tier2-tier3-public:
|
||||
plan:
|
||||
import:
|
||||
url: https://src.fedoraproject.org/tests/expat.git
|
||||
name: /plans/tier2-tier3/public
|
||||
|
||||
/others-internal:
|
||||
plan:
|
||||
import:
|
||||
url: https://src.fedoraproject.org/tests/expat.git
|
||||
name: /plans/others/internal
|
||||
|
||||
/others-public:
|
||||
plan:
|
||||
import:
|
||||
url: https://src.fedoraproject.org/tests/expat.git
|
||||
name: /plans/others/public
|
||||
|
||||
Loading…
Reference in New Issue
Block a user