* [PATCH] libxml2: Fix CVE-2026-0989
@ 2026-01-28 5:56 mingli.yu
2026-01-28 6:46 ` [OE-core] " Marko, Peter
0 siblings, 1 reply; 2+ messages in thread
From: mingli.yu @ 2026-01-28 5:56 UTC (permalink / raw)
To: openembedded-core
From: Mingli Yu <mingli.yu@windriver.com>
Backport a patch [1] to fix CVE-2026-0989.
[1] https://gitlab.gnome.org/GNOME/libxml2/-/commit/19549c61590c1873468c53e0026a2fbffae428ef
Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
---
.../libxml/libxml2/CVE-2026-0989.patch | 314 ++++++++++++++++++
meta/recipes-core/libxml/libxml2_2.15.1.bb | 1 +
2 files changed, 315 insertions(+)
create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2026-0989.patch
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2026-0989.patch b/meta/recipes-core/libxml/libxml2/CVE-2026-0989.patch
new file mode 100644
index 0000000000..800c8cf845
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2026-0989.patch
@@ -0,0 +1,314 @@
+From 19549c61590c1873468c53e0026a2fbffae428ef Mon Sep 17 00:00:00 2001
+From: Daniel Garcia Moreno <daniel.garcia@suse.com>
+Date: Fri, 10 Oct 2025 09:38:31 +0200
+Subject: [PATCH] Add RelaxNG include limit
+
+This patch adds a default xmlRelaxNGIncludeLimit of 1.000, and that
+limit can be modified at runtime with the env variable
+RNG_INCLUDE_LIMIT.
+
+Fix https://gitlab.gnome.org/GNOME/libxml2/-/issues/998
+
+CVE: CVE-2026-0989
+
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/19549c61590c1873468c53e0026a2fbffae428ef]
+
+Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
+---
+ include/libxml/relaxng.h | 4 ++
+ relaxng.c | 63 ++++++++++++++++++++--
+ runtest.c | 67 ++++++++++++++++++++++++
+ test/relaxng/include/include-limit.rng | 4 ++
+ test/relaxng/include/include-limit_1.rng | 4 ++
+ test/relaxng/include/include-limit_2.rng | 4 ++
+ test/relaxng/include/include-limit_3.rng | 8 +++
+ 7 files changed, 150 insertions(+), 4 deletions(-)
+ create mode 100644 test/relaxng/include/include-limit.rng
+ create mode 100644 test/relaxng/include/include-limit_1.rng
+ create mode 100644 test/relaxng/include/include-limit_2.rng
+ create mode 100644 test/relaxng/include/include-limit_3.rng
+
+diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h
+index eafc6604..099dacd8 100644
+--- a/include/libxml/relaxng.h
++++ b/include/libxml/relaxng.h
+@@ -136,6 +136,10 @@ XMLPUBFUN int
+ xmlRelaxParserSetFlag (xmlRelaxNGParserCtxt *ctxt,
+ int flag);
+
++XMLPUBFUN int
++ xmlRelaxParserSetIncLImit (xmlRelaxNGParserCtxt *ctxt,
++ int limit);
++
+ XMLPUBFUN void
+ xmlRelaxNGFreeParserCtxt (xmlRelaxNGParserCtxt *ctxt);
+ XMLPUBFUN void
+diff --git a/relaxng.c b/relaxng.c
+index 1d74ba9f..c0e94a3c 100644
+--- a/relaxng.c
++++ b/relaxng.c
+@@ -18,6 +18,8 @@
+
+ #ifdef LIBXML_RELAXNG_ENABLED
+
++#include <errno.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <stddef.h>
+@@ -44,6 +46,12 @@
+ static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
+ "http://relaxng.org/ns/structure/1.0";
+
++/*
++ * Default include limit, this can be override with RNG_INCLUDE_LIMIT
++ * env variable
++ */
++static const int _xmlRelaxNGIncludeLimit = 1000;
++
+ #define IS_RELAXNG(node, typ) \
+ ((node != NULL) && (node->ns != NULL) && \
+ (node->type == XML_ELEMENT_NODE) && \
+@@ -218,6 +226,7 @@ struct _xmlRelaxNGParserCtxt {
+ int incNr; /* Depth of the include parsing stack */
+ int incMax; /* Max depth of the parsing stack */
+ xmlRelaxNGIncludePtr *incTab; /* array of incs */
++ int incLimit; /* Include limit, to avoid stack-overflow on parse */
+
+ int idref; /* requires idref checking */
+
+@@ -1342,6 +1351,23 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxt *ctxt, int flags)
+ return(0);
+ }
+
++/**
++ * Semi private function used to set the include recursion limit to a
++ * parser context. Set to 0 to use the default value.
++ *
++ * @param ctxt a RelaxNG parser context
++ * @param limit the new include depth limit
++ * @returns 0 if success and -1 in case of error
++ */
++int
++xmlRelaxParserSetIncLImit(xmlRelaxNGParserCtxt *ctxt, int limit)
++{
++ if (ctxt == NULL) return(-1);
++ if (limit < 0) return(-1);
++ ctxt->incLimit = limit;
++ return(0);
++}
++
+ /************************************************************************
+ * *
+ * Document functions *
+@@ -1397,7 +1423,7 @@ xmlRelaxReadMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *buf, int size) {
+ *
+ * @param ctxt the parser context
+ * @param value the element doc
+- * @returns 0 in case of error, the index in the stack otherwise
++ * @returns -1 in case of error, the index in the stack otherwise
+ */
+ static int
+ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
+@@ -1411,9 +1437,15 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
+ sizeof(ctxt->incTab[0]));
+ if (ctxt->incTab == NULL) {
+ xmlRngPErrMemory(ctxt);
+- return (0);
++ return (-1);
+ }
+ }
++ if (ctxt->incNr >= ctxt->incLimit) {
++ xmlRngPErr(ctxt, (xmlNodePtr)value->doc, XML_RNGP_PARSE_ERROR,
++ "xmlRelaxNG: inclusion recursion limit reached\n", NULL, NULL);
++ return(-1);
++ }
++
+ if (ctxt->incNr >= ctxt->incMax) {
+ ctxt->incMax *= 2;
+ ctxt->incTab =
+@@ -1422,7 +1454,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
+ sizeof(ctxt->incTab[0]));
+ if (ctxt->incTab == NULL) {
+ xmlRngPErrMemory(ctxt);
+- return (0);
++ return (-1);
+ }
+ }
+ ctxt->incTab[ctxt->incNr] = value;
+@@ -1586,7 +1618,9 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
+ /*
+ * push it on the stack
+ */
+- xmlRelaxNGIncludePush(ctxt, ret);
++ if (xmlRelaxNGIncludePush(ctxt, ret) < 0) {
++ return (NULL);
++ }
+
+ /*
+ * Some preprocessing of the document content, this include recursing
+@@ -7261,11 +7295,32 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxt *ctxt)
+ xmlDocPtr doc;
+ xmlNodePtr root;
+
++ const char *include_limit_env = getenv("RNG_INCLUDE_LIMIT");
++
+ xmlRelaxNGInitTypes();
+
+ if (ctxt == NULL)
+ return (NULL);
+
++ if (ctxt->incLimit == 0) {
++ ctxt->incLimit = _xmlRelaxNGIncludeLimit;
++ if (include_limit_env != NULL) {
++ char *strEnd;
++ unsigned long val = 0;
++ errno = 0;
++ val = strtoul(include_limit_env, &strEnd, 10);
++ if (errno != 0 || *strEnd != 0 || val > INT_MAX) {
++ xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
++ "xmlRelaxNGParse: invalid RNG_INCLUDE_LIMIT %s\n",
++ (const xmlChar*)include_limit_env,
++ NULL);
++ return(NULL);
++ }
++ if (val)
++ ctxt->incLimit = val;
++ }
++ }
++
+ /*
+ * First step is to parse the input document into an DOM/Infoset
+ */
+diff --git a/runtest.c b/runtest.c
+index 49519aef..45109f0a 100644
+--- a/runtest.c
++++ b/runtest.c
+@@ -3741,6 +3741,70 @@ rngTest(const char *filename,
+ return(ret);
+ }
+
++/**
++ * Parse an RNG schemas with a custom RNG_INCLUDE_LIMIT
++ *
++ * @param filename the schemas file
++ * @param result the file with expected result
++ * @param err the file with error messages
++ * @returns 0 in case of success, an error code otherwise
++ */
++static int
++rngIncludeTest(const char *filename,
++ const char *resul ATTRIBUTE_UNUSED,
++ const char *errr ATTRIBUTE_UNUSED,
++ int options ATTRIBUTE_UNUSED) {
++ xmlRelaxNGParserCtxtPtr ctxt;
++ xmlRelaxNGPtr schemas;
++ int ret = 0;
++
++ /* first compile the schemas if possible */
++ ctxt = xmlRelaxNGNewParserCtxt(filename);
++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler,
++ NULL);
++
++ /* Should work */
++ schemas = xmlRelaxNGParse(ctxt);
++ if (schemas == NULL) {
++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
++ filename);
++ ret = -1;
++ goto done;
++ }
++ xmlRelaxNGFree(schemas);
++ xmlRelaxNGFreeParserCtxt(ctxt);
++
++ ctxt = xmlRelaxNGNewParserCtxt(filename);
++ /* Should fail */
++ xmlRelaxParserSetIncLImit(ctxt, 2);
++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler,
++ NULL);
++ schemas = xmlRelaxNGParse(ctxt);
++ if (schemas != NULL) {
++ ret = -1;
++ xmlRelaxNGFree(schemas);
++ }
++ xmlRelaxNGFreeParserCtxt(ctxt);
++
++ ctxt = xmlRelaxNGNewParserCtxt(filename);
++ /* Should work */
++ xmlRelaxParserSetIncLImit(ctxt, 3);
++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler,
++ NULL);
++ schemas = xmlRelaxNGParse(ctxt);
++ if (schemas == NULL) {
++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
++ filename);
++ ret = -1;
++ goto done;
++ }
++ xmlRelaxNGFree(schemas);
++
++done:
++ xmlRelaxNGFreeParserCtxt(ctxt);
++ return(ret);
++}
++
+ #ifdef LIBXML_READER_ENABLED
+ /**
+ * Parse a set of files with streaming, applying an RNG schemas
+@@ -5202,6 +5266,9 @@ testDesc testDescriptions[] = {
+ { "Relax-NG regression tests" ,
+ rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+ XML_PARSE_DTDATTR | XML_PARSE_NOENT },
++ { "Relax-NG include limit tests" ,
++ rngIncludeTest, "./test/relaxng/include/include-limit.rng", NULL, NULL, NULL,
++ 0 },
+ #ifdef LIBXML_READER_ENABLED
+ { "Relax-NG streaming regression tests" ,
+ rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+diff --git a/test/relaxng/include/include-limit.rng b/test/relaxng/include/include-limit.rng
+new file mode 100644
+index 00000000..51f03942
+--- /dev/null
++++ b/test/relaxng/include/include-limit.rng
+@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++ <include href="include-limit_1.rng"/>
++</grammar>
+diff --git a/test/relaxng/include/include-limit_1.rng b/test/relaxng/include/include-limit_1.rng
+new file mode 100644
+index 00000000..4672da38
+--- /dev/null
++++ b/test/relaxng/include/include-limit_1.rng
+@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++ <include href="include-limit_2.rng"/>
++</grammar>
+diff --git a/test/relaxng/include/include-limit_2.rng b/test/relaxng/include/include-limit_2.rng
+new file mode 100644
+index 00000000..b35ecaa8
+--- /dev/null
++++ b/test/relaxng/include/include-limit_2.rng
+@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++ <include href="include-limit_3.rng"/>
++</grammar>
+diff --git a/test/relaxng/include/include-limit_3.rng b/test/relaxng/include/include-limit_3.rng
+new file mode 100644
+index 00000000..86213c62
+--- /dev/null
++++ b/test/relaxng/include/include-limit_3.rng
+@@ -0,0 +1,8 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
++ <start>
++ <element name="root">
++ <empty/>
++ </element>
++ </start>
++</grammar>
+--
+2.34.1
+
diff --git a/meta/recipes-core/libxml/libxml2_2.15.1.bb b/meta/recipes-core/libxml/libxml2_2.15.1.bb
index a64ed8098e..26fe27e933 100644
--- a/meta/recipes-core/libxml/libxml2_2.15.1.bb
+++ b/meta/recipes-core/libxml/libxml2_2.15.1.bb
@@ -17,6 +17,7 @@ inherit gnomebase
SRC_URI += "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testtar \
file://CVE-2026-0990.patch \
file://CVE-2026-0992.patch \
+ file://CVE-2026-0989.patch \
file://run-ptest \
file://install-tests.patch \
file://0001-Revert-cmake-Fix-installation-directories-in-libxml2.patch \
--
2.34.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* RE: [OE-core] [PATCH] libxml2: Fix CVE-2026-0989
2026-01-28 5:56 [PATCH] libxml2: Fix CVE-2026-0989 mingli.yu
@ 2026-01-28 6:46 ` Marko, Peter
0 siblings, 0 replies; 2+ messages in thread
From: Marko, Peter @ 2026-01-28 6:46 UTC (permalink / raw)
To: mingli.yu@eng.windriver.com,
openembedded-core@lists.openembedded.org
Patch for this CVE has been already submitted under https://lists.openembedded.org/g/openembedded-core/message/229940
Peter
> -----Original Message-----
> From: openembedded-core@lists.openembedded.org <openembedded-
> core@lists.openembedded.org> On Behalf Of Yu, Mingli via
> lists.openembedded.org
> Sent: Wednesday, January 28, 2026 6:56
> To: openembedded-core@lists.openembedded.org
> Subject: [OE-core] [PATCH] libxml2: Fix CVE-2026-0989
>
> From: Mingli Yu <mingli.yu@windriver.com>
>
> Backport a patch [1] to fix CVE-2026-0989.
>
> [1] https://gitlab.gnome.org/GNOME/libxml2/-
> /commit/19549c61590c1873468c53e0026a2fbffae428ef
>
> Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
> ---
> .../libxml/libxml2/CVE-2026-0989.patch | 314 ++++++++++++++++++
> meta/recipes-core/libxml/libxml2_2.15.1.bb | 1 +
> 2 files changed, 315 insertions(+)
> create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2026-0989.patch
>
> diff --git a/meta/recipes-core/libxml/libxml2/CVE-2026-0989.patch b/meta/recipes-
> core/libxml/libxml2/CVE-2026-0989.patch
> new file mode 100644
> index 0000000000..800c8cf845
> --- /dev/null
> +++ b/meta/recipes-core/libxml/libxml2/CVE-2026-0989.patch
> @@ -0,0 +1,314 @@
> +From 19549c61590c1873468c53e0026a2fbffae428ef Mon Sep 17 00:00:00 2001
> +From: Daniel Garcia Moreno <daniel.garcia@suse.com>
> +Date: Fri, 10 Oct 2025 09:38:31 +0200
> +Subject: [PATCH] Add RelaxNG include limit
> +
> +This patch adds a default xmlRelaxNGIncludeLimit of 1.000, and that
> +limit can be modified at runtime with the env variable
> +RNG_INCLUDE_LIMIT.
> +
> +Fix https://gitlab.gnome.org/GNOME/libxml2/-/issues/998
> +
> +CVE: CVE-2026-0989
> +
> +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-
> /commit/19549c61590c1873468c53e0026a2fbffae428ef]
> +
> +Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
> +---
> + include/libxml/relaxng.h | 4 ++
> + relaxng.c | 63 ++++++++++++++++++++--
> + runtest.c | 67 ++++++++++++++++++++++++
> + test/relaxng/include/include-limit.rng | 4 ++
> + test/relaxng/include/include-limit_1.rng | 4 ++
> + test/relaxng/include/include-limit_2.rng | 4 ++
> + test/relaxng/include/include-limit_3.rng | 8 +++
> + 7 files changed, 150 insertions(+), 4 deletions(-)
> + create mode 100644 test/relaxng/include/include-limit.rng
> + create mode 100644 test/relaxng/include/include-limit_1.rng
> + create mode 100644 test/relaxng/include/include-limit_2.rng
> + create mode 100644 test/relaxng/include/include-limit_3.rng
> +
> +diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h
> +index eafc6604..099dacd8 100644
> +--- a/include/libxml/relaxng.h
> ++++ b/include/libxml/relaxng.h
> +@@ -136,6 +136,10 @@ XMLPUBFUN int
> + xmlRelaxParserSetFlag (xmlRelaxNGParserCtxt *ctxt,
> + int flag);
> +
> ++XMLPUBFUN int
> ++ xmlRelaxParserSetIncLImit (xmlRelaxNGParserCtxt *ctxt,
> ++ int limit);
> ++
> + XMLPUBFUN void
> + xmlRelaxNGFreeParserCtxt (xmlRelaxNGParserCtxt *ctxt);
> + XMLPUBFUN void
> +diff --git a/relaxng.c b/relaxng.c
> +index 1d74ba9f..c0e94a3c 100644
> +--- a/relaxng.c
> ++++ b/relaxng.c
> +@@ -18,6 +18,8 @@
> +
> + #ifdef LIBXML_RELAXNG_ENABLED
> +
> ++#include <errno.h>
> ++#include <stdlib.h>
> + #include <string.h>
> + #include <stdio.h>
> + #include <stddef.h>
> +@@ -44,6 +46,12 @@
> + static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
> + "http://relaxng.org/ns/structure/1.0";
> +
> ++/*
> ++ * Default include limit, this can be override with RNG_INCLUDE_LIMIT
> ++ * env variable
> ++ */
> ++static const int _xmlRelaxNGIncludeLimit = 1000;
> ++
> + #define IS_RELAXNG(node, typ) \
> + ((node != NULL) && (node->ns != NULL) && \
> + (node->type == XML_ELEMENT_NODE) &&
> \
> +@@ -218,6 +226,7 @@ struct _xmlRelaxNGParserCtxt {
> + int incNr; /* Depth of the include parsing stack */
> + int incMax; /* Max depth of the parsing stack */
> + xmlRelaxNGIncludePtr *incTab; /* array of incs */
> ++ int incLimit; /* Include limit, to avoid stack-overflow on parse */
> +
> + int idref; /* requires idref checking */
> +
> +@@ -1342,6 +1351,23 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxt *ctxt,
> int flags)
> + return(0);
> + }
> +
> ++/**
> ++ * Semi private function used to set the include recursion limit to a
> ++ * parser context. Set to 0 to use the default value.
> ++ *
> ++ * @param ctxt a RelaxNG parser context
> ++ * @param limit the new include depth limit
> ++ * @returns 0 if success and -1 in case of error
> ++ */
> ++int
> ++xmlRelaxParserSetIncLImit(xmlRelaxNGParserCtxt *ctxt, int limit)
> ++{
> ++ if (ctxt == NULL) return(-1);
> ++ if (limit < 0) return(-1);
> ++ ctxt->incLimit = limit;
> ++ return(0);
> ++}
> ++
> + /************************************************************************
> + * *
> + * Document functions *
> +@@ -1397,7 +1423,7 @@ xmlRelaxReadMemory(xmlRelaxNGParserCtxtPtr ctxt,
> const char *buf, int size) {
> + *
> + * @param ctxt the parser context
> + * @param value the element doc
> +- * @returns 0 in case of error, the index in the stack otherwise
> ++ * @returns -1 in case of error, the index in the stack otherwise
> + */
> + static int
> + xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
> +@@ -1411,9 +1437,15 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr
> ctxt,
> + sizeof(ctxt->incTab[0]));
> + if (ctxt->incTab == NULL) {
> + xmlRngPErrMemory(ctxt);
> +- return (0);
> ++ return (-1);
> + }
> + }
> ++ if (ctxt->incNr >= ctxt->incLimit) {
> ++ xmlRngPErr(ctxt, (xmlNodePtr)value->doc, XML_RNGP_PARSE_ERROR,
> ++ "xmlRelaxNG: inclusion recursion limit reached\n", NULL, NULL);
> ++ return(-1);
> ++ }
> ++
> + if (ctxt->incNr >= ctxt->incMax) {
> + ctxt->incMax *= 2;
> + ctxt->incTab =
> +@@ -1422,7 +1454,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr
> ctxt,
> + sizeof(ctxt->incTab[0]));
> + if (ctxt->incTab == NULL) {
> + xmlRngPErrMemory(ctxt);
> +- return (0);
> ++ return (-1);
> + }
> + }
> + ctxt->incTab[ctxt->incNr] = value;
> +@@ -1586,7 +1618,9 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr
> ctxt, const xmlChar * URL,
> + /*
> + * push it on the stack
> + */
> +- xmlRelaxNGIncludePush(ctxt, ret);
> ++ if (xmlRelaxNGIncludePush(ctxt, ret) < 0) {
> ++ return (NULL);
> ++ }
> +
> + /*
> + * Some preprocessing of the document content, this include recursing
> +@@ -7261,11 +7295,32 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxt *ctxt)
> + xmlDocPtr doc;
> + xmlNodePtr root;
> +
> ++ const char *include_limit_env = getenv("RNG_INCLUDE_LIMIT");
> ++
> + xmlRelaxNGInitTypes();
> +
> + if (ctxt == NULL)
> + return (NULL);
> +
> ++ if (ctxt->incLimit == 0) {
> ++ ctxt->incLimit = _xmlRelaxNGIncludeLimit;
> ++ if (include_limit_env != NULL) {
> ++ char *strEnd;
> ++ unsigned long val = 0;
> ++ errno = 0;
> ++ val = strtoul(include_limit_env, &strEnd, 10);
> ++ if (errno != 0 || *strEnd != 0 || val > INT_MAX) {
> ++ xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
> ++ "xmlRelaxNGParse: invalid RNG_INCLUDE_LIMIT %s\n",
> ++ (const xmlChar*)include_limit_env,
> ++ NULL);
> ++ return(NULL);
> ++ }
> ++ if (val)
> ++ ctxt->incLimit = val;
> ++ }
> ++ }
> ++
> + /*
> + * First step is to parse the input document into an DOM/Infoset
> + */
> +diff --git a/runtest.c b/runtest.c
> +index 49519aef..45109f0a 100644
> +--- a/runtest.c
> ++++ b/runtest.c
> +@@ -3741,6 +3741,70 @@ rngTest(const char *filename,
> + return(ret);
> + }
> +
> ++/**
> ++ * Parse an RNG schemas with a custom RNG_INCLUDE_LIMIT
> ++ *
> ++ * @param filename the schemas file
> ++ * @param result the file with expected result
> ++ * @param err the file with error messages
> ++ * @returns 0 in case of success, an error code otherwise
> ++ */
> ++static int
> ++rngIncludeTest(const char *filename,
> ++ const char *resul ATTRIBUTE_UNUSED,
> ++ const char *errr ATTRIBUTE_UNUSED,
> ++ int options ATTRIBUTE_UNUSED) {
> ++ xmlRelaxNGParserCtxtPtr ctxt;
> ++ xmlRelaxNGPtr schemas;
> ++ int ret = 0;
> ++
> ++ /* first compile the schemas if possible */
> ++ ctxt = xmlRelaxNGNewParserCtxt(filename);
> ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler,
> ++ NULL);
> ++
> ++ /* Should work */
> ++ schemas = xmlRelaxNGParse(ctxt);
> ++ if (schemas == NULL) {
> ++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
> ++ filename);
> ++ ret = -1;
> ++ goto done;
> ++ }
> ++ xmlRelaxNGFree(schemas);
> ++ xmlRelaxNGFreeParserCtxt(ctxt);
> ++
> ++ ctxt = xmlRelaxNGNewParserCtxt(filename);
> ++ /* Should fail */
> ++ xmlRelaxParserSetIncLImit(ctxt, 2);
> ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler,
> ++ NULL);
> ++ schemas = xmlRelaxNGParse(ctxt);
> ++ if (schemas != NULL) {
> ++ ret = -1;
> ++ xmlRelaxNGFree(schemas);
> ++ }
> ++ xmlRelaxNGFreeParserCtxt(ctxt);
> ++
> ++ ctxt = xmlRelaxNGNewParserCtxt(filename);
> ++ /* Should work */
> ++ xmlRelaxParserSetIncLImit(ctxt, 3);
> ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler,
> ++ NULL);
> ++ schemas = xmlRelaxNGParse(ctxt);
> ++ if (schemas == NULL) {
> ++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
> ++ filename);
> ++ ret = -1;
> ++ goto done;
> ++ }
> ++ xmlRelaxNGFree(schemas);
> ++
> ++done:
> ++ xmlRelaxNGFreeParserCtxt(ctxt);
> ++ return(ret);
> ++}
> ++
> + #ifdef LIBXML_READER_ENABLED
> + /**
> + * Parse a set of files with streaming, applying an RNG schemas
> +@@ -5202,6 +5266,9 @@ testDesc testDescriptions[] = {
> + { "Relax-NG regression tests" ,
> + rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
> + XML_PARSE_DTDATTR | XML_PARSE_NOENT },
> ++ { "Relax-NG include limit tests" ,
> ++ rngIncludeTest, "./test/relaxng/include/include-limit.rng", NULL, NULL, NULL,
> ++ 0 },
> + #ifdef LIBXML_READER_ENABLED
> + { "Relax-NG streaming regression tests" ,
> + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
> +diff --git a/test/relaxng/include/include-limit.rng b/test/relaxng/include/include-
> limit.rng
> +new file mode 100644
> +index 00000000..51f03942
> +--- /dev/null
> ++++ b/test/relaxng/include/include-limit.rng
> +@@ -0,0 +1,4 @@
> ++<?xml version="1.0" encoding="UTF-8"?>
> ++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
> ++ <include href="include-limit_1.rng"/>
> ++</grammar>
> +diff --git a/test/relaxng/include/include-limit_1.rng b/test/relaxng/include/include-
> limit_1.rng
> +new file mode 100644
> +index 00000000..4672da38
> +--- /dev/null
> ++++ b/test/relaxng/include/include-limit_1.rng
> +@@ -0,0 +1,4 @@
> ++<?xml version="1.0" encoding="UTF-8"?>
> ++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
> ++ <include href="include-limit_2.rng"/>
> ++</grammar>
> +diff --git a/test/relaxng/include/include-limit_2.rng b/test/relaxng/include/include-
> limit_2.rng
> +new file mode 100644
> +index 00000000..b35ecaa8
> +--- /dev/null
> ++++ b/test/relaxng/include/include-limit_2.rng
> +@@ -0,0 +1,4 @@
> ++<?xml version="1.0" encoding="UTF-8"?>
> ++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
> ++ <include href="include-limit_3.rng"/>
> ++</grammar>
> +diff --git a/test/relaxng/include/include-limit_3.rng b/test/relaxng/include/include-
> limit_3.rng
> +new file mode 100644
> +index 00000000..86213c62
> +--- /dev/null
> ++++ b/test/relaxng/include/include-limit_3.rng
> +@@ -0,0 +1,8 @@
> ++<?xml version="1.0" encoding="UTF-8"?>
> ++<grammar xmlns="http://relaxng.org/ns/structure/1.0">
> ++ <start>
> ++ <element name="root">
> ++ <empty/>
> ++ </element>
> ++ </start>
> ++</grammar>
> +--
> +2.34.1
> +
> diff --git a/meta/recipes-core/libxml/libxml2_2.15.1.bb b/meta/recipes-
> core/libxml/libxml2_2.15.1.bb
> index a64ed8098e..26fe27e933 100644
> --- a/meta/recipes-core/libxml/libxml2_2.15.1.bb
> +++ b/meta/recipes-core/libxml/libxml2_2.15.1.bb
> @@ -17,6 +17,7 @@ inherit gnomebase
> SRC_URI +=
> "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testtar \
> file://CVE-2026-0990.patch \
> file://CVE-2026-0992.patch \
> + file://CVE-2026-0989.patch \
> file://run-ptest \
> file://install-tests.patch \
> file://0001-Revert-cmake-Fix-installation-directories-in-libxml2.patch \
> --
> 2.34.1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-01-28 6:46 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-28 5:56 [PATCH] libxml2: Fix CVE-2026-0989 mingli.yu
2026-01-28 6:46 ` [OE-core] " Marko, Peter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox