From d88df4bd48ba4ce9a68040a2427b4a665d5ff891 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 16 Aug 2020 23:38:48 +0200
Subject: [PATCH] Fix corner case with empty xi:fallback

xi:fallback could become empty after recursive expansion. Use a flag
to track whether nodes should be skipped.
---
 result/XInclude/fallback6.xml     |  1 +
 result/XInclude/fallback6.xml.rdr |  0
 test/XInclude/docs/fallback6.xml  |  6 ++++++
 xinclude.c                        | 11 ++++-------
 4 files changed, 11 insertions(+), 7 deletions(-)
 create mode 100644 result/XInclude/fallback6.xml
 create mode 100644 result/XInclude/fallback6.xml.rdr
 create mode 100644 test/XInclude/docs/fallback6.xml

diff --git a/result/XInclude/fallback6.xml b/result/XInclude/fallback6.xml
new file mode 100644
index 0000000..2b5d411
--- /dev/null
+++ b/result/XInclude/fallback6.xml
@@ -0,0 +1 @@
+<?xml version="1.0"?>
diff --git a/result/XInclude/fallback6.xml.rdr b/result/XInclude/fallback6.xml.rdr
new file mode 100644
index 0000000..e69de29
diff --git a/test/XInclude/docs/fallback6.xml b/test/XInclude/docs/fallback6.xml
new file mode 100644
index 0000000..fd00a03
--- /dev/null
+++ b/test/XInclude/docs/fallback6.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="b.xml">
+    <xi:fallback><xi:include href="c.xml">
+        <xi:fallback/>
+    </xi:include></xi:fallback>
+</xi:include>
diff --git a/xinclude.c b/xinclude.c
index ff265eb..e9d3af5 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -60,7 +60,7 @@ struct _xmlXIncludeRef {
     int                   xml; /* xml or txt */
     int                 count; /* how many refs use that specific doc */
     xmlXPathObjectPtr    xptr; /* the xpointer if needed */
-    int		      emptyFb; /* flag to show fallback empty */
+    int		         skip; /* skip in case of errors */
 };
 
 struct _xmlXIncludeCtxt {
@@ -2007,7 +2007,6 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
 	                                           fallback->children);
     } else {
         ctxt->incTab[nr]->inc = NULL;
-	ctxt->incTab[nr]->emptyFb = 1;	/* flag empty callback */
     }
     return(ret);
 }
@@ -2164,13 +2163,13 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
 		((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
 		 (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
 		ret = xmlXIncludeLoadFallback(ctxt, children, nr);
-		if (ret == 0)
-		    break;
+		break;
 	    }
 	    children = children->next;
 	}
     }
     if (ret < 0) {
+        ctxt->incTab[nr]->skip = 1;
 	xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
 	               XML_XINCLUDE_NO_FALLBACK,
 		       "could not load %s, and no fallback was found\n",
@@ -2468,9 +2467,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
      *
      */
     for (i = ctxt->incBase;i < ctxt->incNr; i++) {
-	if ((ctxt->incTab[i]->inc != NULL) ||
-		(ctxt->incTab[i]->xptr != NULL) ||
-		(ctxt->incTab[i]->emptyFb != 0))	/* (empty fallback) */
+	if (ctxt->incTab[i]->skip == 0)
 	    xmlXIncludeIncludeNode(ctxt, i);
     }
 
-- 
1.8.3.1

