mirror of
https://git.yoctoproject.org/poky
synced 2026-05-09 17:39:31 +00:00
libxml2: add follow-up patch for CVE-2026-0992
References: * https://gitlab.gnome.org/GNOME/libxml2/-/issues/1019 * https://gitlab.gnome.org/GNOME/libxml2/-/merge_requests/377 (From OE-Core rev: 2c8e455148e12e097ff757bcf0a57d7d5bd77c30) Signed-off-by: Peter Marko <peter.marko@siemens.com> Signed-off-by: Yoann Congal <yoann.congal@smile.fr> Signed-off-by: Paul Barker <paul@pbarker.dev> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
bd21ac68d0
commit
8d61eb390a
@@ -0,0 +1,323 @@
|
|||||||
|
From f8399e62a31095bf1ced01827c33f9b29494046f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Garcia Moreno <daniel.garcia@suse.com>
|
||||||
|
Date: Fri, 19 Dec 2025 12:27:54 +0100
|
||||||
|
Subject: [PATCH] testcatalog: Add new tests for catalog.c
|
||||||
|
|
||||||
|
Adds a new test program to run specific tests related to catalog
|
||||||
|
parsing.
|
||||||
|
|
||||||
|
This initial version includes a couple of tests, the first one to check
|
||||||
|
the infinite recursion detection related to:
|
||||||
|
https://gitlab.gnome.org/GNOME/libxml2/-/issues/1018.
|
||||||
|
|
||||||
|
The second one tests the nextCatalog element repeated parsing, related
|
||||||
|
to:
|
||||||
|
https://gitlab.gnome.org/GNOME/libxml2/-/issues/1019
|
||||||
|
https://gitlab.gnome.org/GNOME/libxml2/-/issues/1040
|
||||||
|
|
||||||
|
CVE: CVE-2026-0992
|
||||||
|
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/f8399e62a31095bf1ced01827c33f9b29494046f]
|
||||||
|
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||||
|
---
|
||||||
|
CMakeLists.txt | 2 +
|
||||||
|
Makefile.am | 6 ++
|
||||||
|
catalog.c | 63 +++++++++++-----
|
||||||
|
include/libxml/catalog.h | 2 +
|
||||||
|
test/catalogs/catalog-recursive.xml | 3 +
|
||||||
|
test/catalogs/repeated-next-catalog.xml | 10 +++
|
||||||
|
testcatalog.c | 96 +++++++++++++++++++++++++
|
||||||
|
7 files changed, 163 insertions(+), 19 deletions(-)
|
||||||
|
create mode 100644 test/catalogs/catalog-recursive.xml
|
||||||
|
create mode 100644 test/catalogs/repeated-next-catalog.xml
|
||||||
|
create mode 100644 testcatalog.c
|
||||||
|
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 163661f8..7d5702df 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -517,6 +517,7 @@ if(LIBXML2_WITH_TESTS)
|
||||||
|
runxmlconf
|
||||||
|
runsuite
|
||||||
|
testapi
|
||||||
|
+ testcatalog
|
||||||
|
testchar
|
||||||
|
testdict
|
||||||
|
testModule
|
||||||
|
@@ -543,6 +544,7 @@ if(LIBXML2_WITH_TESTS)
|
||||||
|
if(NOT WIN32)
|
||||||
|
add_test(NAME testapi COMMAND testapi)
|
||||||
|
endif()
|
||||||
|
+ add_test(NAME testcatalog COMMAND testcatalog)
|
||||||
|
add_test(NAME testchar COMMAND testchar)
|
||||||
|
add_test(NAME testdict COMMAND testdict)
|
||||||
|
add_test(NAME testparser COMMAND testparser)
|
||||||
|
diff --git a/Makefile.am b/Makefile.am
|
||||||
|
index c51dfd8e..c794eac8 100644
|
||||||
|
--- a/Makefile.am
|
||||||
|
+++ b/Makefile.am
|
||||||
|
@@ -21,6 +21,7 @@ check_PROGRAMS = \
|
||||||
|
testModule \
|
||||||
|
testThreads \
|
||||||
|
testapi \
|
||||||
|
+ testcatalog \
|
||||||
|
testchar \
|
||||||
|
testdict \
|
||||||
|
testlimits \
|
||||||
|
@@ -143,6 +144,10 @@ testlimits_SOURCES=testlimits.c
|
||||||
|
testlimits_DEPENDENCIES = $(DEPS)
|
||||||
|
testlimits_LDADD= $(LDADDS)
|
||||||
|
|
||||||
|
+testcatalog_SOURCES=testcatalog.c
|
||||||
|
+testcatalog_DEPENDENCIES = $(DEPS)
|
||||||
|
+testcatalog_LDADD= $(LDADDS)
|
||||||
|
+
|
||||||
|
testchar_SOURCES=testchar.c
|
||||||
|
testchar_DEPENDENCIES = $(DEPS)
|
||||||
|
testchar_LDADD= $(LDADDS)
|
||||||
|
@@ -206,6 +211,7 @@ check-local:
|
||||||
|
$(CHECKER) ./runtest$(EXEEXT)
|
||||||
|
$(CHECKER) ./testrecurse$(EXEEXT)
|
||||||
|
$(CHECKER) ./testapi$(EXEEXT)
|
||||||
|
+ $(CHECKER) ./testcatalog$(EXEEXT)
|
||||||
|
$(CHECKER) ./testchar$(EXEEXT)
|
||||||
|
$(CHECKER) ./testdict$(EXEEXT)
|
||||||
|
$(CHECKER) ./testparser$(EXEEXT)
|
||||||
|
diff --git a/catalog.c b/catalog.c
|
||||||
|
index 401dbc14..eb889162 100644
|
||||||
|
--- a/catalog.c
|
||||||
|
+++ b/catalog.c
|
||||||
|
@@ -649,43 +649,54 @@ static void xmlDumpXMLCatalogNode(xmlCatalogEntryPtr catal, xmlNodePtr catalog,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
|
||||||
|
- int ret;
|
||||||
|
- xmlDocPtr doc;
|
||||||
|
+static xmlDocPtr
|
||||||
|
+xmlDumpXMLCatalogToDoc(xmlCatalogEntryPtr catal) {
|
||||||
|
xmlNsPtr ns;
|
||||||
|
xmlDtdPtr dtd;
|
||||||
|
xmlNodePtr catalog;
|
||||||
|
- xmlOutputBufferPtr buf;
|
||||||
|
+ xmlDocPtr doc = xmlNewDoc(NULL);
|
||||||
|
+ if (doc == NULL) {
|
||||||
|
+ return(NULL);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Rebuild a catalog
|
||||||
|
- */
|
||||||
|
- doc = xmlNewDoc(NULL);
|
||||||
|
- if (doc == NULL)
|
||||||
|
- return(-1);
|
||||||
|
dtd = xmlNewDtd(doc, BAD_CAST "catalog",
|
||||||
|
- BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
|
||||||
|
-BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
|
||||||
|
+ BAD_CAST "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN",
|
||||||
|
+ BAD_CAST "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd");
|
||||||
|
|
||||||
|
xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
|
||||||
|
|
||||||
|
ns = xmlNewNs(NULL, XML_CATALOGS_NAMESPACE, NULL);
|
||||||
|
if (ns == NULL) {
|
||||||
|
- xmlFreeDoc(doc);
|
||||||
|
- return(-1);
|
||||||
|
+ xmlFreeDoc(doc);
|
||||||
|
+ return(NULL);
|
||||||
|
}
|
||||||
|
catalog = xmlNewDocNode(doc, ns, BAD_CAST "catalog", NULL);
|
||||||
|
if (catalog == NULL) {
|
||||||
|
- xmlFreeNs(ns);
|
||||||
|
- xmlFreeDoc(doc);
|
||||||
|
- return(-1);
|
||||||
|
+ xmlFreeDoc(doc);
|
||||||
|
+ xmlFreeNs(ns);
|
||||||
|
+ return(NULL);
|
||||||
|
}
|
||||||
|
catalog->nsDef = ns;
|
||||||
|
xmlAddChild((xmlNodePtr) doc, catalog);
|
||||||
|
-
|
||||||
|
xmlDumpXMLCatalogNode(catal, catalog, doc, ns, NULL);
|
||||||
|
|
||||||
|
+ return(doc);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+xmlDumpXMLCatalog(FILE *out, xmlCatalogEntryPtr catal) {
|
||||||
|
+ int ret;
|
||||||
|
+ xmlDocPtr doc;
|
||||||
|
+ xmlOutputBufferPtr buf;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Rebuild a catalog
|
||||||
|
+ */
|
||||||
|
+ doc = xmlDumpXMLCatalogToDoc(catal);
|
||||||
|
+ if (doc == NULL) {
|
||||||
|
+ return(-1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* reserialize it
|
||||||
|
*/
|
||||||
|
@@ -3417,6 +3428,20 @@ xmlCatalogDump(FILE *out) {
|
||||||
|
|
||||||
|
xmlACatalogDump(xmlDefaultCatalog, out);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Dump all the global catalog content as a xmlDoc
|
||||||
|
+ * This function is just for testing/debugging purposes
|
||||||
|
+ *
|
||||||
|
+ * @returns The catalog as xmlDoc or NULL if failed, it must be freed by the caller.
|
||||||
|
+ */
|
||||||
|
+xmlDocPtr
|
||||||
|
+xmlCatalogDumpDoc(void) {
|
||||||
|
+ if (!xmlCatalogInitialized)
|
||||||
|
+ xmlInitializeCatalog();
|
||||||
|
+
|
||||||
|
+ return xmlDumpXMLCatalogToDoc(xmlDefaultCatalog->xml);
|
||||||
|
+}
|
||||||
|
#endif /* LIBXML_OUTPUT_ENABLED */
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/include/libxml/catalog.h b/include/libxml/catalog.h
|
||||||
|
index 88a7483c..e1bc5feb 100644
|
||||||
|
--- a/include/libxml/catalog.h
|
||||||
|
+++ b/include/libxml/catalog.h
|
||||||
|
@@ -119,6 +119,8 @@ XMLPUBFUN void
|
||||||
|
#ifdef LIBXML_OUTPUT_ENABLED
|
||||||
|
XMLPUBFUN void
|
||||||
|
xmlCatalogDump (FILE *out);
|
||||||
|
+XMLPUBFUN xmlDocPtr
|
||||||
|
+ xmlCatalogDumpDoc (void);
|
||||||
|
#endif /* LIBXML_OUTPUT_ENABLED */
|
||||||
|
XMLPUBFUN xmlChar *
|
||||||
|
xmlCatalogResolve (const xmlChar *pubID,
|
||||||
|
diff --git a/test/catalogs/catalog-recursive.xml b/test/catalogs/catalog-recursive.xml
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..3b3d03f9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/test/catalogs/catalog-recursive.xml
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
|
||||||
|
+ <delegateURI uriStartString="/foo" catalog="catalog-recursive.xml"/>
|
||||||
|
+</catalog>
|
||||||
|
diff --git a/test/catalogs/repeated-next-catalog.xml b/test/catalogs/repeated-next-catalog.xml
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..76d34c3c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/test/catalogs/repeated-next-catalog.xml
|
||||||
|
@@ -0,0 +1,10 @@
|
||||||
|
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
|
||||||
|
+ <nextCatalog catalog="registry.xml"/>
|
||||||
|
+ <nextCatalog catalog="registry.xml"/>
|
||||||
|
+ <nextCatalog catalog="./registry.xml"/>
|
||||||
|
+ <nextCatalog catalog="././registry.xml"/>
|
||||||
|
+ <nextCatalog catalog="./././registry.xml"/>
|
||||||
|
+ <nextCatalog catalog="./../catalogs/registry.xml"/>
|
||||||
|
+ <nextCatalog catalog="./../catalogs/./registry.xml"/>
|
||||||
|
+</catalog>
|
||||||
|
+
|
||||||
|
diff --git a/testcatalog.c b/testcatalog.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..86d33bd0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/testcatalog.c
|
||||||
|
@@ -0,0 +1,96 @@
|
||||||
|
+/*
|
||||||
|
+ * testcatalog.c: C program to run libxml2 catalog.c unit tests
|
||||||
|
+ *
|
||||||
|
+ * To compile on Unixes:
|
||||||
|
+ * cc -o testcatalog `xml2-config --cflags` testcatalog.c `xml2-config --libs` -lpthread
|
||||||
|
+ *
|
||||||
|
+ * See Copyright for the status of this software.
|
||||||
|
+ *
|
||||||
|
+ * Author: Daniel Garcia <dani@danigm.net>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#include "libxml.h"
|
||||||
|
+#include <stdio.h>
|
||||||
|
+
|
||||||
|
+#ifdef LIBXML_CATALOG_ENABLED
|
||||||
|
+#include <libxml/catalog.h>
|
||||||
|
+
|
||||||
|
+/* Test catalog resolve uri with recursive catalog */
|
||||||
|
+static int
|
||||||
|
+testRecursiveDelegateUri(void) {
|
||||||
|
+ int ret = 0;
|
||||||
|
+ const char *cat = "test/catalogs/catalog-recursive.xml";
|
||||||
|
+ const char *entity = "/foo.ent";
|
||||||
|
+ xmlChar *resolved = NULL;
|
||||||
|
+
|
||||||
|
+ xmlInitParser();
|
||||||
|
+ xmlLoadCatalog(cat);
|
||||||
|
+
|
||||||
|
+ /* This should trigger recursive error */
|
||||||
|
+ resolved = xmlCatalogResolveURI(BAD_CAST entity);
|
||||||
|
+ if (resolved != NULL) {
|
||||||
|
+ fprintf(stderr, "CATALOG-FAILURE: Catalog %s entity should fail to resolve\n", entity);
|
||||||
|
+ ret = 1;
|
||||||
|
+ }
|
||||||
|
+ xmlCatalogCleanup();
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Test parsing repeated NextCatalog */
|
||||||
|
+static int
|
||||||
|
+testRepeatedNextCatalog(void) {
|
||||||
|
+ int ret = 0;
|
||||||
|
+ int i = 0;
|
||||||
|
+ const char *cat = "test/catalogs/repeated-next-catalog.xml";
|
||||||
|
+ const char *entity = "/foo.ent";
|
||||||
|
+ xmlDocPtr doc = NULL;
|
||||||
|
+ xmlNodePtr node = NULL;
|
||||||
|
+
|
||||||
|
+ xmlInitParser();
|
||||||
|
+
|
||||||
|
+ xmlLoadCatalog(cat);
|
||||||
|
+ /* To force the complete recursive load */
|
||||||
|
+ xmlCatalogResolveURI(BAD_CAST entity);
|
||||||
|
+ /**
|
||||||
|
+ * Ensure that the doc doesn't contain the same nextCatalog
|
||||||
|
+ */
|
||||||
|
+ doc = xmlCatalogDumpDoc();
|
||||||
|
+ xmlCatalogCleanup();
|
||||||
|
+
|
||||||
|
+ if (doc == NULL) {
|
||||||
|
+ fprintf(stderr, "CATALOG-FAILURE: Failed to dump the catalog\n");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Just the root "catalog" node with a series of nextCatalog */
|
||||||
|
+ node = xmlDocGetRootElement(doc);
|
||||||
|
+ node = node->children;
|
||||||
|
+ for (i=0; node != NULL; node=node->next, i++) {}
|
||||||
|
+ if (i > 1) {
|
||||||
|
+ fprintf(stderr, "CATALOG-FAILURE: Found %d nextCatalog entries and should be 1\n", i);
|
||||||
|
+ ret = 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ xmlFreeDoc(doc);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main(void) {
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ err |= testRecursiveDelegateUri();
|
||||||
|
+ err |= testRepeatedNextCatalog();
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+/* No catalog, so everything okay */
|
||||||
|
+int
|
||||||
|
+main(void) {
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
From deed3b7873dff30b7f87f7f33154c9932a772522 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Garcia Moreno <dani@danigm.net>
|
||||||
|
Date: Sun, 18 Jan 2026 19:47:11 +0100
|
||||||
|
Subject: [PATCH] catalog: Do not check value for duplication nextCatalog
|
||||||
|
|
||||||
|
The value field stores the path as it appears in the catalog definition,
|
||||||
|
the URL is built using xmlBuildURI that changes the relative paths to
|
||||||
|
absolute.
|
||||||
|
|
||||||
|
This change fixes the issue of using relative path to the same catalog
|
||||||
|
in the same file.
|
||||||
|
|
||||||
|
Fix https://gitlab.gnome.org/GNOME/libxml2/-/issues/1040
|
||||||
|
|
||||||
|
CVE: CVE-2026-0992
|
||||||
|
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/deed3b7873dff30b7f87f7f33154c9932a772522]
|
||||||
|
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||||
|
---
|
||||||
|
catalog.c | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/catalog.c b/catalog.c
|
||||||
|
index eb889162..ba9ee7ae 100644
|
||||||
|
--- a/catalog.c
|
||||||
|
+++ b/catalog.c
|
||||||
|
@@ -1286,7 +1286,6 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer,
|
||||||
|
while (prev != NULL) {
|
||||||
|
if ((prev->type == XML_CATA_NEXT_CATALOG) &&
|
||||||
|
(xmlStrEqual (prev->URL, entry->URL)) &&
|
||||||
|
- (xmlStrEqual (prev->value, entry->value)) &&
|
||||||
|
(prev->prefer == entry->prefer) &&
|
||||||
|
(prev->group == entry->group)) {
|
||||||
|
if (xmlDebugCatalogs)
|
||||||
@@ -27,7 +27,9 @@ SRC_URI += "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testt
|
|||||||
file://CVE-2025-7425.patch \
|
file://CVE-2025-7425.patch \
|
||||||
file://CVE-2026-0989.patch \
|
file://CVE-2026-0989.patch \
|
||||||
file://CVE-2026-0990.patch \
|
file://CVE-2026-0990.patch \
|
||||||
file://CVE-2026-0992.patch \
|
file://CVE-2026-0992-01.patch \
|
||||||
|
file://CVE-2026-0992-02.patch \
|
||||||
|
file://CVE-2026-0992-03.patch \
|
||||||
"
|
"
|
||||||
|
|
||||||
SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995"
|
SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995"
|
||||||
|
|||||||
Reference in New Issue
Block a user