| Message ID | 20250711091527.15224-2-roland.kovacs@est.tech |
|---|---|
| State | Changes Requested |
| Delegated to: | Steve Sakoman |
| Headers | show |
| Series | [scarthgap] libxml2: fix CVE-2025-49795 | expand |
I'm getting ptest failures with this patch:
WARNING: core-image-ptest-libxml2-1.0-r0 do_testimage: There were
failing ptests.
Traceback (most recent call last):
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
line 35, in wrapped_f
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
line 35, in wrapped_f
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
line 35, in wrapped_f
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py",
line 27, in test_ptestrunner_expectfail
self.do_ptestrunner()
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py",
line 120, in do_ptestrunner
self.fail(failmsg)
AssertionError:
Failed ptests:
{'libxml2': ['runtest']}
I'm seeing it on both x86-64 and arm64:
https://autobuilder.yoctoproject.org/valkyrie/?#/builders/73/builds/1900/steps/12/logs/stdio
https://autobuilder.yoctoproject.org/valkyrie/?#/builders/61/builds/1897/steps/12/logs/stdio
I do not see the same issue with the walnascar version of the patch,
so perhaps that is a clue that will aid your debugging.
Steve
On Fri, Jul 11, 2025 at 2:15 AM roland.kovacs via
lists.openembedded.org <roland.kovacs=est.tech@lists.openembedded.org>
wrote:
>
> From: Roland Kovacs <roland.kovacs@est.tech>
>
> A NULL pointer dereference vulnerability was found in libxml2 when processing
> XPath XML expressions. This flaw allows an attacker to craft a malicious XML
> input to libxml2, leading to a denial of service.
>
> Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
> ---
> .../libxml/libxml2/CVE-2025-49795.patch | 238 ++++++++++++++++++
> meta/recipes-core/libxml/libxml2_2.12.10.bb | 1 +
> 2 files changed, 239 insertions(+)
> create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
>
> diff --git a/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
> new file mode 100644
> index 0000000000..fd784ea45b
> --- /dev/null
> +++ b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
> @@ -0,0 +1,238 @@
> +From 68ce19940f8e08c85f9c8ce65180cdb90bf4b0d2 Mon Sep 17 00:00:00 2001
> +From: Michael Mann <mmann78@netscape.net>
> +Date: Sat, 21 Jun 2025 12:11:30 -0400
> +Subject: [PATCH] Schematron: Fix null pointer dereference leading to DoS
> +
> +(CVE-2025-49795)
> +
> +Fixes #932
> +
> +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c24909ba2601848825b49a60f988222da3019667]
> +CVE: CVE-2025-49795
> +
> +(cherry picked from commit c24909ba2601848825b49a60f988222da3019667)
> +Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
> +---
> + result/schematron/zvon16_0.err | 3 +
> + runtest.c | 139 +++++++++++++++++++++++++++++++++
> + schematron.c | 5 ++
> + test/schematron/zvon16.sct | 7 ++
> + test/schematron/zvon16_0.xml | 5 ++
> + 5 files changed, 159 insertions(+)
> + create mode 100644 result/schematron/zvon16_0.err
> + create mode 100644 test/schematron/zvon16.sct
> + create mode 100644 test/schematron/zvon16_0.xml
> +
> +diff --git a/result/schematron/zvon16_0.err b/result/schematron/zvon16_0.err
> +new file mode 100644
> +index 00000000..3d052409
> +--- /dev/null
> ++++ b/result/schematron/zvon16_0.err
> +@@ -0,0 +1,3 @@
> ++XPath error : Unregistered function
> ++./test/schematron/zvon16_0.xml:2: element book: schematron error : /library/book line 2: Book
> ++./test/schematron/zvon16_0.xml fails to validate
> +diff --git a/runtest.c b/runtest.c
> +index c78eec81..736cae5e 100644
> +--- a/runtest.c
> ++++ b/runtest.c
> +@@ -52,6 +52,10 @@
> + #include <libxml/xmlschemastypes.h>
> + #endif
> +
> ++#ifdef LIBXML_SCHEMATRON_ENABLED
> ++#include <libxml/schematron.h>
> ++#endif
> ++
> + #ifdef LIBXML_PATTERN_ENABLED
> + #include <libxml/pattern.h>
> + #endif
> +@@ -3881,6 +3885,136 @@ rngStreamTest(const char *filename,
> +
> + #endif
> +
> ++/************************************************************************
> ++ * *
> ++ * Schematron tests *
> ++ * *
> ++ ************************************************************************/
> ++
> ++#ifdef LIBXML_SCHEMATRON_ENABLED
> ++static int
> ++schematronOneTest(const char *sch, const char *filename, int options,
> ++ xmlSchematronPtr schematron) {
> ++ xmlDocPtr doc;
> ++ xmlSchematronValidCtxtPtr ctxt;
> ++ int ret;
> ++
> ++ doc = xmlReadFile(filename, NULL, options);
> ++ if (doc == NULL) {
> ++ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
> ++ return(-1);
> ++ }
> ++
> ++ ctxt = xmlSchematronNewValidCtxt(schematron, XML_SCHEMATRON_OUT_ERROR);
> ++ xmlSchematronSetValidStructuredErrors(ctxt, testStructuredErrorHandler,
> ++ NULL);
> ++ ret = xmlSchematronValidateDoc(ctxt, doc);
> ++ if (ret == 0) {
> ++ testErrorHandler(NULL, "%s validates\n", filename);
> ++ } else if (ret > 0) {
> ++ testErrorHandler(NULL, "%s fails to validate\n", filename);
> ++ } else {
> ++ testErrorHandler(NULL, "%s validation generated an internal error\n",
> ++ filename);
> ++ }
> ++
> ++ xmlSchematronFreeValidCtxt(ctxt);
> ++ xmlFreeDoc(doc);
> ++ return(0);
> ++}
> ++
> ++/**
> ++ * schematronTest:
> ++ * @filename: the schemas file
> ++ * @result: the file with expected result
> ++ * @err: the file with error messages
> ++ *
> ++ * Returns 0 in case of success, an error code otherwise
> ++ */
> ++static int
> ++schematronTest(const char *filename,
> ++ const char *resul ATTRIBUTE_UNUSED,
> ++ const char *errr ATTRIBUTE_UNUSED,
> ++ int options) {
> ++ const char *base = baseFilename(filename);
> ++ const char *base2;
> ++ const char *instance;
> ++ xmlSchematronParserCtxtPtr pctxt;
> ++ xmlSchematronPtr schematron;
> ++ int res = 0, len, ret = 0;
> ++ int parseErrorsSize;
> ++ char pattern[500];
> ++ char prefix[500];
> ++ char err[500];
> ++ glob_t globbuf;
> ++ size_t i;
> ++ char count = 0;
> ++
> ++ /* Redirect XPath errors */
> ++ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
> ++
> ++ pctxt = xmlSchematronNewParserCtxt(filename);
> ++ schematron = xmlSchematronParse(pctxt);
> ++ xmlSchematronFreeParserCtxt(pctxt);
> ++ if (schematron == NULL)
> ++ testErrorHandler(NULL, "Schematron schema %s failed to compile\n",
> ++ filename);
> ++ parseErrorsSize = testErrorsSize;
> ++
> ++ /*
> ++ * most of the mess is about the output filenames generated by the Makefile
> ++ */
> ++ len = strlen(base);
> ++ if ((len > 499) || (len < 5)) {
> ++ ret = -1;
> ++ goto done;
> ++ }
> ++ len -= 4; /* remove trailing .sct */
> ++ memcpy(prefix, base, len);
> ++ prefix[len] = 0;
> ++
> ++ if (snprintf(pattern, 499, "./test/schematron/%s_?.xml", prefix) >= 499)
> ++ pattern[499] = 0;
> ++
> ++ globbuf.gl_offs = 0;
> ++ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
> ++ for (i = 0;i < globbuf.gl_pathc;i++) {
> ++ testErrorsSize = parseErrorsSize;
> ++ testErrors[parseErrorsSize] = 0;
> ++ instance = globbuf.gl_pathv[i];
> ++ base2 = baseFilename(instance);
> ++ len = strlen(base2);
> ++ if ((len > 6) && (base2[len - 6] == '_')) {
> ++ count = base2[len - 5];
> ++ res = snprintf(err, 499, "result/schematron/%s_%c.err",
> ++ prefix, count);
> ++ if (res >= 499)
> ++ err[499] = 0;
> ++ } else {
> ++ fprintf(stderr, "don't know how to process %s\n", instance);
> ++ continue;
> ++ }
> ++ if (schematron != NULL) {
> ++ nb_tests++;
> ++ res = schematronOneTest(filename, instance, options, schematron);
> ++ if (res != 0)
> ++ ret = res;
> ++ }
> ++ if (compareFileMem(err, testErrors, testErrorsSize)) {
> ++ fprintf(stderr, "Error for %s on %s failed\n", instance,
> ++ filename);
> ++ ret = 1;
> ++ }
> ++ }
> ++ globfree(&globbuf);
> ++
> ++done:
> ++ xmlSchematronFree(schematron);
> ++ xmlSetStructuredErrorFunc(NULL, NULL);
> ++ return(ret);
> ++}
> ++#endif /* LIBXML_SCHEMATRON_ENABLED */
> ++
> + #ifdef LIBXML_PATTERN_ENABLED
> + #ifdef LIBXML_READER_ENABLED
> + /************************************************************************
> +@@ -5117,6 +5251,11 @@ testDesc testDescriptions[] = {
> + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
> + XML_PARSE_DTDATTR | XML_PARSE_NOENT },
> + #endif
> ++#if defined(LIBXML_SCHEMATRON_ENABLED)
> ++ { "Schematron regression tests" ,
> ++ schematronTest, "./test/schematron/*.sct", NULL, NULL, NULL,
> ++ 0 },
> ++#endif
> + #endif
> + #ifdef LIBXML_PATTERN_ENABLED
> + #ifdef LIBXML_READER_ENABLED
> +diff --git a/schematron.c b/schematron.c
> +index 411a515c..c970d31f 100644
> +--- a/schematron.c
> ++++ b/schematron.c
> +@@ -1484,6 +1484,11 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
> + select = xmlGetNoNsProp(child, BAD_CAST "select");
> + comp = xmlXPathCtxtCompile(ctxt->xctxt, select);
> + eval = xmlXPathCompiledEval(comp, ctxt->xctxt);
> ++ if (eval == NULL) {
> ++ xmlXPathFreeCompExpr(comp);
> ++ xmlFree(select);
> ++ return ret;
> ++ }
> +
> + switch (eval->type) {
> + case XPATH_NODESET: {
> +diff --git a/test/schematron/zvon16.sct b/test/schematron/zvon16.sct
> +new file mode 100644
> +index 00000000..f03848aa
> +--- /dev/null
> ++++ b/test/schematron/zvon16.sct
> +@@ -0,0 +1,7 @@
> ++<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
> ++ <sch:pattern id="TestPattern">
> ++ <sch:rule context="book">
> ++ <sch:report test="not(@available)">Book <sch:value-of select="falae()"/> test</sch:report>
> ++ </sch:rule>
> ++ </sch:pattern>
> ++</sch:schema>
> +diff --git a/test/schematron/zvon16_0.xml b/test/schematron/zvon16_0.xml
> +new file mode 100644
> +index 00000000..551e2d65
> +--- /dev/null
> ++++ b/test/schematron/zvon16_0.xml
> +@@ -0,0 +1,5 @@
> ++<library>
> ++ <book title="Test Book" id="bk101">
> ++ <author>Test Author</author>
> ++ </book>
> ++</library>
> diff --git a/meta/recipes-core/libxml/libxml2_2.12.10.bb b/meta/recipes-core/libxml/libxml2_2.12.10.bb
> index 2eea65732b..ea40ca68ed 100644
> --- a/meta/recipes-core/libxml/libxml2_2.12.10.bb
> +++ b/meta/recipes-core/libxml/libxml2_2.12.10.bb
> @@ -20,6 +20,7 @@ SRC_URI += "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testt
> file://install-tests.patch \
> file://CVE-2025-32414.patch \
> file://CVE-2025-32415.patch \
> + file://CVE-2025-49795.patch \
> "
>
> SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995"
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#220138): https://lists.openembedded.org/g/openembedded-core/message/220138
> Mute This Topic: https://lists.openembedded.org/mt/114097487/3620601
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
On Wed, 2025-07-16 at 08:04 -0700, Steve Sakoman wrote: > I'm getting ptest failures with this patch: > > WARNING: core-image-ptest-libxml2-1.0-r0 do_testimage: There were > failing ptests. > Traceback (most recent call last): > File "/srv/pokybuild/yocto-worker/qemux86-64- > ptest/build/meta/lib/oeqa/core/decorator/__init__.py", > line 35, in wrapped_f > return func(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^ > File "/srv/pokybuild/yocto-worker/qemux86-64- > ptest/build/meta/lib/oeqa/core/decorator/__init__.py", > line 35, in wrapped_f > return func(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^ > File "/srv/pokybuild/yocto-worker/qemux86-64- > ptest/build/meta/lib/oeqa/core/decorator/__init__.py", > line 35, in wrapped_f > return func(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^ > File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py", > line 27, in test_ptestrunner_expectfail > self.do_ptestrunner() > File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py", > line 120, in do_ptestrunner > self.fail(failmsg) > AssertionError: > Failed ptests: > {'libxml2': ['runtest']} > > I'm seeing it on both x86-64 and arm64: > > https://autobuilder.yoctoproject.org/valkyrie/?#/builders/73/builds/1900/steps/12/logs/stdio > https://autobuilder.yoctoproject.org/valkyrie/?#/builders/61/builds/1897/steps/12/logs/stdio > > I do not see the same issue with the walnascar version of the patch, > so perhaps that is a clue that will aid your debugging. > > Steve > I'll look into it, and thanks for the pointers! Cheers, Roland > On Fri, Jul 11, 2025 at 2:15 AM roland.kovacs via > lists.openembedded.org <roland.kovacs=est.tech@lists.openembedded.org> > wrote: > > > > From: Roland Kovacs <roland.kovacs@est.tech> > > > > A NULL pointer dereference vulnerability was found in libxml2 when processing > > XPath XML expressions. This flaw allows an attacker to craft a malicious XML > > input to libxml2, leading to a denial of service. > > > > Signed-off-by: Roland Kovacs <roland.kovacs@est.tech> > > --- > > .../libxml/libxml2/CVE-2025-49795.patch | 238 ++++++++++++++++++ > > meta/recipes-core/libxml/libxml2_2.12.10.bb | 1 + > > 2 files changed, 239 insertions(+) > > create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch > > > > diff --git a/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch b/meta/recipes- > > core/libxml/libxml2/CVE-2025-49795.patch > > new file mode 100644 > > index 0000000000..fd784ea45b > > --- /dev/null > > +++ b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch > > @@ -0,0 +1,238 @@ > > +From 68ce19940f8e08c85f9c8ce65180cdb90bf4b0d2 Mon Sep 17 00:00:00 2001 > > +From: Michael Mann <mmann78@netscape.net> > > +Date: Sat, 21 Jun 2025 12:11:30 -0400 > > +Subject: [PATCH] Schematron: Fix null pointer dereference leading to DoS > > + > > +(CVE-2025-49795) > > + > > +Fixes #932 > > + > > +Upstream-Status: Backport > > [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c24909ba2601848825b49a60f988222da3019667] > > +CVE: CVE-2025-49795 > > + > > +(cherry picked from commit c24909ba2601848825b49a60f988222da3019667) > > +Signed-off-by: Roland Kovacs <roland.kovacs@est.tech> > > +--- > > + result/schematron/zvon16_0.err | 3 + > > + runtest.c | 139 +++++++++++++++++++++++++++++++++ > > + schematron.c | 5 ++ > > + test/schematron/zvon16.sct | 7 ++ > > + test/schematron/zvon16_0.xml | 5 ++ > > + 5 files changed, 159 insertions(+) > > + create mode 100644 result/schematron/zvon16_0.err > > + create mode 100644 test/schematron/zvon16.sct > > + create mode 100644 test/schematron/zvon16_0.xml > > + > > +diff --git a/result/schematron/zvon16_0.err b/result/schematron/zvon16_0.err > > +new file mode 100644 > > +index 00000000..3d052409 > > +--- /dev/null > > ++++ b/result/schematron/zvon16_0.err > > +@@ -0,0 +1,3 @@ > > ++XPath error : Unregistered function > > ++./test/schematron/zvon16_0.xml:2: element book: schematron error : /library/book line 2: Book > > ++./test/schematron/zvon16_0.xml fails to validate > > +diff --git a/runtest.c b/runtest.c > > +index c78eec81..736cae5e 100644 > > +--- a/runtest.c > > ++++ b/runtest.c > > +@@ -52,6 +52,10 @@ > > + #include <libxml/xmlschemastypes.h> > > + #endif > > + > > ++#ifdef LIBXML_SCHEMATRON_ENABLED > > ++#include <libxml/schematron.h> > > ++#endif > > ++ > > + #ifdef LIBXML_PATTERN_ENABLED > > + #include <libxml/pattern.h> > > + #endif > > +@@ -3881,6 +3885,136 @@ rngStreamTest(const char *filename, > > + > > + #endif > > + > > ++/************************************************************************ > > ++ * * > > ++ * Schematron tests * > > ++ * * > > ++ ************************************************************************/ > > ++ > > ++#ifdef LIBXML_SCHEMATRON_ENABLED > > ++static int > > ++schematronOneTest(const char *sch, const char *filename, int options, > > ++ xmlSchematronPtr schematron) { > > ++ xmlDocPtr doc; > > ++ xmlSchematronValidCtxtPtr ctxt; > > ++ int ret; > > ++ > > ++ doc = xmlReadFile(filename, NULL, options); > > ++ if (doc == NULL) { > > ++ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch); > > ++ return(-1); > > ++ } > > ++ > > ++ ctxt = xmlSchematronNewValidCtxt(schematron, XML_SCHEMATRON_OUT_ERROR); > > ++ xmlSchematronSetValidStructuredErrors(ctxt, testStructuredErrorHandler, > > ++ NULL); > > ++ ret = xmlSchematronValidateDoc(ctxt, doc); > > ++ if (ret == 0) { > > ++ testErrorHandler(NULL, "%s validates\n", filename); > > ++ } else if (ret > 0) { > > ++ testErrorHandler(NULL, "%s fails to validate\n", filename); > > ++ } else { > > ++ testErrorHandler(NULL, "%s validation generated an internal error\n", > > ++ filename); > > ++ } > > ++ > > ++ xmlSchematronFreeValidCtxt(ctxt); > > ++ xmlFreeDoc(doc); > > ++ return(0); > > ++} > > ++ > > ++/** > > ++ * schematronTest: > > ++ * @filename: the schemas file > > ++ * @result: the file with expected result > > ++ * @err: the file with error messages > > ++ * > > ++ * Returns 0 in case of success, an error code otherwise > > ++ */ > > ++static int > > ++schematronTest(const char *filename, > > ++ const char *resul ATTRIBUTE_UNUSED, > > ++ const char *errr ATTRIBUTE_UNUSED, > > ++ int options) { > > ++ const char *base = baseFilename(filename); > > ++ const char *base2; > > ++ const char *instance; > > ++ xmlSchematronParserCtxtPtr pctxt; > > ++ xmlSchematronPtr schematron; > > ++ int res = 0, len, ret = 0; > > ++ int parseErrorsSize; > > ++ char pattern[500]; > > ++ char prefix[500]; > > ++ char err[500]; > > ++ glob_t globbuf; > > ++ size_t i; > > ++ char count = 0; > > ++ > > ++ /* Redirect XPath errors */ > > ++ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); > > ++ > > ++ pctxt = xmlSchematronNewParserCtxt(filename); > > ++ schematron = xmlSchematronParse(pctxt); > > ++ xmlSchematronFreeParserCtxt(pctxt); > > ++ if (schematron == NULL) > > ++ testErrorHandler(NULL, "Schematron schema %s failed to compile\n", > > ++ filename); > > ++ parseErrorsSize = testErrorsSize; > > ++ > > ++ /* > > ++ * most of the mess is about the output filenames generated by the Makefile > > ++ */ > > ++ len = strlen(base); > > ++ if ((len > 499) || (len < 5)) { > > ++ ret = -1; > > ++ goto done; > > ++ } > > ++ len -= 4; /* remove trailing .sct */ > > ++ memcpy(prefix, base, len); > > ++ prefix[len] = 0; > > ++ > > ++ if (snprintf(pattern, 499, "./test/schematron/%s_?.xml", prefix) >= 499) > > ++ pattern[499] = 0; > > ++ > > ++ globbuf.gl_offs = 0; > > ++ glob(pattern, GLOB_DOOFFS, NULL, &globbuf); > > ++ for (i = 0;i < globbuf.gl_pathc;i++) { > > ++ testErrorsSize = parseErrorsSize; > > ++ testErrors[parseErrorsSize] = 0; > > ++ instance = globbuf.gl_pathv[i]; > > ++ base2 = baseFilename(instance); > > ++ len = strlen(base2); > > ++ if ((len > 6) && (base2[len - 6] == '_')) { > > ++ count = base2[len - 5]; > > ++ res = snprintf(err, 499, "result/schematron/%s_%c.err", > > ++ prefix, count); > > ++ if (res >= 499) > > ++ err[499] = 0; > > ++ } else { > > ++ fprintf(stderr, "don't know how to process %s\n", instance); > > ++ continue; > > ++ } > > ++ if (schematron != NULL) { > > ++ nb_tests++; > > ++ res = schematronOneTest(filename, instance, options, schematron); > > ++ if (res != 0) > > ++ ret = res; > > ++ } > > ++ if (compareFileMem(err, testErrors, testErrorsSize)) { > > ++ fprintf(stderr, "Error for %s on %s failed\n", instance, > > ++ filename); > > ++ ret = 1; > > ++ } > > ++ } > > ++ globfree(&globbuf); > > ++ > > ++done: > > ++ xmlSchematronFree(schematron); > > ++ xmlSetStructuredErrorFunc(NULL, NULL); > > ++ return(ret); > > ++} > > ++#endif /* LIBXML_SCHEMATRON_ENABLED */ > > ++ > > + #ifdef LIBXML_PATTERN_ENABLED > > + #ifdef LIBXML_READER_ENABLED > > + /************************************************************************ > > +@@ -5117,6 +5251,11 @@ testDesc testDescriptions[] = { > > + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL, > > + XML_PARSE_DTDATTR | XML_PARSE_NOENT }, > > + #endif > > ++#if defined(LIBXML_SCHEMATRON_ENABLED) > > ++ { "Schematron regression tests" , > > ++ schematronTest, "./test/schematron/*.sct", NULL, NULL, NULL, > > ++ 0 }, > > ++#endif > > + #endif > > + #ifdef LIBXML_PATTERN_ENABLED > > + #ifdef LIBXML_READER_ENABLED > > +diff --git a/schematron.c b/schematron.c > > +index 411a515c..c970d31f 100644 > > +--- a/schematron.c > > ++++ b/schematron.c > > +@@ -1484,6 +1484,11 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt, > > + select = xmlGetNoNsProp(child, BAD_CAST "select"); > > + comp = xmlXPathCtxtCompile(ctxt->xctxt, select); > > + eval = xmlXPathCompiledEval(comp, ctxt->xctxt); > > ++ if (eval == NULL) { > > ++ xmlXPathFreeCompExpr(comp); > > ++ xmlFree(select); > > ++ return ret; > > ++ } > > + > > + switch (eval->type) { > > + case XPATH_NODESET: { > > +diff --git a/test/schematron/zvon16.sct b/test/schematron/zvon16.sct > > +new file mode 100644 > > +index 00000000..f03848aa > > +--- /dev/null > > ++++ b/test/schematron/zvon16.sct > > +@@ -0,0 +1,7 @@ > > ++<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron"> > > ++ <sch:pattern id="TestPattern"> > > ++ <sch:rule context="book"> > > ++ <sch:report test="not(@available)">Book <sch:value-of select="falae()"/> > > test</sch:report> > > ++ </sch:rule> > > ++ </sch:pattern> > > ++</sch:schema> > > +diff --git a/test/schematron/zvon16_0.xml b/test/schematron/zvon16_0.xml > > +new file mode 100644 > > +index 00000000..551e2d65 > > +--- /dev/null > > ++++ b/test/schematron/zvon16_0.xml > > +@@ -0,0 +1,5 @@ > > ++<library> > > ++ <book title="Test Book" id="bk101"> > > ++ <author>Test Author</author> > > ++ </book> > > ++</library> > > diff --git a/meta/recipes-core/libxml/libxml2_2.12.10.bb b/meta/recipes- > > core/libxml/libxml2_2.12.10.bb > > index 2eea65732b..ea40ca68ed 100644 > > --- a/meta/recipes-core/libxml/libxml2_2.12.10.bb > > +++ b/meta/recipes-core/libxml/libxml2_2.12.10.bb > > @@ -20,6 +20,7 @@ SRC_URI += > > "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testt > > file://install-tests.patch \ > > file://CVE-2025-32414.patch \ > > file://CVE-2025-32415.patch \ > > + file://CVE-2025-49795.patch \ > > " > > > > SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995" > > > > -=-=-=-=-=-=-=-=-=-=-=- > > Links: You receive all messages sent to this group. > > View/Reply Online (#220138): https://lists.openembedded.org/g/openembedded-core/message/220138 > > Mute This Topic: https://lists.openembedded.org/mt/114097487/3620601 > > Group Owner: openembedded-core+owner@lists.openembedded.org > > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com] > > -=-=-=-=-=-=-=-=-=-=-=- > >
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch new file mode 100644 index 0000000000..fd784ea45b --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch @@ -0,0 +1,238 @@ +From 68ce19940f8e08c85f9c8ce65180cdb90bf4b0d2 Mon Sep 17 00:00:00 2001 +From: Michael Mann <mmann78@netscape.net> +Date: Sat, 21 Jun 2025 12:11:30 -0400 +Subject: [PATCH] Schematron: Fix null pointer dereference leading to DoS + +(CVE-2025-49795) + +Fixes #932 + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c24909ba2601848825b49a60f988222da3019667] +CVE: CVE-2025-49795 + +(cherry picked from commit c24909ba2601848825b49a60f988222da3019667) +Signed-off-by: Roland Kovacs <roland.kovacs@est.tech> +--- + result/schematron/zvon16_0.err | 3 + + runtest.c | 139 +++++++++++++++++++++++++++++++++ + schematron.c | 5 ++ + test/schematron/zvon16.sct | 7 ++ + test/schematron/zvon16_0.xml | 5 ++ + 5 files changed, 159 insertions(+) + create mode 100644 result/schematron/zvon16_0.err + create mode 100644 test/schematron/zvon16.sct + create mode 100644 test/schematron/zvon16_0.xml + +diff --git a/result/schematron/zvon16_0.err b/result/schematron/zvon16_0.err +new file mode 100644 +index 00000000..3d052409 +--- /dev/null ++++ b/result/schematron/zvon16_0.err +@@ -0,0 +1,3 @@ ++XPath error : Unregistered function ++./test/schematron/zvon16_0.xml:2: element book: schematron error : /library/book line 2: Book ++./test/schematron/zvon16_0.xml fails to validate +diff --git a/runtest.c b/runtest.c +index c78eec81..736cae5e 100644 +--- a/runtest.c ++++ b/runtest.c +@@ -52,6 +52,10 @@ + #include <libxml/xmlschemastypes.h> + #endif + ++#ifdef LIBXML_SCHEMATRON_ENABLED ++#include <libxml/schematron.h> ++#endif ++ + #ifdef LIBXML_PATTERN_ENABLED + #include <libxml/pattern.h> + #endif +@@ -3881,6 +3885,136 @@ rngStreamTest(const char *filename, + + #endif + ++/************************************************************************ ++ * * ++ * Schematron tests * ++ * * ++ ************************************************************************/ ++ ++#ifdef LIBXML_SCHEMATRON_ENABLED ++static int ++schematronOneTest(const char *sch, const char *filename, int options, ++ xmlSchematronPtr schematron) { ++ xmlDocPtr doc; ++ xmlSchematronValidCtxtPtr ctxt; ++ int ret; ++ ++ doc = xmlReadFile(filename, NULL, options); ++ if (doc == NULL) { ++ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch); ++ return(-1); ++ } ++ ++ ctxt = xmlSchematronNewValidCtxt(schematron, XML_SCHEMATRON_OUT_ERROR); ++ xmlSchematronSetValidStructuredErrors(ctxt, testStructuredErrorHandler, ++ NULL); ++ ret = xmlSchematronValidateDoc(ctxt, doc); ++ if (ret == 0) { ++ testErrorHandler(NULL, "%s validates\n", filename); ++ } else if (ret > 0) { ++ testErrorHandler(NULL, "%s fails to validate\n", filename); ++ } else { ++ testErrorHandler(NULL, "%s validation generated an internal error\n", ++ filename); ++ } ++ ++ xmlSchematronFreeValidCtxt(ctxt); ++ xmlFreeDoc(doc); ++ return(0); ++} ++ ++/** ++ * schematronTest: ++ * @filename: the schemas file ++ * @result: the file with expected result ++ * @err: the file with error messages ++ * ++ * Returns 0 in case of success, an error code otherwise ++ */ ++static int ++schematronTest(const char *filename, ++ const char *resul ATTRIBUTE_UNUSED, ++ const char *errr ATTRIBUTE_UNUSED, ++ int options) { ++ const char *base = baseFilename(filename); ++ const char *base2; ++ const char *instance; ++ xmlSchematronParserCtxtPtr pctxt; ++ xmlSchematronPtr schematron; ++ int res = 0, len, ret = 0; ++ int parseErrorsSize; ++ char pattern[500]; ++ char prefix[500]; ++ char err[500]; ++ glob_t globbuf; ++ size_t i; ++ char count = 0; ++ ++ /* Redirect XPath errors */ ++ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); ++ ++ pctxt = xmlSchematronNewParserCtxt(filename); ++ schematron = xmlSchematronParse(pctxt); ++ xmlSchematronFreeParserCtxt(pctxt); ++ if (schematron == NULL) ++ testErrorHandler(NULL, "Schematron schema %s failed to compile\n", ++ filename); ++ parseErrorsSize = testErrorsSize; ++ ++ /* ++ * most of the mess is about the output filenames generated by the Makefile ++ */ ++ len = strlen(base); ++ if ((len > 499) || (len < 5)) { ++ ret = -1; ++ goto done; ++ } ++ len -= 4; /* remove trailing .sct */ ++ memcpy(prefix, base, len); ++ prefix[len] = 0; ++ ++ if (snprintf(pattern, 499, "./test/schematron/%s_?.xml", prefix) >= 499) ++ pattern[499] = 0; ++ ++ globbuf.gl_offs = 0; ++ glob(pattern, GLOB_DOOFFS, NULL, &globbuf); ++ for (i = 0;i < globbuf.gl_pathc;i++) { ++ testErrorsSize = parseErrorsSize; ++ testErrors[parseErrorsSize] = 0; ++ instance = globbuf.gl_pathv[i]; ++ base2 = baseFilename(instance); ++ len = strlen(base2); ++ if ((len > 6) && (base2[len - 6] == '_')) { ++ count = base2[len - 5]; ++ res = snprintf(err, 499, "result/schematron/%s_%c.err", ++ prefix, count); ++ if (res >= 499) ++ err[499] = 0; ++ } else { ++ fprintf(stderr, "don't know how to process %s\n", instance); ++ continue; ++ } ++ if (schematron != NULL) { ++ nb_tests++; ++ res = schematronOneTest(filename, instance, options, schematron); ++ if (res != 0) ++ ret = res; ++ } ++ if (compareFileMem(err, testErrors, testErrorsSize)) { ++ fprintf(stderr, "Error for %s on %s failed\n", instance, ++ filename); ++ ret = 1; ++ } ++ } ++ globfree(&globbuf); ++ ++done: ++ xmlSchematronFree(schematron); ++ xmlSetStructuredErrorFunc(NULL, NULL); ++ return(ret); ++} ++#endif /* LIBXML_SCHEMATRON_ENABLED */ ++ + #ifdef LIBXML_PATTERN_ENABLED + #ifdef LIBXML_READER_ENABLED + /************************************************************************ +@@ -5117,6 +5251,11 @@ testDesc testDescriptions[] = { + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL, + XML_PARSE_DTDATTR | XML_PARSE_NOENT }, + #endif ++#if defined(LIBXML_SCHEMATRON_ENABLED) ++ { "Schematron regression tests" , ++ schematronTest, "./test/schematron/*.sct", NULL, NULL, NULL, ++ 0 }, ++#endif + #endif + #ifdef LIBXML_PATTERN_ENABLED + #ifdef LIBXML_READER_ENABLED +diff --git a/schematron.c b/schematron.c +index 411a515c..c970d31f 100644 +--- a/schematron.c ++++ b/schematron.c +@@ -1484,6 +1484,11 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt, + select = xmlGetNoNsProp(child, BAD_CAST "select"); + comp = xmlXPathCtxtCompile(ctxt->xctxt, select); + eval = xmlXPathCompiledEval(comp, ctxt->xctxt); ++ if (eval == NULL) { ++ xmlXPathFreeCompExpr(comp); ++ xmlFree(select); ++ return ret; ++ } + + switch (eval->type) { + case XPATH_NODESET: { +diff --git a/test/schematron/zvon16.sct b/test/schematron/zvon16.sct +new file mode 100644 +index 00000000..f03848aa +--- /dev/null ++++ b/test/schematron/zvon16.sct +@@ -0,0 +1,7 @@ ++<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron"> ++ <sch:pattern id="TestPattern"> ++ <sch:rule context="book"> ++ <sch:report test="not(@available)">Book <sch:value-of select="falae()"/> test</sch:report> ++ </sch:rule> ++ </sch:pattern> ++</sch:schema> +diff --git a/test/schematron/zvon16_0.xml b/test/schematron/zvon16_0.xml +new file mode 100644 +index 00000000..551e2d65 +--- /dev/null ++++ b/test/schematron/zvon16_0.xml +@@ -0,0 +1,5 @@ ++<library> ++ <book title="Test Book" id="bk101"> ++ <author>Test Author</author> ++ </book> ++</library> diff --git a/meta/recipes-core/libxml/libxml2_2.12.10.bb b/meta/recipes-core/libxml/libxml2_2.12.10.bb index 2eea65732b..ea40ca68ed 100644 --- a/meta/recipes-core/libxml/libxml2_2.12.10.bb +++ b/meta/recipes-core/libxml/libxml2_2.12.10.bb @@ -20,6 +20,7 @@ SRC_URI += "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testt file://install-tests.patch \ file://CVE-2025-32414.patch \ file://CVE-2025-32415.patch \ + file://CVE-2025-49795.patch \ " SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995"