1From e20f4d7a656e47553f9da9d594e299e2fa2dbe41 Mon Sep 17 00:00:00 2001 2From: Nick Wellnhofer <wellnhofer@aevum.de> 3Date: Mon, 13 Feb 2023 14:38:05 +0100 4Subject: [PATCH] xinclude: Fix quadratic behavior in xmlXIncludeLoadTxt 5 6Also make text inclusions work with memory buffers, for example when 7using a custom entity loader, and fix a memory leak in case of invalid 8characters. 9 10Fixes #483. 11 12Reference:https://github.com/GNOME/libxml2/commit/e20f4d7a656e47553f9da9d594e299e2fa2dbe41 13Conflict:NA 14 15--- 16 result/XInclude/invalid_char.xml.err | 2 + 17 result/XInclude/invalid_char.xml.rdr | 7 ++++ 18 test/XInclude/docs/invalid_char.xml | 3 ++ 19 test/XInclude/ents/invalid_char.txt | 1 + 20 xinclude.c | 61 ++++++++++++---------------- 21 5 files changed, 39 insertions(+), 35 deletions(-) 22 create mode 100644 result/XInclude/invalid_char.xml.err 23 create mode 100644 result/XInclude/invalid_char.xml.rdr 24 create mode 100644 test/XInclude/docs/invalid_char.xml 25 create mode 100644 test/XInclude/ents/invalid_char.txt 26 27diff --git a/result/XInclude/invalid_char.xml.err b/result/XInclude/invalid_char.xml.err 28new file mode 100644 29index 0000000..c28c109 30--- /dev/null 31+++ b/result/XInclude/invalid_char.xml.err 32@@ -0,0 +1,2 @@ 33+./test/XInclude/docs/invalid_char.xml:2: element include: XInclude error : test/XInclude/ents/invalid_char.txt contains invalid char 34+./test/XInclude/docs/invalid_char.xml:2: element include: XInclude error : could not load test/XInclude/ents/invalid_char.txt, and no fallback was found 35diff --git a/result/XInclude/invalid_char.xml.rdr b/result/XInclude/invalid_char.xml.rdr 36new file mode 100644 37index 0000000..1fb5774 38--- /dev/null 39+++ b/result/XInclude/invalid_char.xml.rdr 40@@ -0,0 +1,7 @@ 41+0 1 x 0 0 42+1 14 #text 0 1 43+ 44+1 1 xinclude:include 1 0 45+1 14 #text 0 1 46+ 47+0 15 x 0 0 48diff --git a/test/XInclude/docs/invalid_char.xml b/test/XInclude/docs/invalid_char.xml 49new file mode 100644 50index 0000000..28e5a48 51--- /dev/null 52+++ b/test/XInclude/docs/invalid_char.xml 53@@ -0,0 +1,3 @@ 54+<x xmlns:xinclude="http://www.w3.org/2001/XInclude"> 55+ <xinclude:include href="../ents/invalid_char.txt" parse="text"/> 56+</x> 57diff --git a/test/XInclude/ents/invalid_char.txt b/test/XInclude/ents/invalid_char.txt 58new file mode 100644 59index 0000000..ae06618 60--- /dev/null 61+++ b/test/XInclude/ents/invalid_char.txt 62@@ -0,0 +1 @@ 63+invalid: � 64\ No newline at end of file 65diff --git a/xinclude.c b/xinclude.c 66index cc486f5..6e5b61d 100644 67--- a/xinclude.c 68+++ b/xinclude.c 69@@ -1798,7 +1798,9 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) { 70 xmlCharEncoding enc = (xmlCharEncoding) 0; 71 xmlParserCtxtPtr pctxt; 72 xmlParserInputPtr inputStream; 73- int xinclude_multibyte_fallback_used = 0; 74+ int len; 75+ const xmlChar *content; 76+ 77 78 /* Don't read from stdin. */ 79 if (xmlStrcmp(url, BAD_CAST "-") == 0) 80@@ -1905,41 +1907,30 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) { 81 /* 82 * Scan all chars from the resource and add the to the node 83 */ 84-xinclude_multibyte_fallback: 85- while (xmlParserInputBufferRead(buf, 128) > 0) { 86- int len; 87- const xmlChar *content; 88- 89- content = xmlBufContent(buf->buffer); 90- len = xmlBufLength(buf->buffer); 91- for (i = 0;i < len;) { 92- int cur; 93- int l; 94- 95- cur = xmlStringCurrentChar(NULL, &content[i], &l); 96- if (!IS_CHAR(cur)) { 97- /* Handle split multibyte char at buffer boundary */ 98- if (((len - i) < 4) && (!xinclude_multibyte_fallback_used)) { 99- xinclude_multibyte_fallback_used = 1; 100- xmlBufShrink(buf->buffer, i); 101- goto xinclude_multibyte_fallback; 102- } else { 103- xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, 104- XML_XINCLUDE_INVALID_CHAR, 105- "%s contains invalid char\n", URL); 106- xmlFreeParserCtxt(pctxt); 107- xmlFreeParserInputBuffer(buf); 108- xmlFree(URL); 109- return(-1); 110- } 111- } else { 112- xinclude_multibyte_fallback_used = 0; 113- xmlNodeAddContentLen(node, &content[i], l); 114- } 115- i += l; 116- } 117- xmlBufShrink(buf->buffer, len); 118+ while (xmlParserInputBufferRead(buf, 4096) > 0) 119+ ; 120+ 121+ content = xmlBufContent(buf->buffer); 122+ len = xmlBufLength(buf->buffer); 123+ for (i = 0; i < len;) { 124+ int cur; 125+ int l; 126+ 127+ cur = xmlStringCurrentChar(NULL, &content[i], &l); 128+ if (!IS_CHAR(cur)) { 129+ xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_INVALID_CHAR, 130+ "%s contains invalid char\n", URL); 131+ xmlFreeNode(node); 132+ xmlFreeInputStream(inputStream); 133+ xmlFreeParserCtxt(pctxt); 134+ xmlFree(URL); 135+ return(-1); 136+ } 137+ 138+ i += l; 139 } 140+ 141+ xmlNodeAddContentLen(node, content, len); 142 xmlFreeParserCtxt(pctxt); 143 xmlXIncludeAddTxt(ctxt, node->content, URL); 144 xmlFreeInputStream(inputStream); 145-- 1462.27.0 147 148