From 67c34fe24e8b627138f95eb45a24d55547981c49 Mon Sep 17 00:00:00 2001
From: Ruben Thijssen <ruben.thijssen@cba.com.au>
Date: Fri, 15 May 2026 15:42:18 +1000
Subject: [PATCH] fix(xinclude): propagate parseFlags in xmlXIncludeProcess and
 xmlXIncludeProcessTree

---
 result/XInclude/issue1120-1.xml         |  4 ++
 result/XInclude/issue1120-1.xml.err     |  1 +
 result/XInclude/issue1120-2.xml         |  4 ++
 result/XInclude/issue1120-2.xml.err     |  1 +
 runtest.c                               | 75 +++++++++++++++++++++++++
 test/XInclude/issue1120/issue1120-1.xml |  6 ++
 test/XInclude/issue1120/issue1120-2.xml |  6 ++
 xinclude.c                              |  9 ++-
 8 files changed, 103 insertions(+), 3 deletions(-)
 create mode 100644 result/XInclude/issue1120-1.xml
 create mode 100644 result/XInclude/issue1120-1.xml.err
 create mode 100644 result/XInclude/issue1120-2.xml
 create mode 100644 result/XInclude/issue1120-2.xml.err
 create mode 100644 test/XInclude/issue1120/issue1120-1.xml
 create mode 100644 test/XInclude/issue1120/issue1120-2.xml

diff --git a/result/XInclude/issue1120-1.xml b/result/XInclude/issue1120-1.xml
new file mode 100644
index 000000000..5d83cc966
--- /dev/null
+++ b/result/XInclude/issue1120-1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:xi="http://www.w3.org/2001/XInclude">
+  Network access is not allowed
+</doc>
diff --git a/result/XInclude/issue1120-1.xml.err b/result/XInclude/issue1120-1.xml.err
new file mode 100644
index 000000000..c134bed1c
--- /dev/null
+++ b/result/XInclude/issue1120-1.xml.err
@@ -0,0 +1 @@
+I/O error : failed to load "http://example.invalid/file.txt": Attempt to load network entity
diff --git a/result/XInclude/issue1120-2.xml b/result/XInclude/issue1120-2.xml
new file mode 100644
index 000000000..af5bde91a
--- /dev/null
+++ b/result/XInclude/issue1120-2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:xi="http://www.w3.org/2001/XInclude">
+  <p>Network access is not allowed</p>
+</doc>
diff --git a/result/XInclude/issue1120-2.xml.err b/result/XInclude/issue1120-2.xml.err
new file mode 100644
index 000000000..051f59280
--- /dev/null
+++ b/result/XInclude/issue1120-2.xml.err
@@ -0,0 +1 @@
+I/O error : failed to load "http://example.invalid/file.xml": Attempt to load network entity
diff --git a/runtest.c b/runtest.c
index 48c54a0b9..6961f648d 100644
--- a/runtest.c
+++ b/runtest.c
@@ -2477,6 +2477,75 @@ noentParseTest(const char *filename, const char *result,
     return(res);
 }
 
+#ifdef LIBXML_XINCLUDE_ENABLED
+/**
+ * Parse a file and run xmlXIncludeProcess() to verify that doc->parseFlags
+ * is propagated properly.
+ *
+ * @param filename  the file to parse
+ * @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
+xincludeProcessTest(const char *filename, const char *result, const char *err,
+                    int options) {
+    xmlParserCtxtPtr ctxt;
+    xmlDocPtr doc;
+    xmlChar *base = NULL;
+    int size, res;
+    int ret = 0;
+
+    nb_tests++;
+
+    /* Create a new parser context */
+    ctxt = xmlNewParserCtxt();
+    if (ctxt == NULL)
+        return(-1);
+
+    /* Load the data from `filename` into a parser context */
+    xmlCtxtSetErrorHandler(ctxt, testStructuredErrorHandler, NULL);
+    doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
+    xmlFreeParserCtxt(ctxt);
+
+    /* Check if `doc` was created successfully */
+    if (doc == NULL) {
+        testErrorHandler(NULL, "%s : failed to parse\n", filename);
+        return(-1);
+    }
+
+    /*
+     * Run xmlXIncludeProcess() with a structured error handler to check that
+     * the parse flags are propagated.
+     */
+    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
+    xmlXIncludeProcess(doc);
+    xmlSetStructuredErrorFunc(NULL, NULL);
+
+    /* Check the result and for any errors */
+    if (result) {
+        xmlDocDumpMemory(doc, &base, &size);
+        res = compareFileMem(result, (char *) base, size);
+        xmlFree(base);
+        if (res != 0) {
+            fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+            ret = -1;
+        }
+    }
+
+    if ((ret == 0) && (err != NULL)) {
+        res = compareFileMem(err, testErrors, testErrorsSize);
+        if (res != 0) {
+            fprintf(stderr, "Error for %s failed\n", filename);
+            ret = -1;
+        }
+    }
+
+    xmlFreeDoc(doc);
+    return(ret);
+}
+#endif
+
 /**
  * Parse a file using the #xmlReadFile API and check for errors.
  *
@@ -5502,6 +5571,12 @@ testDesc testDescriptions[] = {
     { "XInclude regression tests without reader",
       errParseTest, "./test/XInclude/without-reader/*", "result/XInclude/", "",
       ".err", XML_PARSE_XINCLUDE },
+    { "XInclude issue1120 regression tests",
+      errParseTest, "./test/XInclude/issue1120/*", "result/XInclude/", "",
+      ".err", XML_PARSE_XINCLUDE | XML_PARSE_NONET },
+    { "XInclude xmlXIncludeProcess() issue1120 regression tests",
+      xincludeProcessTest, "./test/XInclude/issue1120/*", "result/XInclude/",
+      "", ".err", XML_PARSE_NONET },
 #endif
 #ifdef LIBXML_XPATH_ENABLED
 #ifdef LIBXML_DEBUG_ENABLED
diff --git a/test/XInclude/issue1120/issue1120-1.xml b/test/XInclude/issue1120/issue1120-1.xml
new file mode 100644
index 000000000..b0b8feef4
--- /dev/null
+++ b/test/XInclude/issue1120/issue1120-1.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<doc xmlns:xi="http://www.w3.org/2001/XInclude">
+  <xi:include href="http://example.invalid/file.txt" parse="text">
+    <xi:fallback>Network access is not allowed</xi:fallback>
+  </xi:include>
+</doc>
diff --git a/test/XInclude/issue1120/issue1120-2.xml b/test/XInclude/issue1120/issue1120-2.xml
new file mode 100644
index 000000000..b4c9fe5ef
--- /dev/null
+++ b/test/XInclude/issue1120/issue1120-2.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<doc xmlns:xi="http://www.w3.org/2001/XInclude">
+  <xi:include href="http://example.invalid/file.xml">
+    <xi:fallback><p>Network access is not allowed</p></xi:fallback>
+  </xi:include>
+</doc>
diff --git a/xinclude.c b/xinclude.c
index 8a4989473..c7cedd055 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -1409,6 +1409,8 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
         xmlCtxtSetResourceLoader(pctxt, ctxt->resourceLoader,
                                  ctxt->resourceCtxt);
 
+    xmlCtxtUseOptions(pctxt, ctxt->parseFlags);
+
     inputStream = xmlLoadResource(pctxt, (const char*) url, NULL,
                                   XML_RESOURCE_XINCLUDE_TEXT);
     if (inputStream == NULL) {
@@ -1419,7 +1421,8 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) {
             xmlXIncludeErrMemory(ctxt);
         else if ((pctxt->errNo != XML_ERR_OK) &&
                  (pctxt->errNo != XML_IO_ENOENT) &&
-                 (pctxt->errNo != XML_IO_UNKNOWN))
+                 (pctxt->errNo != XML_IO_UNKNOWN) &&
+                 (pctxt->errNo != XML_IO_NETWORK_ATTEMPT))
             xmlXIncludeErr(ctxt, NULL, pctxt->errNo, "load error", NULL);
 	goto error;
     }
@@ -2121,7 +2124,7 @@ xmlXIncludeProcessFlags(xmlDoc *doc, int flags) {
  */
 int
 xmlXIncludeProcess(xmlDoc *doc) {
-    return(xmlXIncludeProcessFlags(doc, 0));
+    return(xmlXIncludeProcessFlags(doc, doc ? doc->parseFlags : 0));
 }
 
 /**
@@ -2161,7 +2164,7 @@ xmlXIncludeProcessTreeFlags(xmlNode *tree, int flags) {
  */
 int
 xmlXIncludeProcessTree(xmlNode *tree) {
-    return(xmlXIncludeProcessTreeFlags(tree, 0));
+    return(xmlXIncludeProcessTreeFlags(tree, (tree && tree->doc) ? tree->doc->parseFlags : 0));
 }
 
 /**
-- 
GitLab

