libxml2/SOURCES/libxml2-2.9.13-CVE-2025-49794.patch

195 lines
6.5 KiB
Diff

From b2a28a861e9d43a23b877c3994daa28f8af69618 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Fri, 4 Jul 2025 14:28:26 +0200
Subject: [PATCH] schematron: Fix memory safety issues in
xmlSchematronReportOutput
Fix use-after-free (CVE-2025-49794) and type confusion (CVE-2025-49796)
in xmlSchematronReportOutput.
Fixes #931.
Fixes #933.
---
result/schematron/cve-2025-49794_0.err | 2 +
result/schematron/cve-2025-49796_0.err | 2 +
schematron.c | 67 ++++++++++++++------------
test/schematron/cve-2025-49794.sct | 10 ++++
test/schematron/cve-2025-49794_0.xml | 6 +++
test/schematron/cve-2025-49796.sct | 9 ++++
test/schematron/cve-2025-49796_0.xml | 3 ++
7 files changed, 67 insertions(+), 32 deletions(-)
create mode 100644 result/schematron/cve-2025-49794_0.err
create mode 100644 result/schematron/cve-2025-49796_0.err
create mode 100644 test/schematron/cve-2025-49794.sct
create mode 100644 test/schematron/cve-2025-49794_0.xml
create mode 100644 test/schematron/cve-2025-49796.sct
create mode 100644 test/schematron/cve-2025-49796_0.xml
diff --git a/result/schematron/cve-2025-49794_0.err b/result/schematron/cve-2025-49794_0.err
new file mode 100644
index 00000000..57752310
--- /dev/null
+++ b/result/schematron/cve-2025-49794_0.err
@@ -0,0 +1,2 @@
+./test/schematron/cve-2025-49794_0.xml:2: element boo0: schematron error : /librar0/boo0 line 2:
+./test/schematron/cve-2025-49794_0.xml fails to validate
diff --git a/result/schematron/cve-2025-49796_0.err b/result/schematron/cve-2025-49796_0.err
new file mode 100644
index 00000000..bf875ee0
--- /dev/null
+++ b/result/schematron/cve-2025-49796_0.err
@@ -0,0 +1,2 @@
+./test/schematron/cve-2025-49796_0.xml:2: element boo0: schematron error : /librar0/boo0 line 2:
+./test/schematron/cve-2025-49796_0.xml fails to validate
diff --git a/schematron.c b/schematron.c
index ddbb069b..0c7bc84a 100644
--- a/schematron.c
+++ b/schematron.c
@@ -1239,27 +1239,15 @@ exit:
* *
************************************************************************/
-static xmlNodePtr
+static xmlXPathObjectPtr
xmlSchematronGetNode(xmlSchematronValidCtxtPtr ctxt,
xmlNodePtr cur, const xmlChar *xpath) {
- xmlNodePtr node = NULL;
- xmlXPathObjectPtr ret;
-
if ((ctxt == NULL) || (cur == NULL) || (xpath == NULL))
return(NULL);
ctxt->xctxt->doc = cur->doc;
ctxt->xctxt->node = cur;
- ret = xmlXPathEval(xpath, ctxt->xctxt);
- if (ret == NULL)
- return(NULL);
-
- if ((ret->type == XPATH_NODESET) &&
- (ret->nodesetval != NULL) && (ret->nodesetval->nodeNr > 0))
- node = ret->nodesetval->nodeTab[0];
-
- xmlXPathFreeObject(ret);
- return(node);
+ return(xmlXPathEval(xpath, ctxt->xctxt));
}
/**
@@ -1301,28 +1289,43 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
child = test->children;
while (child != NULL) {
if ((child->type == XML_TEXT_NODE) ||
- (child->type == XML_CDATA_SECTION_NODE))
- ret = xmlStrcat(ret, child->content);
- else if (IS_SCHEMATRON(child, "name")) {
- xmlChar *path;
+ (child->type == XML_CDATA_SECTION_NODE))
+ ret = xmlStrcat(ret, child->content);
+ else if (IS_SCHEMATRON(child, "name")) {
+ xmlXPathObject *obj = NULL;
+ xmlChar *path;
path = xmlGetNoNsProp(child, BAD_CAST "path");
node = cur;
- if (path != NULL) {
- node = xmlSchematronGetNode(ctxt, cur, path);
- if (node == NULL)
- node = cur;
- xmlFree(path);
- }
-
- if ((node->ns == NULL) || (node->ns->prefix == NULL))
- ret = xmlStrcat(ret, node->name);
- else {
- ret = xmlStrcat(ret, node->ns->prefix);
- ret = xmlStrcat(ret, BAD_CAST ":");
- ret = xmlStrcat(ret, node->name);
- }
+ if (path != NULL) {
+ obj = xmlSchematronGetNode(ctxt, cur, path);
+ if ((obj != NULL) &&
+ (obj->type == XPATH_NODESET) &&
+ (obj->nodesetval != NULL) &&
+ (obj->nodesetval->nodeNr > 0))
+ node = obj->nodesetval->nodeTab[0];
+ xmlFree(path);
+ }
+
+ switch (node->type) {
+ case XML_ELEMENT_NODE:
+ case XML_ATTRIBUTE_NODE:
+ if ((node->ns == NULL) || (node->ns->prefix == NULL))
+ ret = xmlStrcat(ret, node->name);
+ else {
+ ret = xmlStrcat(ret, node->ns->prefix);
+ ret = xmlStrcat(ret, BAD_CAST ":");
+ ret = xmlStrcat(ret, node->name);
+ }
+ break;
+
+ /* TODO: handle other node types */
+ default:
+ break;
+ }
+
+ xmlXPathFreeObject(obj);
} else {
child = child->next;
continue;
diff --git a/test/schematron/cve-2025-49794.sct b/test/schematron/cve-2025-49794.sct
new file mode 100644
index 00000000..7fc9ee3d
--- /dev/null
+++ b/test/schematron/cve-2025-49794.sct
@@ -0,0 +1,10 @@
+<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
+ <sch:pattern id="">
+ <sch:rule context="boo0">
+ <sch:report test="not(0)">
+ <sch:name path="&#9;e|namespace::*|e"/>
+ </sch:report>
+ <sch:report test="0"></sch:report>
+ </sch:rule>
+ </sch:pattern>
+</sch:schema>
diff --git a/test/schematron/cve-2025-49794_0.xml b/test/schematron/cve-2025-49794_0.xml
new file mode 100644
index 00000000..debc64ba
--- /dev/null
+++ b/test/schematron/cve-2025-49794_0.xml
@@ -0,0 +1,6 @@
+<librar0>
+ <boo0 t="">
+ <author></author>
+ </boo0>
+ <ins></ins>
+</librar0>
diff --git a/test/schematron/cve-2025-49796.sct b/test/schematron/cve-2025-49796.sct
new file mode 100644
index 00000000..e9702d75
--- /dev/null
+++ b/test/schematron/cve-2025-49796.sct
@@ -0,0 +1,9 @@
+<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
+ <sch:pattern id="">
+ <sch:rule context="boo0">
+ <sch:report test="not(0)">
+ <sch:name path="/"/>
+ </sch:report>
+ </sch:rule>
+ </sch:pattern>
+</sch:schema>
diff --git a/test/schematron/cve-2025-49796_0.xml b/test/schematron/cve-2025-49796_0.xml
new file mode 100644
index 00000000..be33c4ec
--- /dev/null
+++ b/test/schematron/cve-2025-49796_0.xml
@@ -0,0 +1,3 @@
+<librar0>
+ <boo0/>
+</librar0>
--
2.49.0