From 90e3de1f97f2db56ff1fd1e480e9f7780dfa67b5 Mon Sep 17 00:00:00 2001 From: gaosix Date: Tue, 5 Aug 2025 09:06:58 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=89=E5=85=A8=E8=A1=A5=E4=B8=81?= =?UTF-8?q?=E5=9B=9E=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: gaosix --- ...-issues-in-xmlSchematronReportOutput.patch | 181 ++++++++++++++++++ install.py | 3 +- 2 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch diff --git a/Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch b/Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch new file mode 100644 index 0000000..772c9ac --- /dev/null +++ b/Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch @@ -0,0 +1,181 @@ +From 71e1e8af5ee46dad1b57bb96cfbf1c3ad21fbd7b Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 | 49 ++++++++++++++------------ + 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, 58 insertions(+), 23 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 000000000..57752310e +--- /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 000000000..bf875ee0c +--- /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 85b462827..0fd374617 100644 +--- a/schematron.c ++++ b/schematron.c +@@ -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; +diff --git a/test/schematron/cve-2025-49794.sct b/test/schematron/cve-2025-49794.sct +new file mode 100644 +index 000000000..7fc9ee3db +--- /dev/null ++++ b/test/schematron/cve-2025-49794.sct +@@ -0,0 +1,10 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/test/schematron/cve-2025-49794_0.xml b/test/schematron/cve-2025-49794_0.xml +new file mode 100644 +index 000000000..debc64ba6 +--- /dev/null ++++ b/test/schematron/cve-2025-49794_0.xml +@@ -0,0 +1,6 @@ ++ ++ ++ ++ ++ ++ +diff --git a/test/schematron/cve-2025-49796.sct b/test/schematron/cve-2025-49796.sct +new file mode 100644 +index 000000000..e9702d752 +--- /dev/null ++++ b/test/schematron/cve-2025-49796.sct +@@ -0,0 +1,9 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/test/schematron/cve-2025-49796_0.xml b/test/schematron/cve-2025-49796_0.xml +new file mode 100644 +index 000000000..be33c4ec5 +--- /dev/null ++++ b/test/schematron/cve-2025-49796_0.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +-- +GitLab diff --git a/install.py b/install.py index 3965dd5..3b4a14c 100755 --- a/install.py +++ b/install.py @@ -239,7 +239,8 @@ def do_patch(args, target_dir): "Fix-CVE-2025-32415.patch", "Backport-CVE-2025-6021-tree-Fix-integer-overflow-in-xmlBuildQName-c.patch", "Fix-relaxng-is-parsed-to-an-infinite-attrs-next-loop.patch", - "Backport-CVE-2025-6170-Fix-potential-buffer-overflow-of-interactive-shell.patch" + "Backport-CVE-2025-6170-Fix-potential-buffer-overflow-of-interactive-shell.patch", + "Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch" ] for patch in patch_file: -- Gitee From 85f88131b3cc62b967f00f4c91de1e8a0eb217dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E8=B6=85?= Date: Tue, 5 Aug 2025 01:11:27 +0000 Subject: [PATCH 2/2] update Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 高超 --- ...-issues-in-xmlSchematronReportOutput.patch | 134 +++++++++--------- 1 file changed, 70 insertions(+), 64 deletions(-) diff --git a/Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch b/Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch index 772c9ac..7ba961f 100644 --- a/Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch +++ b/Fix-CVE-2025-49794-CVE-2025-49796-memory-safety-issues-in-xmlSchematronReportOutput.patch @@ -3,50 +3,52 @@ From: Nick Wellnhofer 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 | 49 ++++++++++++++------------ - test/schematron/cve-2025-49794.sct | 10 ++++++ - test/schematron/cve-2025-49794_0.xml | 6 ++++ + result/schematron/cve-2025-49794_0.err | 2 + + result/schematron/cve-2025-49796_0.err | 2 + + schematron.c | 55 ++++++++++++++------------ + 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, 58 insertions(+), 23 deletions(-) + 7 files changed, 61 insertions(+), 26 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 000000000..57752310e +index 0000000..53f131c --- /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 000000000..bf875ee0c +index 0000000..cd1730f --- /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 85b462827..0fd374617 100644 +index ddbb069..4611817 100644 --- a/schematron.c +++ b/schematron.c -@@ -1364,27 +1364,15 @@ exit: - * * +@@ -1239,27 +1239,15 @@ exit: + * * ************************************************************************/ -static xmlNodePtr @@ -67,7 +69,7 @@ index 85b462827..0fd374617 100644 - - if ((ret->type == XPATH_NODESET) && - (ret->nodesetval != NULL) && (ret->nodesetval->nodeNr > 0)) -- node = ret->nodesetval->nodeTab[0]; +- node = ret->nodesetval->nodeTab[0]; - - xmlXPathFreeObject(ret); - return(node); @@ -75,59 +77,62 @@ index 85b462827..0fd374617 100644 } /** -@@ -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; +@@ -1304,25 +1292,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"); + 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 (path != NULL) { +- node = xmlSchematronGetNode(ctxt, cur, path); +- if (node == NULL) +- node = cur; +- xmlFree(path); +- } ++ 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; +- 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; - } ++ /* TODO: handle other node types */ ++ default: ++ break; ++ } + -+ xmlXPathFreeObject(obj); - } else if (IS_SCHEMATRON(child, "value-of")) { - xmlChar *select; - xmlXPathObjectPtr eval; ++ 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 000000000..7fc9ee3db +index 0000000..7fc9ee3 --- /dev/null +++ b/test/schematron/cve-2025-49794.sct @@ -0,0 +1,10 @@ @@ -143,7 +148,7 @@ index 000000000..7fc9ee3db + diff --git a/test/schematron/cve-2025-49794_0.xml b/test/schematron/cve-2025-49794_0.xml new file mode 100644 -index 000000000..debc64ba6 +index 0000000..debc64b --- /dev/null +++ b/test/schematron/cve-2025-49794_0.xml @@ -0,0 +1,6 @@ @@ -155,7 +160,7 @@ index 000000000..debc64ba6 + diff --git a/test/schematron/cve-2025-49796.sct b/test/schematron/cve-2025-49796.sct new file mode 100644 -index 000000000..e9702d752 +index 0000000..e9702d7 --- /dev/null +++ b/test/schematron/cve-2025-49796.sct @@ -0,0 +1,9 @@ @@ -170,7 +175,7 @@ index 000000000..e9702d752 + diff --git a/test/schematron/cve-2025-49796_0.xml b/test/schematron/cve-2025-49796_0.xml new file mode 100644 -index 000000000..be33c4ec5 +index 0000000..be33c4e --- /dev/null +++ b/test/schematron/cve-2025-49796_0.xml @@ -0,0 +1,3 @@ @@ -178,4 +183,5 @@ index 000000000..be33c4ec5 + + -- -GitLab +2.34.1 + \ No newline at end of file -- Gitee