Upgrade to upstream v2.9.14 and Cleanup duplicate installation

This commit is contained in:
fly_fzc 2022-07-12 15:57:11 +08:00 committed by fly_fzc
parent 24a5ba8e03
commit b8bc4e4ffd
13 changed files with 15 additions and 1170 deletions

View File

@ -1,36 +0,0 @@
From c3ae53279a37369d8b100b016126136dea05b44b Mon Sep 17 00:00:00 2001
From: huangduirong <huangduirong@huawei.com>
Date: Sat, 30 Oct 2021 15:21:01 +0800
Subject: [PATCH] fix null-deref in xmlSchemaGetComponentTargetNs
---
xmlschemas.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/xmlschemas.c b/xmlschemas.c
index 5387c8e..17aa6df 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -1329,6 +1329,9 @@ xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
{
+ if (item == NULL) {
+ return (NULL);
+ }
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return (((xmlSchemaElementPtr) item)->name);
@@ -1384,6 +1387,9 @@ xmlSchemaGetQNameRefTargetNs(void *ref)
static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
{
+ if (item == NULL) {
+ return (NULL);
+ }
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return (((xmlSchemaElementPtr) item)->targetNamespace);
--
1.8.3.1

View File

@ -1,31 +0,0 @@
From 3e1aad4fe584747fd7d17cc7b2863a78e2d21a77 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 2 Jun 2021 17:31:49 +0200
Subject: [PATCH] Fix XPath recursion limit
Fix accounting of recursion depth when parsing XPath expressions.
This silly bug introduced in commit 804c5297 could lead to spurious
errors when parsing larger expressions or XSLT documents.
Should fix #264.
---
xpath.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xpath.c b/xpath.c
index 7497ba0..1aa2f1a 100644
--- a/xpath.c
+++ b/xpath.c
@@ -10983,7 +10983,7 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
}
if (xpctxt != NULL)
- xpctxt->depth -= 1;
+ xpctxt->depth -= 10;
}
/**
--
1.8.3.1

View File

@ -1,63 +0,0 @@
From dea91c97debeac7c1aaf9c19f79029809e23a353 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 27 Jul 2021 16:12:54 +0200
Subject: [PATCH] Fix buffering in xmlOutputBufferWrite
Fix a regression introduced with commit a697ed1e which caused
xmlOutputBufferWrite to flush internal buffers too late.
Fixes #296.
---
xmlIO.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/xmlIO.c b/xmlIO.c
index 57312b9..f20c0fa 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -3401,12 +3401,18 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
out->error = XML_IO_ENCODER;
return(-1);
}
- nbchars = ret >= 0 ? ret : 0;
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->conv);
+ else
+ nbchars = ret >= 0 ? ret : 0;
} else {
ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
if (ret != 0)
return(-1);
- nbchars = chunk;
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->buffer);
+ else
+ nbchars = chunk;
}
buf += chunk;
len -= chunk;
@@ -3593,13 +3599,19 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
out->error = XML_IO_ENCODER;
return(-1);
}
- nbchars = ret >= 0 ? ret : 0;
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->conv);
+ else
+ nbchars = ret >= 0 ? ret : 0;
} else {
ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
return(-1);
xmlBufAddLen(out->buffer, chunk);
- nbchars = chunk;
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->buffer);
+ else
+ nbchars = chunk;
}
str += cons;
len -= cons;
--
1.8.3.1

View File

@ -1,46 +0,0 @@
From 13ad8736d294536da4cbcd70a96b0a2fbf47070c Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 25 May 2021 10:55:25 +0200
Subject: [PATCH] Fix regression in xmlNodeDumpOutputInternal
Commit 85b1792e could cause additional whitespace if xmlNodeDump was
called with a non-zero starting level.
---
xmlsave.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/xmlsave.c b/xmlsave.c
index aedbd5e..489505f 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -890,6 +890,13 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
break;
case XML_ELEMENT_NODE:
+ if ((cur != root) && (ctxt->format == 1) &&
+ (xmlIndentTreeOutput))
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level),
+ ctxt->indent);
+
/*
* Some users like lxml are known to pass nodes with a corrupted
* tree structure. Fall back to a recursive call to handle this
@@ -900,13 +907,6 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
break;
}
- if ((ctxt->level > 0) && (ctxt->format == 1) &&
- (xmlIndentTreeOutput))
- xmlOutputBufferWrite(buf, ctxt->indent_size *
- (ctxt->level > ctxt->indent_nr ?
- ctxt->indent_nr : ctxt->level),
- ctxt->indent);
-
xmlOutputBufferWrite(buf, 1, "<");
if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
--
1.8.3.1

View File

@ -1,43 +0,0 @@
From 92d9ab4c28842a09ca2b76d3ff2f933e01b6cd6f Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 7 Jun 2021 15:09:53 +0200
Subject: [PATCH] Fix whitespace when serializing empty HTML documents
The old, non-recursive HTML serialization code would always terminate
the output with a newline. The new implementation omitted the newline
if the document node had no children. Readd the newline when
serializing empty documents.
Fixes #266.
---
HTMLtree.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/HTMLtree.c b/HTMLtree.c
index bdd639c..7a2b855 100644
--- a/HTMLtree.c
+++ b/HTMLtree.c
@@ -763,11 +763,15 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
if (((xmlDocPtr) cur)->intSubset != NULL) {
htmlDtdDumpOutput(buf, (xmlDocPtr) cur, NULL);
}
- /* Always validate cur->parent when descending. */
- if ((cur->parent == parent) && (cur->children != NULL)) {
- parent = cur;
- cur = cur->children;
- continue;
+ if (cur->children != NULL) {
+ /* Always validate cur->parent when descending. */
+ if (cur->parent == parent) {
+ parent = cur;
+ cur = cur->children;
+ continue;
+ }
+ } else {
+ xmlOutputBufferWriteString(buf, "\n");
}
break;
--
1.8.3.1

View File

@ -1,60 +0,0 @@
From ec6e3efb06d7b15cf5a2328fabd3845acea4c815 Mon Sep 17 00:00:00 2001
From: Arne Becker <arne_becker@genua.de>
Date: Tue, 6 Jul 2021 21:56:04 +0200
Subject: [PATCH] Patch to forbid epsilon-reduction of final states
When building the internal representation of a regexp, it is possible
that a lot of empty transitions are created. Therefore there is a step
to reduce them in the function xmlFAEliminateSimpleEpsilonTransitions.
There is an error there for this case:
* State 1 has a transition with an atom (in this case "a") to state 2.
* State 2 is final and has an epsilon transition to state 1.
After reduction it looked like:
* State 1 has a transition with an atom (in this case "a") to itself
and is final.
In other words, the empty string is accepted when it shouldn't be.
The attached patch skips the reduction step for final states.
An alternative would be to insert or increment counters when reducing a
final state, but this seemed error prone and unnecessary, since there
aren't that many final states.
Fixes #282
---
xmlregexp.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/xmlregexp.c b/xmlregexp.c
index 40dabb2..8d01c2b 100644
--- a/xmlregexp.c
+++ b/xmlregexp.c
@@ -1892,6 +1892,12 @@ xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr,
* then X and Y are semantically equivalent and X can be eliminated
* If X is the start state then make Y the start state, else replace the
* target of all transitions to X by transitions to Y.
+ *
+ * If X is a final state, skip it.
+ * Otherwise it would be necessary to manipulate counters for this case when
+ * eliminating state 2:
+ * State 1 has a transition with an atom to state 2.
+ * State 2 is final and has an epsilon transition to state 1.
*/
static void
xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
@@ -1904,7 +1910,8 @@ xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
continue;
if (state->nbTrans != 1)
continue;
- if (state->type == XML_REGEXP_UNREACH_STATE)
+ if (state->type == XML_REGEXP_UNREACH_STATE ||
+ state->type == XML_REGEXP_FINAL_STATE)
continue;
/* is the only transition out a basic transition */
if ((state->trans[0].atom == NULL) &&
--
1.8.3.1

View File

@ -1,212 +0,0 @@
From 85b1792e37b131e7a51af98a37f92472e8de5f3f Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 18 May 2021 20:08:28 +0200
Subject: [PATCH] Work around lxml API abuse
Make xmlNodeDumpOutput and htmlNodeDumpFormatOutput work with corrupted
parent pointers. This used to work with the old recursive code but the
non-recursive rewrite required parent pointers to be set correctly.
Unfortunately, lxml relies on the old behavior and passes subtrees with
a corrupted structure. Fall back to a recursive function call if an
invalid parent pointer is detected.
Fixes #255.
---
HTMLtree.c | 46 ++++++++++++++++++++++++++++------------------
xmlsave.c | 31 +++++++++++++++++++++----------
2 files changed, 49 insertions(+), 28 deletions(-)
diff --git a/HTMLtree.c b/HTMLtree.c
index 24434d4..bdd639c 100644
--- a/HTMLtree.c
+++ b/HTMLtree.c
@@ -744,7 +744,7 @@ void
htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
xmlNodePtr cur, const char *encoding ATTRIBUTE_UNUSED,
int format) {
- xmlNodePtr root;
+ xmlNodePtr root, parent;
xmlAttrPtr attr;
const htmlElemDesc * info;
@@ -755,6 +755,7 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
}
root = cur;
+ parent = cur->parent;
while (1) {
switch (cur->type) {
case XML_HTML_DOCUMENT_NODE:
@@ -762,7 +763,9 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
if (((xmlDocPtr) cur)->intSubset != NULL) {
htmlDtdDumpOutput(buf, (xmlDocPtr) cur, NULL);
}
- if (cur->children != NULL) {
+ /* Always validate cur->parent when descending. */
+ if ((cur->parent == parent) && (cur->children != NULL)) {
+ parent = cur;
cur = cur->children;
continue;
}
@@ -770,6 +773,16 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
case XML_ELEMENT_NODE:
/*
+ * Some users like lxml are known to pass nodes with a corrupted
+ * tree structure. Fall back to a recursive call to handle this
+ * case.
+ */
+ if ((cur->parent != parent) && (cur->children != NULL)) {
+ htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
+ break;
+ }
+
+ /*
* Get specific HTML info for that node.
*/
if (cur->ns == NULL)
@@ -817,6 +830,7 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
(cur->name != NULL) &&
(cur->name[0] != 'p')) /* p, pre, param */
xmlOutputBufferWriteString(buf, "\n");
+ parent = cur;
cur = cur->children;
continue;
}
@@ -825,9 +839,9 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
(info != NULL) && (!info->isinline)) {
if ((cur->next->type != HTML_TEXT_NODE) &&
(cur->next->type != HTML_ENTITY_REF_NODE) &&
- (cur->parent != NULL) &&
- (cur->parent->name != NULL) &&
- (cur->parent->name[0] != 'p')) /* p, pre, param */
+ (parent != NULL) &&
+ (parent->name != NULL) &&
+ (parent->name[0] != 'p')) /* p, pre, param */
xmlOutputBufferWriteString(buf, "\n");
}
@@ -842,9 +856,9 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
break;
if (((cur->name == (const xmlChar *)xmlStringText) ||
(cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
- ((cur->parent == NULL) ||
- ((xmlStrcasecmp(cur->parent->name, BAD_CAST "script")) &&
- (xmlStrcasecmp(cur->parent->name, BAD_CAST "style"))))) {
+ ((parent == NULL) ||
+ ((xmlStrcasecmp(parent->name, BAD_CAST "script")) &&
+ (xmlStrcasecmp(parent->name, BAD_CAST "style"))))) {
xmlChar *buffer;
buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
@@ -902,13 +916,9 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
break;
}
- /*
- * The parent should never be NULL here but we want to handle
- * corrupted documents gracefully.
- */
- if (cur->parent == NULL)
- return;
- cur = cur->parent;
+ cur = parent;
+ /* cur->parent was validated when descending. */
+ parent = cur->parent;
if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
(cur->type == XML_DOCUMENT_NODE)) {
@@ -939,9 +949,9 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
(cur->next != NULL)) {
if ((cur->next->type != HTML_TEXT_NODE) &&
(cur->next->type != HTML_ENTITY_REF_NODE) &&
- (cur->parent != NULL) &&
- (cur->parent->name != NULL) &&
- (cur->parent->name[0] != 'p')) /* p, pre, param */
+ (parent != NULL) &&
+ (parent->name != NULL) &&
+ (parent->name[0] != 'p')) /* p, pre, param */
xmlOutputBufferWriteString(buf, "\n");
}
}
diff --git a/xmlsave.c b/xmlsave.c
index 61a4045..aedbd5e 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -847,7 +847,7 @@ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
static void
xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
int format = ctxt->format;
- xmlNodePtr tmp, root, unformattedNode = NULL;
+ xmlNodePtr tmp, root, unformattedNode = NULL, parent;
xmlAttrPtr attr;
xmlChar *start, *end;
xmlOutputBufferPtr buf;
@@ -856,6 +856,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
buf = ctxt->buf;
root = cur;
+ parent = cur->parent;
while (1) {
switch (cur->type) {
case XML_DOCUMENT_NODE:
@@ -868,7 +869,9 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
break;
case XML_DOCUMENT_FRAG_NODE:
- if (cur->children != NULL) {
+ /* Always validate cur->parent when descending. */
+ if ((cur->parent == parent) && (cur->children != NULL)) {
+ parent = cur;
cur = cur->children;
continue;
}
@@ -887,7 +890,18 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
break;
case XML_ELEMENT_NODE:
- if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+ /*
+ * Some users like lxml are known to pass nodes with a corrupted
+ * tree structure. Fall back to a recursive call to handle this
+ * case.
+ */
+ if ((cur->parent != parent) && (cur->children != NULL)) {
+ xmlNodeDumpOutputInternal(ctxt, cur);
+ break;
+ }
+
+ if ((ctxt->level > 0) && (ctxt->format == 1) &&
+ (xmlIndentTreeOutput))
xmlOutputBufferWrite(buf, ctxt->indent_size *
(ctxt->level > ctxt->indent_nr ?
ctxt->indent_nr : ctxt->level),
@@ -942,6 +956,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
xmlOutputBufferWrite(buf, 1, ">");
if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
if (ctxt->level >= 0) ctxt->level++;
+ parent = cur;
cur = cur->children;
continue;
}
@@ -1058,13 +1073,9 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
break;
}
- /*
- * The parent should never be NULL here but we want to handle
- * corrupted documents gracefully.
- */
- if (cur->parent == NULL)
- return;
- cur = cur->parent;
+ cur = parent;
+ /* cur->parent was validated when descending. */
+ parent = cur->parent;
if (cur->type == XML_ELEMENT_NODE) {
if (ctxt->level > 0) ctxt->level--;
--
1.8.3.1

View File

@ -1,210 +0,0 @@
From 652dd12a858989b14eed4e84e453059cd3ba340e Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 8 Feb 2022 03:29:24 +0100
Subject: [PATCH] [CVE-2022-23308] Use-after-free of ID and IDREF attributes
If a document is parsed with XML_PARSE_DTDVALID and without
XML_PARSE_NOENT, the value of ID attributes has to be normalized after
potentially expanding entities in xmlRemoveID. Otherwise, later calls
to xmlGetID can return a pointer to previously freed memory.
ID attributes which are empty or contain only whitespace after
entity expansion are affected in a similar way. This is fixed by
not storing such attributes in the ID table.
The test to detect streaming mode when validating against a DTD was
broken. In connection with the defects above, this could result in a
use-after-free when using the xmlReader interface with validation.
Fix detection of streaming mode to avoid similar issues. (This changes
the expected result of a test case. But as far as I can tell, using the
XML reader with XIncludes referencing the root document never worked
properly, anyway.)
All of these issues can result in denial of service. Using xmlReader
with validation could result in disclosure of memory via the error
channel, typically stderr. The security impact of xmlGetID returning
a pointer to freed memory depends on the application. The typical use
case of calling xmlGetID on an unmodified document is not affected.
---
result/XInclude/ns1.xml.rdr | 2 +-
valid.c | 88 ++++++++++++++++++++++++++++-----------------
2 files changed, 56 insertions(+), 34 deletions(-)
diff --git a/result/XInclude/ns1.xml.rdr b/result/XInclude/ns1.xml.rdr
index f23702f..9a3a5e7 100644
--- a/result/XInclude/ns1.xml.rdr
+++ b/result/XInclude/ns1.xml.rdr
@@ -1,7 +1,7 @@
0 1 doc 0 0
1 14 #text 0 1
-1 1 ns:elem 1 0
+1 1 xi:include 1 0
1 14 #text 0 1
1 1 elem 0 0
diff --git a/valid.c b/valid.c
index 5ee391c..8e596f1 100644
--- a/valid.c
+++ b/valid.c
@@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt)
return (ret);
}
+/**
+ * xmlValidNormalizeString:
+ * @str: a string
+ *
+ * Normalize a string in-place.
+ */
+static void
+xmlValidNormalizeString(xmlChar *str) {
+ xmlChar *dst;
+ const xmlChar *src;
+
+ if (str == NULL)
+ return;
+ src = str;
+ dst = str;
+
+ while (*src == 0x20) src++;
+ while (*src != 0) {
+ if (*src == 0x20) {
+ while (*src == 0x20) src++;
+ if (*src != 0)
+ *dst++ = 0x20;
+ } else {
+ *dst++ = *src++;
+ }
+ }
+ *dst = 0;
+}
+
#ifdef DEBUG_VALID_ALGO
static void
xmlValidPrintNode(xmlNodePtr cur) {
@@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
xmlFree((char *)(str));
+static int
+xmlIsStreaming(xmlValidCtxtPtr ctxt) {
+ xmlParserCtxtPtr pctxt;
+
+ if (ctxt == NULL)
+ return(0);
+ /*
+ * These magic values are also abused to detect whether we're validating
+ * while parsing a document. In this case, userData points to the parser
+ * context.
+ */
+ if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) &&
+ (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1))
+ return(0);
+ pctxt = ctxt->userData;
+ return(pctxt->parseMode == XML_PARSE_READER);
+}
+
/**
* xmlFreeID:
* @not: A id
@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
if (doc == NULL) {
return(NULL);
}
- if (value == NULL) {
+ if ((value == NULL) || (value[0] == 0)) {
return(NULL);
}
if (attr == NULL) {
@@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
*/
ret->value = xmlStrdup(value);
ret->doc = doc;
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
+ if (xmlIsStreaming(ctxt)) {
/*
* Operating in streaming mode, attr is gonna disappear
*/
@@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
ID = xmlNodeListGetString(doc, attr->children, 1);
if (ID == NULL)
return(-1);
+ xmlValidNormalizeString(ID);
id = xmlHashLookup(table, ID);
if (id == NULL || id->attr != attr) {
@@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
* fill the structure.
*/
ret->value = xmlStrdup(value);
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
+ if (xmlIsStreaming(ctxt)) {
/*
* Operating in streaming mode, attr is gonna disappear
*/
@@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlChar *
xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
- xmlChar *ret, *dst;
- const xmlChar *src;
+ xmlChar *ret;
xmlAttributePtr attrDecl = NULL;
int extsubset = 0;
@@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
ret = xmlStrdup(value);
if (ret == NULL)
return(NULL);
- src = value;
- dst = ret;
- while (*src == 0x20) src++;
- while (*src != 0) {
- if (*src == 0x20) {
- while (*src == 0x20) src++;
- if (*src != 0)
- *dst++ = 0x20;
- } else {
- *dst++ = *src++;
- }
- }
- *dst = 0;
+ xmlValidNormalizeString(ret);
if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
"standalone: %s on %s value had to be normalized based on external subset declaration\n",
@@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlChar *
xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
const xmlChar *name, const xmlChar *value) {
- xmlChar *ret, *dst;
- const xmlChar *src;
+ xmlChar *ret;
xmlAttributePtr attrDecl = NULL;
if (doc == NULL) return(NULL);
@@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
ret = xmlStrdup(value);
if (ret == NULL)
return(NULL);
- src = value;
- dst = ret;
- while (*src == 0x20) src++;
- while (*src != 0) {
- if (*src == 0x20) {
- while (*src == 0x20) src++;
- if (*src != 0)
- *dst++ = 0x20;
- } else {
- *dst++ = *src++;
- }
- }
- *dst = 0;
+ xmlValidNormalizeString(ret);
return(ret);
}
--
1.8.3.1

View File

@ -1,341 +0,0 @@
From 2554a2408e09f13652049e5ffb0d26196b02ebab Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 8 Mar 2022 20:10:02 +0100
Subject: [PATCH] [CVE-2022-29824] Fix integer overflows in xmlBuf and
xmlBuffer
In several places, the code handling string buffers didn't check for
integer overflow or used wrong types for buffer sizes. This could
result in out-of-bounds writes or other memory errors when working on
large, multi-gigabyte buffers.
Thanks to Felix Wilhelm for the report.
---
buf.c | 86 +++++++++++++++++++++++-----------------------------------
tree.c | 72 ++++++++++++++++++------------------------------
2 files changed, 61 insertions(+), 97 deletions(-)
diff --git a/buf.c b/buf.c
index 24368d37..40a5ee06 100644
--- a/buf.c
+++ b/buf.c
@@ -30,6 +30,10 @@
#include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
#include "buf.h"
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
+
#define WITH_BUFFER_COMPAT
/**
@@ -156,6 +160,8 @@ xmlBufPtr
xmlBufCreateSize(size_t size) {
xmlBufPtr ret;
+ if (size == SIZE_MAX)
+ return(NULL);
ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
if (ret == NULL) {
xmlBufMemoryError(NULL, "creating buffer");
@@ -166,8 +172,8 @@ xmlBufCreateSize(size_t size) {
ret->error = 0;
ret->buffer = NULL;
ret->alloc = xmlBufferAllocScheme;
- ret->size = (size ? size+2 : 0); /* +1 for ending null */
- ret->compat_size = (int) ret->size;
+ ret->size = (size ? size + 1 : 0); /* +1 for ending null */
+ ret->compat_size = (ret->size > INT_MAX ? INT_MAX : ret->size);
if (ret->size){
ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
if (ret->content == NULL) {
@@ -442,23 +448,17 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
CHECK_COMPAT(buf)
if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
- if (buf->use + len < buf->size)
+ if (len < buf->size - buf->use)
return(buf->size - buf->use);
+ if (len > SIZE_MAX - buf->use)
+ return(0);
- /*
- * Windows has a BIG problem on realloc timing, so we try to double
- * the buffer size (if that's enough) (bug 146697)
- * Apparently BSD too, and it's probably best for linux too
- * On an embedded system this may be something to change
- */
-#if 1
- if (buf->size > (size_t) len)
- size = buf->size * 2;
- else
- size = buf->use + len + 100;
-#else
- size = buf->use + len + 100;
-#endif
+ if (buf->size > (size_t) len) {
+ size = buf->size > SIZE_MAX / 2 ? SIZE_MAX : buf->size * 2;
+ } else {
+ size = buf->use + len;
+ size = size > SIZE_MAX - 100 ? SIZE_MAX : size + 100;
+ }
if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
/*
@@ -744,7 +744,7 @@ xmlBufIsEmpty(const xmlBufPtr buf)
int
xmlBufResize(xmlBufPtr buf, size_t size)
{
- unsigned int newSize;
+ size_t newSize;
xmlChar* rebuf = NULL;
size_t start_buf;
@@ -772,9 +772,13 @@ xmlBufResize(xmlBufPtr buf, size_t size)
case XML_BUFFER_ALLOC_IO:
case XML_BUFFER_ALLOC_DOUBLEIT:
/*take care of empty case*/
- newSize = (buf->size ? buf->size*2 : size + 10);
+ if (buf->size == 0) {
+ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
+ } else {
+ newSize = buf->size;
+ }
while (size > newSize) {
- if (newSize > UINT_MAX / 2) {
+ if (newSize > SIZE_MAX / 2) {
xmlBufMemoryError(buf, "growing buffer");
return 0;
}
@@ -782,15 +786,15 @@ xmlBufResize(xmlBufPtr buf, size_t size)
}
break;
case XML_BUFFER_ALLOC_EXACT:
- newSize = size+10;
+ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
break;
case XML_BUFFER_ALLOC_HYBRID:
if (buf->use < BASE_BUFFER_SIZE)
newSize = size;
else {
- newSize = buf->size * 2;
+ newSize = buf->size;
while (size > newSize) {
- if (newSize > UINT_MAX / 2) {
+ if (newSize > SIZE_MAX / 2) {
xmlBufMemoryError(buf, "growing buffer");
return 0;
}
@@ -800,7 +804,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
break;
default:
- newSize = size+10;
+ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
break;
}
@@ -866,7 +870,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
*/
int
xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
- unsigned int needSize;
+ size_t needSize;
if ((str == NULL) || (buf == NULL) || (buf->error))
return -1;
@@ -888,8 +892,10 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
if (len < 0) return -1;
if (len == 0) return 0;
- needSize = buf->use + len + 2;
- if (needSize > buf->size){
+ if ((size_t) len >= buf->size - buf->use) {
+ if ((size_t) len >= SIZE_MAX - buf->use)
+ return(-1);
+ needSize = buf->use + len + 1;
if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
/*
* Used to provide parsing limits
@@ -1025,31 +1031,7 @@ xmlBufCat(xmlBufPtr buf, const xmlChar *str) {
*/
int
xmlBufCCat(xmlBufPtr buf, const char *str) {
- const char *cur;
-
- if ((buf == NULL) || (buf->error))
- return(-1);
- CHECK_COMPAT(buf)
- if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
- if (str == NULL) {
-#ifdef DEBUG_BUFFER
- xmlGenericError(xmlGenericErrorContext,
- "xmlBufCCat: str == NULL\n");
-#endif
- return -1;
- }
- for (cur = str;*cur != 0;cur++) {
- if (buf->use + 10 >= buf->size) {
- if (!xmlBufResize(buf, buf->use+10)){
- xmlBufMemoryError(buf, "growing buffer");
- return XML_ERR_NO_MEMORY;
- }
- }
- buf->content[buf->use++] = *cur;
- }
- buf->content[buf->use] = 0;
- UPDATE_COMPAT(buf)
- return 0;
+ return xmlBufCat(buf, (const xmlChar *) str);
}
/**
diff --git a/tree.c b/tree.c
index 9d94aa42..86afb7d6 100644
--- a/tree.c
+++ b/tree.c
@@ -7104,6 +7104,8 @@ xmlBufferPtr
xmlBufferCreateSize(size_t size) {
xmlBufferPtr ret;
+ if (size >= UINT_MAX)
+ return(NULL);
ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
if (ret == NULL) {
xmlTreeErrMemory("creating buffer");
@@ -7111,7 +7113,7 @@ xmlBufferCreateSize(size_t size) {
}
ret->use = 0;
ret->alloc = xmlBufferAllocScheme;
- ret->size = (size ? size+2 : 0); /* +1 for ending null */
+ ret->size = (size ? size + 1 : 0); /* +1 for ending null */
if (ret->size){
ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
if (ret->content == NULL) {
@@ -7171,6 +7173,8 @@ xmlBufferCreateStatic(void *mem, size_t size) {
if ((mem == NULL) || (size == 0))
return(NULL);
+ if (size > UINT_MAX)
+ return(NULL);
ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
if (ret == NULL) {
@@ -7318,28 +7322,23 @@ xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
*/
int
xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
- int size;
+ unsigned int size;
xmlChar *newbuf;
if (buf == NULL) return(-1);
if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
- if (len + buf->use < buf->size) return(0);
+ if (len < buf->size - buf->use)
+ return(0);
+ if (len > UINT_MAX - buf->use)
+ return(-1);
- /*
- * Windows has a BIG problem on realloc timing, so we try to double
- * the buffer size (if that's enough) (bug 146697)
- * Apparently BSD too, and it's probably best for linux too
- * On an embedded system this may be something to change
- */
-#if 1
- if (buf->size > len)
- size = buf->size * 2;
- else
- size = buf->use + len + 100;
-#else
- size = buf->use + len + 100;
-#endif
+ if (buf->size > (size_t) len) {
+ size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;
+ } else {
+ size = buf->use + len;
+ size = size > UINT_MAX - 100 ? UINT_MAX : size + 100;
+ }
if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
size_t start_buf = buf->content - buf->contentIO;
@@ -7466,7 +7465,10 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
case XML_BUFFER_ALLOC_IO:
case XML_BUFFER_ALLOC_DOUBLEIT:
/*take care of empty case*/
- newSize = (buf->size ? buf->size : size + 10);
+ if (buf->size == 0)
+ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
+ else
+ newSize = buf->size;
while (size > newSize) {
if (newSize > UINT_MAX / 2) {
xmlTreeErrMemory("growing buffer");
@@ -7476,7 +7478,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
}
break;
case XML_BUFFER_ALLOC_EXACT:
- newSize = size+10;
+ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);;
break;
case XML_BUFFER_ALLOC_HYBRID:
if (buf->use < BASE_BUFFER_SIZE)
@@ -7494,7 +7496,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
break;
default:
- newSize = size+10;
+ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);;
break;
}
@@ -7580,8 +7582,10 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
if (len < 0) return -1;
if (len == 0) return 0;
- needSize = buf->use + len + 2;
- if (needSize > buf->size){
+ if ((unsigned) len >= buf->size - buf->use) {
+ if ((unsigned) len >= UINT_MAX - buf->use)
+ return XML_ERR_NO_MEMORY;
+ needSize = buf->use + len + 1;
if (!xmlBufferResize(buf, needSize)){
xmlTreeErrMemory("growing buffer");
return XML_ERR_NO_MEMORY;
@@ -7694,29 +7698,7 @@ xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
*/
int
xmlBufferCCat(xmlBufferPtr buf, const char *str) {
- const char *cur;
-
- if (buf == NULL)
- return(-1);
- if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
- if (str == NULL) {
-#ifdef DEBUG_BUFFER
- xmlGenericError(xmlGenericErrorContext,
- "xmlBufferCCat: str == NULL\n");
-#endif
- return -1;
- }
- for (cur = str;*cur != 0;cur++) {
- if (buf->use + 10 >= buf->size) {
- if (!xmlBufferResize(buf, buf->use+10)){
- xmlTreeErrMemory("growing buffer");
- return XML_ERR_NO_MEMORY;
- }
- }
- buf->content[buf->use++] = *cur;
- }
- buf->content[buf->use] = 0;
- return 0;
+ return xmlBufferCat(buf, (const xmlChar *) str);
}
/**
--
GitLab

Binary file not shown.

BIN
libxml2-2.9.14.tar.xz Normal file

Binary file not shown.

View File

@ -1,25 +1,15 @@
Summary: Library providing XML and HTML support Summary: Library providing XML and HTML support
Name: libxml2 Name: libxml2
Version: 2.9.12 Version: 2.9.14
Release: 8 Release: 1
License: MIT License: MIT
Group: Development/Libraries Group: Development/Libraries
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz Source: https://download.gnome.org/sources/%{name}/2.9/%{name}-%{version}.tar.xz
Patch0: libxml2-multilib.patch Patch0: libxml2-multilib.patch
Patch1: Fix-XPath-recursion-limit.patch Patch1: Fix-memleaks-in-xmlXIncludeProcessFlags.patch
Patch2: Fix-Null-deref-in-xmlSchemaGetComponentTargetNs.patch Patch2: Fix-memory-leaks-for-xmlACatalogAdd.patch
Patch3: Fix-memleaks-in-xmlXIncludeProcessFlags.patch Patch3: Fix-memory-leaks-in-xmlACatalogAdd-when-xmlHashAddEntry-failed.patch
Patch4: xmlAddChild-and-xmlAddNextSibling-may-not-attach-the.patch
Patch5: Work-around-lxml-API-abuse.patch
Patch6: Fix-regression-in-xmlNodeDumpOutputInternal.patch
Patch7: Fix-whitespace-when-serializing-empty-HTML-documents.patch
Patch8: Patch-to-forbid-epsilon-reduction-of-final-states.patch
Patch9: Fix-buffering-in-xmlOutputBufferWrite.patch
Patch10:backport-CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch
Patch11:backport-CVE-2022-29824-Fix-integer-overflows-in-xmlBuf-and-xmlBuffer.patch
Patch12:Fix-memory-leaks-for-xmlACatalogAdd.patch
Patch13:Fix-memory-leaks-in-xmlACatalogAdd-when-xmlHashAddEntry-failed.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-root BuildRoot: %{_tmppath}/%{name}-%{version}-root
BuildRequires: python3-devel BuildRequires: python3-devel
@ -102,14 +92,9 @@ sed -i 's|#!/usr/bin/python |#!%{__python3} |' py3doc/*.py
find doc -type f -exec chmod 0644 \{\} \; find doc -type f -exec chmod 0644 \{\} \;
%install %install
%make_install
make clean
# for python3
%configure --with-python=%{__python3} %configure --with-python=%{__python3}
%make_install %make_install
rm -f $RPM_BUILD_ROOT%{_libdir}/*.la rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.a rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.a
rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.la rm -f $RPM_BUILD_ROOT%{_libdir}/python*/site-packages/*.la
@ -131,7 +116,7 @@ rm -fr %{buildroot}
%files %files
%defattr(-, root, root) %defattr(-, root, root)
%doc AUTHORS NEWS README Copyright TODO %doc %{_datadir}/doc/libxml2
%{_libdir}/lib*.so.* %{_libdir}/lib*.so.*
%{_bindir}/xmllint %{_bindir}/xmllint
@ -140,12 +125,12 @@ rm -fr %{buildroot}
%files devel %files devel
%defattr(-, root, root) %defattr(-, root, root)
%doc AUTHORS NEWS README Copyright %doc NEWS README.md Copyright
%doc doc/*.html doc/html doc/*.gif doc/*.png %doc doc/*.html doc/html doc/*.gif doc/*.png
%doc doc/tutorial doc/libxml2-api.xml.gz %doc doc/tutorial doc/libxml2-api.xml.gz
%doc doc/examples %doc doc/examples
%doc %dir %{_datadir}/gtk-doc/html/libxml2 %doc %dir %{_datadir}/gtk-doc/html/libxml2
%doc %{_datadir}/gtk-doc/html/libxml2/*.devhelp %doc %{_datadir}/gtk-doc/html/libxml2/*.devhelp2
%doc %{_datadir}/gtk-doc/html/libxml2/*.html %doc %{_datadir}/gtk-doc/html/libxml2/*.html
%doc %{_datadir}/gtk-doc/html/libxml2/*.png %doc %{_datadir}/gtk-doc/html/libxml2/*.png
%doc %{_datadir}/gtk-doc/html/libxml2/*.css %doc %{_datadir}/gtk-doc/html/libxml2/*.css
@ -180,6 +165,12 @@ rm -fr %{buildroot}
%changelog %changelog
* Wed Jul 13 2022 fuanan <fuanan3@h-partners.com> - 2.9.14-1
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:Upgrade to upstream v2.9.14 and Cleanup duplicate installation
* Fri Jun 24 2022 fuanan <fuanan3@h-partners.com> - 2.9.12-8 * Fri Jun 24 2022 fuanan <fuanan3@h-partners.com> - 2.9.12-8
- Type:bugfix - Type:bugfix
- ID:NA - ID:NA

View File

@ -1,104 +0,0 @@
From 8f5ccada05ddd4a1ff8e399ad39fc7cd4bd33325 Mon Sep 17 00:00:00 2001
From: David Kilzer <ddkilzer@apple.com>
Date: Wed, 7 Jul 2021 19:24:36 -0700
Subject: [PATCH] xmlAddChild() and xmlAddNextSibling() may not attach their
second argument
Use the return value of xmlAddChild() and xmlAddNextSibling()
instead of the second argument directly.
Found by OSS-Fuzz.
Fixes #316
---
xinclude.c | 14 ++++++--------
xpointer.c | 13 ++++++-------
2 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/xinclude.c b/xinclude.c
index b2e6ea1..2a0614d 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -1014,15 +1014,15 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
if (list == NULL) {
list = tmp;
listParent = cur->parent;
+ last = tmp;
} else {
if (level == lastLevel)
- xmlAddNextSibling(last, tmp);
+ last = xmlAddNextSibling(last, tmp);
else {
- xmlAddChild(last, tmp);
+ last = xmlAddChild(last, tmp);
lastLevel = level;
}
}
- last = tmp;
if (index2 > 1) {
end = xmlXIncludeGetNthChild(cur, index2 - 1);
@@ -1103,12 +1103,11 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
}
if (tmp != NULL) {
if (level == lastLevel)
- xmlAddNextSibling(last, tmp);
+ last = xmlAddNextSibling(last, tmp);
else {
- xmlAddChild(last, tmp);
+ last = xmlAddChild(last, tmp);
lastLevel = level;
}
- last = tmp;
}
}
/*
@@ -1186,8 +1185,7 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
if (last == NULL) {
list = last = tmp;
} else {
- xmlAddNextSibling(last, tmp);
- last = tmp;
+ last = xmlAddNextSibling(last, tmp);
}
cur = cur->next;
continue;
diff --git a/xpointer.c b/xpointer.c
index 27a6a8c..fe2fca5 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -1483,16 +1483,16 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
return(list);
} else {
tmp = xmlCopyNode(cur, 0);
- if (list == NULL)
+ if (list == NULL) {
list = tmp;
- else {
+ parent = tmp;
+ } else {
if (last != NULL)
- xmlAddNextSibling(last, tmp);
+ parent = xmlAddNextSibling(last, tmp);
else
- xmlAddChild(parent, tmp);
+ parent = xmlAddChild(parent, tmp);
}
last = NULL;
- parent = tmp;
if (index2 > 1) {
end = xmlXPtrGetNthChild(cur, index2 - 1);
@@ -1574,8 +1574,7 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
if (last != NULL)
xmlAddNextSibling(last, tmp);
else {
- xmlAddChild(parent, tmp);
- last = tmp;
+ last = xmlAddChild(parent, tmp);
}
}
}
--
1.8.3.1