Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Prevent an infinite loop when dumping a node with encoding problems

When a node is dumped with a new encoding, we may encounter characters
that are not supported in the new encoding. libxml2 handles this by
replacing the character with character references, but in some encodings
this can result in an infinite loop when the character references
themselves contain unsupported characters.

This fixes the infinite loop by undoing a character reference substitution
when it cannot be inserted, and returning an encoder error.

This bug was noticed when looking into an infinite loop bug report for
the Ruby Nokogiri project. The original bug report, "nokogiri process
hangs on call to inner_html" is here:
https://github.com/tenderlove/nokogiri/issues/400
  • Loading branch information...
commit 689408bd86227c33b1d93aab478d735effe8af6b 1 parent 8658d27
@ender672 ender672 authored veillard committed
Showing with 18 additions and 2 deletions.
  1. +18 −2 encoding.c
View
20 encoding.c
@@ -2161,6 +2161,7 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
int writtentot = 0;
int toconv;
int output = 0;
+ int charref_len = 0;
if (handler == NULL) return(-1);
if (out == NULL) return(-1);
@@ -2242,6 +2243,7 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
/*
* Can be a limitation of iconv
*/
+ charref_len = 0;
goto retry;
}
ret = -3;
@@ -2262,6 +2264,7 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
/*
* Can be a limitation of iconv
*/
+ charref_len = 0;
goto retry;
}
ret = -3;
@@ -2305,7 +2308,19 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
int cur;
cur = xmlGetUTF8Char(utf, &len);
- if (cur > 0) {
+ if ((charref_len != 0) && (written < charref_len)) {
+ /*
+ * We attempted to insert a character reference and failed.
+ * Undo what was written and skip the remaining charref.
+ */
+ out->use -= written;
+ writtentot -= written;
+ xmlBufferShrink(in, charref_len - written);
+ charref_len = 0;
+
+ ret = -1;
+ break;
+ } else if (cur > 0) {
xmlChar charref[20];
#ifdef DEBUG_ENCODING
@@ -2321,7 +2336,8 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
* and continue the transcoding phase, hoping the error
* did not mangle the encoder state.
*/
- snprintf((char *) &charref[0], sizeof(charref), "&#%d;", cur);
+ charref_len = snprintf((char *) &charref[0], sizeof(charref),
+ "&#%d;", cur);
xmlBufferShrink(in, len);
xmlBufferAddHead(in, charref, -1);
Please sign in to comment.
Something went wrong with that request. Please try again.