1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-08-03 08:21:55 +03:00

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.
This commit is contained in:
Nick Wellnhofer
2025-07-04 14:28:26 +02:00
parent 24d7e15914
commit 71e1e8af5e
7 changed files with 58 additions and 23 deletions

View File

@ -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

View File

@ -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

View File

@ -1364,27 +1364,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));
}
/**
@ -1427,25 +1415,40 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
(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;
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);
}
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);
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 if (IS_SCHEMATRON(child, "value-of")) {
xmlChar *select;
xmlXPathObjectPtr eval;

View File

@ -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>

View File

@ -0,0 +1,6 @@
<librar0>
<boo0 t="">
<author></author>
</boo0>
<ins></ins>
</librar0>

View File

@ -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>

View File

@ -0,0 +1,3 @@
<librar0>
<boo0/>
</librar0>