catalog: Fix NULL deref for nextCatalog without 'catalog' attribute
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 04d373b..ec9e73d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -525,7 +525,7 @@
         add_test(NAME runxmlconf COMMAND runxmlconf WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
     endif()
     add_test(NAME testapi COMMAND testapi)
-    add_test(NAME testcatalog COMMAND testcatalog)
+    add_test(NAME testcatalog COMMAND testcatalog WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
     add_test(NAME testchar COMMAND testchar)
     add_test(NAME testdict COMMAND testdict)
     add_test(NAME testparser COMMAND testparser WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/catalog.c b/catalog.c
index 448c88a..2a080f8 100644
--- a/catalog.c
+++ b/catalog.c
@@ -1329,7 +1329,7 @@
 		BAD_CAST "nextCatalog", NULL,
 		BAD_CAST "catalog", prefer, cgroup);
 	/* Avoid duplication of nextCatalog */
-	while (prev != NULL) {
+	while ((entry != NULL) && (prev != NULL)) {
 	    if ((prev->type == XML_CATA_NEXT_CATALOG) &&
 		(xmlStrEqual (prev->URL, entry->URL)) &&
 		(prev->prefer == entry->prefer) &&
diff --git a/test/catalogs/next-catalog-missing-attr.xml b/test/catalogs/next-catalog-missing-attr.xml
new file mode 100644
index 0000000..b31a490
--- /dev/null
+++ b/test/catalogs/next-catalog-missing-attr.xml
@@ -0,0 +1,4 @@
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+  <nextCatalog catalog="registry.xml"/>
+  <nextCatalog/>
+</catalog>
diff --git a/testcatalog.c b/testcatalog.c
index 56c9bef..d3384a4 100644
--- a/testcatalog.c
+++ b/testcatalog.c
@@ -80,6 +80,62 @@
 }
 
 /*
+ * Test a nextCatalog entry which lacks the mandatory 'catalog' attribute
+ * See https://gitlab.gnome.org/GNOME/libxml2/-/issues/1143
+ */
+static int
+testNextCatalogMissingAttr(void) {
+    int ret = 0;
+    int i = 0;
+    const char *cat = "test/catalogs/next-catalog-missing-attr.xml";
+    const char *sysId = "http://www.oasis-open.org/docbook/xml/4.1.2/dbpoolx.mod";
+    const char *expect = "/usr/share/xml/docbook/xml/4.1.2/dbpoolx.mod";
+    xmlChar *resolved = NULL;
+    xmlDocPtr doc = NULL;
+    xmlNodePtr node = NULL;
+
+    xmlInitParser();
+
+    xmlLoadCatalog(cat);
+    /*
+     * The malformed nextCatalog must be ignored, the valid one must still
+     * be followed. This also forces the complete recursive load.
+     */
+    resolved = xmlCatalogResolveSystem(BAD_CAST sysId);
+    if ((resolved == NULL) || (strcmp((char *) resolved, expect) != 0)) {
+        fprintf(stderr, "CATALOG-FAILURE: %s resolved to %s, expected %s\n",
+                sysId, resolved == NULL ? "NULL" : (char *) resolved, expect);
+        ret = 1;
+    }
+    if (resolved != NULL)
+        xmlFree(resolved);
+
+    /**
+     * Ensure that only the valid nextCatalog was recorded
+     */
+    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 single 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;
+}
+
+/*
  * Test repeated call to xmlCatalogResolveURI
  * See https://gitlab.gnome.org/GNOME/libxml2/-/work_items/1125
  */
@@ -135,6 +191,7 @@
 
     err |= testRecursiveDelegateUri();
     err |= testRepeatedNextCatalog();
+    err |= testNextCatalogMissingAttr();
     err |= testRepeatedResolveURI();
 
     return err;