[xml] RFC: bug#769658 infinite loop in xmlParseConditionalSections



Hello,

I'm wondering if following xml can *really* creates infinite loop,
because it includes %zz entry over and over.

$ LD_PRELOAD=./.libs/libxml2.so  ./.libs/xmllint --huge --recover ./crash.xml
----<8----<8----<8----<8----<8----<8----<8----<8----<8
<?m?>
<!DOCTYPE[
  <!ELEMENT
  <!ENTITY %xx '<![INCLUDE[&#37;zz;'>
  <!ENTITY %zz '<![INCLUDE[&#37;zz;'>
  <!ENTITY z''>
%xx;
----<8----<8----<8----<8----<8----<8----<8----<8----<8

xmlParseConditionalSections
   ...
   if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
        ...
        printf("before NEXT '%s'\n", CUR_PTR);
        NEXT;
        printf("after NEXT '%s'\n", CUR_PTR);
    }
    while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
        (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {

         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
                xmlParseConditionalSections(ctxt);
                  ^^^^^^
              recursion loop

and the output is

    before NEXT '[%zz;'
    after NEXT '<![INCLUDE[%zz;'

that means, that xmlNextChar() with CUR_PTR containing '[%zz;'
expands again to '<![INCLUDE[%zz;', hence it creates infinite recursion
loop, which later leads to stack overflow.

Does parser parse xml correctly and it's really possible to create infinite
recursion?

Since my xml-fu is not very good, I have come up with recursion cap,
because I have seen it on other places.

I wasn't sure, if I can use ctxt->depth, so I did it bit differently.

----<8----<8----<8----<8----<8----<8----<8----<8----<8
diff --git a/parser.c b/parser.c
index 53a6b7f0c961..ee2d3c3d4053 100644
--- a/parser.c
+++ b/parser.c
@@ -6813,9 +6813,17 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
  */
 
 static void
-xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
+xmlParseConditionalSections(xmlParserCtxtPtr ctxt, int recurse_depth) {
     int id = ctxt->input->id;
 
+    if (((recurse_depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
+        (recurse_depth >  2048)) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
+"xmlParseConditionalSections : depth %d too deep, use XML_PARSE_HUGE\n",
+                          recurse_depth);
+       return;
+    }
+
     SKIP(3);
     SKIP_BLANKS;
     if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
@@ -6848,7 +6856,7 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
            unsigned int cons = ctxt->input->consumed;
 
            if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
-               xmlParseConditionalSections(ctxt);
+               xmlParseConditionalSections(ctxt, recurse_depth + 1);
            } else if (IS_BLANK_CH(CUR)) {
                NEXT;
            } else if (RAW == '%') {
@@ -7036,7 +7044,7 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
      */
     if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
-           xmlParseConditionalSections(ctxt);
+           xmlParseConditionalSections(ctxt, 0);
        }
     }
 
@@ -7179,7 +7187,7 @@ xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
 
        GROW;
         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
-           xmlParseConditionalSections(ctxt);
+           xmlParseConditionalSections(ctxt, 0);
        } else if (IS_BLANK_CH(CUR)) {
            NEXT;
        } else if (RAW == '%') {
-- 
Nikola


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]