Bump to libxml2 2.9.4
[platform/upstream/libxml2.git] / parser.c
index ee429f3..53a6b7f 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -94,6 +94,8 @@ static xmlParserCtxtPtr
 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
                          const xmlChar *base, xmlParserCtxtPtr pctx);
 
+static void xmlHaltParser(xmlParserCtxtPtr ctxt);
+
 /************************************************************************
  *                                                                     *
  *     Arbitrary limits set in the parser. See XML_PARSE_HUGE          *
@@ -130,6 +132,35 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
         return (0);
     if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
         return (1);
+
+    /*
+     * This may look absurd but is needed to detect
+     * entities problems
+     */
+    if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
+       (ent->content != NULL) && (ent->checked == 0) &&
+       (ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
+       unsigned long oldnbent = ctxt->nbentities;
+       xmlChar *rep;
+
+       ent->checked = 1;
+
+        ++ctxt->depth;
+       rep = xmlStringDecodeEntities(ctxt, ent->content,
+                                 XML_SUBSTITUTE_REF, 0, 0, 0);
+        --ctxt->depth;
+       if (ctxt->errNo == XML_ERR_ENTITY_LOOP) {
+           ent->content[0] = 0;
+       }
+
+       ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
+       if (rep != NULL) {
+           if (xmlStrchr(rep, '<'))
+               ent->checked |= 1;
+           xmlFree(rep);
+           rep = NULL;
+       }
+    }
     if (replacement != 0) {
        if (replacement < XML_MAX_TEXT_LENGTH)
            return(0);
@@ -189,9 +220,12 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
             return (0);
     } else {
         /*
-         * strange we got no data for checking just return
+         * strange we got no data for checking
          */
-        return (0);
+       if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
+            (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
+           (ctxt->nbentities <= 10000))
+           return (0);
     }
     xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
     return (1);
@@ -316,7 +350,6 @@ static void
 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
 {
     const char *errmsg;
-    char errstr[129] = "";
 
     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
         (ctxt->instate == XML_PARSER_EOF))
@@ -503,15 +536,17 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
         default:
             errmsg = "Unregistered error message";
     }
-    if (info == NULL)
-        snprintf(errstr, 128, "%s\n", errmsg);
-    else
-        snprintf(errstr, 128, "%s: %%s\n", errmsg);
     if (ctxt != NULL)
        ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
-                    info);
+    if (info == NULL) {
+        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
+                        errmsg);
+    } else {
+        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
+                        errmsg, info);
+    }
     if (ctxt != NULL) {
        ctxt->wellFormed = 0;
        if (ctxt->recovery == 0)
@@ -527,7 +562,7 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                const char *msg)
 {
@@ -555,7 +590,7 @@ xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a warning.
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
@@ -593,7 +628,7 @@ xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a validity error.
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
@@ -633,7 +668,7 @@ xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, int val)
 {
@@ -663,7 +698,7 @@ xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar *str1, int val,
                  const xmlChar *str2)
@@ -693,7 +728,7 @@ xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
@@ -722,7 +757,7 @@ xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a non fatal parser error
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
@@ -747,7 +782,7 @@ xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const char *msg,
          const xmlChar * info1, const xmlChar * info2,
@@ -776,7 +811,7 @@ xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
  *
  * Handle a namespace warning error
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const char *msg,
          const xmlChar * info1, const xmlChar * info2,
@@ -1745,7 +1780,7 @@ nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
                 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
                          xmlParserMaxDepth);
-       ctxt->instate = XML_PARSER_EOF;
+       xmlHaltParser(ctxt);
        return(-1);
     }
     ctxt->nodeTab[ctxt->nodeNr] = value;
@@ -1980,6 +2015,7 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
 #define CUR (*ctxt->input->cur)
 #define NXT(val) ctxt->input->cur[(val)]
 #define CUR_PTR ctxt->input->cur
+#define BASE_PTR ctxt->input->base
 
 #define CMP4( s, c1, c2, c3, c4 ) \
   ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
@@ -2039,14 +2075,24 @@ static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
        xmlGROW (ctxt);
 
 static void xmlGROW (xmlParserCtxtPtr ctxt) {
-    if ((((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
-         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
+    unsigned long curEnd = ctxt->input->end - ctxt->input->cur;
+    unsigned long curBase = ctxt->input->cur - ctxt->input->base;
+
+    if (((curEnd > (unsigned long) XML_MAX_LOOKUP_LIMIT) ||
+         (curBase > (unsigned long) XML_MAX_LOOKUP_LIMIT)) &&
          ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) &&
         ((ctxt->options & XML_PARSE_HUGE) == 0)) {
         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
-        ctxt->instate = XML_PARSER_EOF;
+        xmlHaltParser(ctxt);
+       return;
     }
     xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+    if ((ctxt->input->cur > ctxt->input->end) ||
+        (ctxt->input->cur < ctxt->input->base)) {
+        xmlHaltParser(ctxt);
+        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
+       return;
+    }
     if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
            xmlPopInput(ctxt);
@@ -2106,6 +2152,8 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
        while (IS_BLANK_CH(*cur)) {
            if (*cur == '\n') {
                ctxt->input->line++; ctxt->input->col = 1;
+           } else {
+               ctxt->input->col++;
            }
            cur++;
            res++;
@@ -2120,7 +2168,8 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
        int cur;
        do {
            cur = CUR;
-           while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
+           while ((IS_BLANK_CH(cur) && /* CHECKED tstblanks.xml */
+                  (ctxt->instate != XML_PARSER_EOF))) {
                NEXT;
                cur = CUR;
                res++;
@@ -2134,7 +2183,8 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
             * Need to handle support of entities branching here
             */
            if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
-       } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
+       } while ((IS_BLANK(cur)) && /* CHECKED tstblanks.xml */
+                (ctxt->instate != XML_PARSER_EOF));
     }
     return(res);
 }
@@ -2584,6 +2634,7 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
                                      name, NULL);
                    ctxt->valid = 0;
                }
+               xmlParserEntityCheck(ctxt, 0, NULL, 0);
            } else if (ctxt->input->free != deallocblankswrapper) {
                    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
                    if (xmlPushInput(ctxt, input) < 0)
@@ -2595,6 +2646,23 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
                    xmlCharEncoding enc;
 
                    /*
+                    * Note: external parameter entities will not be loaded, it
+                    * is not required for a non-validating parser, unless the
+                    * option of validating, or substituting entities were
+                    * given. Doing so is far more secure as the parser will
+                    * only process data coming from the document entity by
+                    * default.
+                    */
+                    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
+                       ((ctxt->options & XML_PARSE_NOENT) == 0) &&
+                       ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
+                       ((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
+                       ((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
+                       (ctxt->replaceEntities == 0) &&
+                       (ctxt->validate == 0))
+                       return;
+
+                   /*
                     * handle the extra spaces added before and after
                     * c.f. http://www.w3.org/TR/REC-xml#as-PE
                     * this is done independently.
@@ -2737,6 +2805,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
            if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
                (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
                goto int_error;
+           xmlParserEntityCheck(ctxt, 0, ent, 0);
            if (ent != NULL)
                ctxt->nbentities += ent->checked / 2;
            if ((ent != NULL) &&
@@ -2756,6 +2825,10 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
                                              0, 0, 0);
                ctxt->depth--;
 
+               if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
+                   (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
+                   goto int_error;
+
                if (rep != NULL) {
                    current = rep;
                    while (*current != 0) { /* non input consuming loop */
@@ -2788,11 +2861,26 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
            ent = xmlParseStringPEReference(ctxt, &str);
            if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
                goto int_error;
+           xmlParserEntityCheck(ctxt, 0, ent, 0);
            if (ent != NULL)
                ctxt->nbentities += ent->checked / 2;
            if (ent != NULL) {
                 if (ent->content == NULL) {
-                   xmlLoadEntityContent(ctxt, ent);
+                   /*
+                    * Note: external parsed entities will not be loaded,
+                    * it is not required for a non-validating parser to
+                    * complete external PEreferences coming from the
+                    * internal subset
+                    */
+                   if (((ctxt->options & XML_PARSE_NOENT) != 0) ||
+                       ((ctxt->options & XML_PARSE_DTDVALID) != 0) ||
+                       (ctxt->validate != 0)) {
+                       xmlLoadEntityContent(ctxt, ent);
+                   } else {
+                       xmlWarningMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
+                 "not validating will not read content for PE entity %s\n",
+                                     ent->name, NULL);
+                   }
                }
                ctxt->depth++;
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
@@ -3404,6 +3492,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
     int len = 0, l;
     int c;
     int count = 0;
+    size_t startPosition = 0;
 
 #ifdef DEBUG
     nbParseNCNameComplex++;
@@ -3413,6 +3502,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
      * Handler for more complex cases
      */
     GROW;
+    startPosition = CUR_PTR - BASE_PTR;
     c = CUR_CHAR(l);
     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
        (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
@@ -3437,7 +3527,14 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
        c = CUR_CHAR(l);
        if (c == 0) {
            count = 0;
+           /*
+            * when shrinking to extend the buffer we really need to preserve
+            * the part of the name we already parsed. Hence rolling back
+            * by current lenght.
+            */
+           ctxt->input->cur -= l;
            GROW;
+           ctxt->input->cur += l;
             if (ctxt->instate == XML_PARSER_EOF)
                 return(NULL);
            c = CUR_CHAR(l);
@@ -3448,7 +3545,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
         return(NULL);
     }
-    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
+    return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len));
 }
 
 /**
@@ -3468,7 +3565,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
 
 static const xmlChar *
 xmlParseNCName(xmlParserCtxtPtr ctxt) {
-    const xmlChar *in;
+    const xmlChar *in, *e;
     const xmlChar *ret;
     int count = 0;
 
@@ -3480,16 +3577,19 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
      * Accelerator for simple ASCII names
      */
     in = ctxt->input->cur;
-    if (((*in >= 0x61) && (*in <= 0x7A)) ||
-       ((*in >= 0x41) && (*in <= 0x5A)) ||
-       (*in == '_')) {
+    e = ctxt->input->end;
+    if ((((*in >= 0x61) && (*in <= 0x7A)) ||
+        ((*in >= 0x41) && (*in <= 0x5A)) ||
+        (*in == '_')) && (in < e)) {
        in++;
-       while (((*in >= 0x61) && (*in <= 0x7A)) ||
-              ((*in >= 0x41) && (*in <= 0x5A)) ||
-              ((*in >= 0x30) && (*in <= 0x39)) ||
-              (*in == '_') || (*in == '-') ||
-              (*in == '.'))
+       while ((((*in >= 0x61) && (*in <= 0x7A)) ||
+               ((*in >= 0x41) && (*in <= 0x5A)) ||
+               ((*in >= 0x30) && (*in <= 0x39)) ||
+               (*in == '_') || (*in == '-') ||
+               (*in == '.')) && (in < e))
            in++;
+       if (in >= e)
+           goto complex;
        if ((*in > 0) && (*in < 0x80)) {
            count = in - ctxt->input->cur;
             if ((count > XML_MAX_NAME_LENGTH) &&
@@ -3507,6 +3607,7 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
            return(ret);
        }
     }
+complex:
     return(xmlParseNCNameComplex(ctxt));
 }
 
@@ -3544,7 +3645,7 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
     }
     /* failure (or end of input buffer), check with full function */
     ret = xmlParseName (ctxt);
-    /* strings coming from the dictionnary direct compare possible */
+    /* strings coming from the dictionary direct compare possible */
     if (ret == other) {
        return (const xmlChar*) 1;
     }
@@ -3885,8 +3986,10 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
         * an entity declaration, it is bypassed and left as is.
         * so XML_SUBSTITUTE_REF is not set here.
         */
+        ++ctxt->depth;
        ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
                                      0, 0, 0);
+        --ctxt->depth;
        if (orig != NULL)
            *orig = buf;
        else
@@ -4011,9 +4114,11 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
                } else if ((ent != NULL) &&
                           (ctxt->replaceEntities != 0)) {
                    if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
+                       ++ctxt->depth;
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
                                                      XML_SUBSTITUTE_REF,
                                                      0, 0, 0);
+                       --ctxt->depth;
                        if (rep != NULL) {
                            current = rep;
                            while (*current != 0) { /* non input consuming */
@@ -4049,8 +4154,10 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
                        (ent->content != NULL) && (ent->checked == 0)) {
                        unsigned long oldnbent = ctxt->nbentities;
 
+                       ++ctxt->depth;
                        rep = xmlStringDecodeEntities(ctxt, ent->content,
                                                  XML_SUBSTITUTE_REF, 0, 0, 0);
+                       --ctxt->depth;
 
                        ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
                        if (rep != NULL) {
@@ -5075,7 +5182,7 @@ xmlParsePITarget(xmlParserCtxtPtr ctxt) {
     }
     if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
        xmlNsErr(ctxt, XML_NS_ERR_COLON,
-                "colon are forbidden from PI names '%s'\n", name, NULL, NULL);
+                "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
     }
     return(name);
 }
@@ -5344,7 +5451,7 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
        }
        if (xmlStrchr(name, ':') != NULL) {
            xmlNsErr(ctxt, XML_NS_ERR_COLON,
-                    "colon are forbidden from notation names '%s'\n",
+                    "colons are forbidden from notation names '%s'\n",
                     name, NULL, NULL);
        }
        SKIP_BLANKS;
@@ -5420,7 +5527,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
            skipped = SKIP_BLANKS;
            if (skipped == 0) {
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-                              "Space required after '%'\n");
+                              "Space required after '%%'\n");
            }
            isParameter = 1;
        }
@@ -5433,7 +5540,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
        }
        if (xmlStrchr(name, ':') != NULL) {
            xmlNsErr(ctxt, XML_NS_ERR_COLON,
-                    "colon are forbidden from entities names '%s'\n",
+                    "colons are forbidden from entities names '%s'\n",
                     name, NULL, NULL);
        }
         skipped = SKIP_BLANKS;
@@ -5603,6 +5710,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
        if (RAW != '>') {
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
                    "xmlParseEntityDecl: entity %s not terminated\n", name);
+           xmlHaltParser(ctxt);
        } else {
            if (input != ctxt->input) {
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
@@ -6604,6 +6712,7 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
        if (!IS_BLANK_CH(CUR)) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after 'ELEMENT'\n");
+           return(-1);
        }
         SKIP_BLANKS;
         name = xmlParseName(ctxt);
@@ -6714,6 +6823,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
        SKIP_BLANKS;
        if (RAW != '[') {
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+           xmlHaltParser(ctxt);
+           return;
        } else {
            if (ctxt->input->id != id) {
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
@@ -6753,6 +6864,7 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+               xmlHaltParser(ctxt);
                break;
            }
        }
@@ -6774,6 +6886,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
        SKIP_BLANKS;
        if (RAW != '[') {
            xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+           xmlHaltParser(ctxt);
+           return;
        } else {
            if (ctxt->input->id != id) {
                xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
@@ -6829,6 +6943,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
     } else {
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
+       xmlHaltParser(ctxt);
+       return;
     }
 
     if (RAW == 0)
@@ -6842,7 +6958,9 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
        "All markup of the conditional section is not in the same entity\n",
                                 NULL, NULL);
        }
-        SKIP(3);
+       if ((ctxt-> instate != XML_PARSER_EOF) &&
+           ((ctxt->input->cur + 3) <= ctxt->input->end))
+           SKIP(3);
     }
 }
 
@@ -6897,6 +7015,14 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
            xmlParsePI(ctxt);
        }
     }
+
+    /*
+     * detect requirement to exit there and act accordingly
+     * and avoid having instate overriden later on
+     */
+    if (ctxt->instate == XML_PARSER_EOF)
+        return;
+
     /*
      * This is only for internal subset. On external entities,
      * the replacement is done before parsing stage
@@ -7028,7 +7154,7 @@ xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
            /*
             * The XML REC instructs us to stop parsing right here
             */
-           ctxt->instate = XML_PARSER_EOF;
+           xmlHaltParser(ctxt);
            return;
        }
     }
@@ -7180,7 +7306,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
      * far more secure as the parser will only process data coming from
      * the document entity by default.
      */
-    if ((ent->checked == 0) &&
+    if (((ent->checked == 0) ||
+         ((ent->children == NULL) && (ctxt->options & XML_PARSE_NOENT))) &&
         ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
          (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
        unsigned long oldnbent = ctxt->nbentities;
@@ -7286,6 +7413,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
                   (ret != XML_WAR_UNDECLARED_ENTITY)) {
            xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
                     "Entity '%s' failed to parse\n", ent->name);
+           xmlParserEntityCheck(ctxt, 0, ent, 0);
        } else if (list != NULL) {
            xmlFreeNodeList(list);
            list = NULL;
@@ -7392,7 +7520,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
                /*
                 * We are copying here, make sure there is no abuse
                 */
-               ctxt->sizeentcopy += ent->length;
+               ctxt->sizeentcopy += ent->length + 5;
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
                    return;
 
@@ -7440,7 +7568,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
                /*
                 * We are copying here, make sure there is no abuse
                 */
-               ctxt->sizeentcopy += ent->length;
+               ctxt->sizeentcopy += ent->length + 5;
                if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
                    return;
 
@@ -7626,6 +7754,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
                ctxt->sax->reference(ctxt->userData, name);
            }
        }
+       xmlParserEntityCheck(ctxt, 0, ent, 0);
        ctxt->valid = 0;
     }
 
@@ -7658,8 +7787,8 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
             (ent != NULL) && 
             (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
-       if ((ent->checked & 1) || ((ent->checked == 0) &&
-            (ent->content != NULL) &&(xmlStrchr(ent->content, '<')))) {
+       if (((ent->checked & 1) || (ent->checked == 0)) &&
+            (ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
            xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
        "'<' in entity '%s' is not allowed in attributes values\n", name);
         }
@@ -7753,7 +7882,7 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
 
 
     /*
-     * Predefined entites override any extra definition
+     * Predefined entities override any extra definition
      */
     if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
         ent = xmlGetPredefinedEntity(name);
@@ -7819,6 +7948,7 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
                          "Entity '%s' not defined\n",
                          name);
        }
+       xmlParserEntityCheck(ctxt, 0, ent, 0);
        /* TODO ? check regressions ctxt->valid = 0; */
     }
 
@@ -7978,6 +8108,7 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
                          name, NULL);
            ctxt->valid = 0;
        }
+       xmlParserEntityCheck(ctxt, 0, NULL, 0);
     } else {
        /*
         * Internal checking in case the entity quest barfed
@@ -8010,7 +8141,7 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
                     * The XML REC instructs us to stop parsing
                     * right here
                     */
-                   ctxt->instate = XML_PARSER_EOF;
+                   xmlHaltParser(ctxt);
                    return;
                }
            }
@@ -8217,6 +8348,7 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
                          name, NULL);
            ctxt->valid = 0;
        }
+       xmlParserEntityCheck(ctxt, 0, NULL, 0);
     } else {
        /*
         * Internal checking in case the entity quest barfed
@@ -8364,6 +8496,7 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
      */
     if (RAW != '>') {
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+       return;
     }
     NEXT;
 }
@@ -8714,7 +8847,7 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) {
  * @prefix:  the prefix to lookup
  *
  * Lookup the namespace name for the @prefix (which ca be NULL)
- * The prefix must come from the @ctxt->dict dictionnary
+ * The prefix must come from the @ctxt->dict dictionary
  *
  * Returns the namespace name or NULL if not bound
  */
@@ -8906,9 +9039,12 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
     xmlChar limit = 0;
     const xmlChar *in = NULL, *start, *end, *last;
     xmlChar *ret = NULL;
+    int line, col;
 
     GROW;
     in = (xmlChar *) CUR_PTR;
+    line = ctxt->input->line;
+    col = ctxt->input->col;
     if (*in != '"' && *in != '\'') {
         xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
         return (NULL);
@@ -8921,6 +9057,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
      * pure ASCII.
      */
     limit = *in++;
+    col++;
     end = ctxt->input->end;
     start = in;
     if (in >= end) {
@@ -8940,6 +9077,11 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
        while ((in < end) && (*in != limit) &&
               ((*in == 0x20) || (*in == 0x9) ||
                (*in == 0xA) || (*in == 0xD))) {
+           if (*in == 0xA) {
+               line++; col = 1;
+           } else {
+               col++;
+           }
            in++;
            start = in;
            if (in >= end) {
@@ -8963,6 +9105,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
        }
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
+           col++;
            if ((*in++ == 0x20) && (*in == 0x20)) break;
            if (in >= end) {
                const xmlChar *oldbase = ctxt->input->base;
@@ -8991,6 +9134,11 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
        while ((in < end) && (*in != limit) &&
               ((*in == 0x20) || (*in == 0x9) ||
                (*in == 0xA) || (*in == 0xD))) {
+           if (*in == 0xA) {
+               line++, col = 1;
+           } else {
+               col++;
+           }
            in++;
            if (in >= end) {
                const xmlChar *oldbase = ctxt->input->base;
@@ -9023,6 +9171,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
        while ((in < end) && (*in != limit) && (*in >= 0x20) &&
               (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
            in++;
+           col++;
            if (in >= end) {
                const xmlChar *oldbase = ctxt->input->base;
                GROW;
@@ -9052,6 +9201,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
        if (*in != limit) goto need_complex;
     }
     in++;
+    col++;
     if (len != NULL) {
         *len = last - start;
         ret = (xmlChar *) start;
@@ -9060,6 +9210,8 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
         ret = xmlStrndup(start, last - start);
     }
     CUR_PTR = in;
+    ctxt->input->line = line;
+    ctxt->input->col = col;
     if (alloc) *alloc = 0;
     return ret;
 need_complex:
@@ -9225,7 +9377,7 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
     const xmlChar **atts = ctxt->atts;
     int maxatts = ctxt->maxatts;
     int nratts, nbatts, nbdef;
-    int i, j, nbNs, attval, oldline, oldcol;
+    int i, j, nbNs, attval, oldline, oldcol, inputNr;
     const xmlChar *base;
     unsigned long cur;
     int nsNr = ctxt->nsNr;
@@ -9244,6 +9396,7 @@ reparse:
     SHRINK;
     base = ctxt->input->base;
     cur = ctxt->input->cur - ctxt->input->base;
+    inputNr = ctxt->inputNr;
     oldline = ctxt->input->line;
     oldcol = ctxt->input->col;
     nbatts = 0;
@@ -9269,7 +9422,8 @@ reparse:
      */
     SKIP_BLANKS;
     GROW;
-    if (ctxt->input->base != base) goto base_changed;
+    if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+        goto base_changed;
 
     while (((RAW != '>') &&
           ((RAW != '/') || (NXT(1) != '>')) &&
@@ -9280,7 +9434,7 @@ reparse:
 
        attname = xmlParseAttribute2(ctxt, prefix, localname,
                                     &aprefix, &attvalue, &len, &alloc);
-       if (ctxt->input->base != base) {
+       if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr)) {
            if ((attvalue != NULL) && (alloc != 0))
                xmlFree(attvalue);
            attvalue = NULL;
@@ -9292,6 +9446,12 @@ reparse:
                const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
                xmlURIPtr uri;
 
+                if (URL == NULL) {
+                   xmlErrMemory(ctxt, "dictionary allocation failure");
+                   if ((attvalue != NULL) && (alloc != 0))
+                       xmlFree(attvalue);
+                   return(NULL);
+               }
                 if (*URL != 0) {
                    uri = xmlParseURI((const char *) URL);
                    if (uri == NULL) {
@@ -9334,8 +9494,20 @@ reparse:
                else
                    if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
 skip_default_ns:
-               if (alloc != 0) xmlFree(attvalue);
+               if ((attvalue != NULL) && (alloc != 0)) {
+                   xmlFree(attvalue);
+                   attvalue = NULL;
+               }
+               if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+                   break;
+               if (!IS_BLANK_CH(RAW)) {
+                   xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+                                  "attributes construct error\n");
+                   break;
+               }
                SKIP_BLANKS;
+               if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+                   goto base_changed;
                continue;
            }
             if (aprefix == ctxt->str_xmlns) {
@@ -9407,9 +9579,20 @@ skip_default_ns:
                else
                    if (nsPush(ctxt, attname, URL) > 0) nbNs++;
 skip_ns:
-               if (alloc != 0) xmlFree(attvalue);
+               if ((attvalue != NULL) && (alloc != 0)) {
+                   xmlFree(attvalue);
+                   attvalue = NULL;
+               }
+               if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+                   break;
+               if (!IS_BLANK_CH(RAW)) {
+                   xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+                                  "attributes construct error\n");
+                   break;
+               }
                SKIP_BLANKS;
-               if (ctxt->input->base != base) goto base_changed;
+               if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+                   goto base_changed;
                continue;
            }
 
@@ -9446,7 +9629,8 @@ failed:
        GROW
         if (ctxt->instate == XML_PARSER_EOF)
             break;
-       if (ctxt->input->base != base) goto base_changed;
+       if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+           goto base_changed;
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
            break;
        if (!IS_BLANK_CH(RAW)) {
@@ -9462,7 +9646,8 @@ failed:
            break;
        }
         GROW;
-       if (ctxt->input->base != base) goto base_changed;
+       if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+           goto base_changed;
     }
 
     /*
@@ -9629,6 +9814,17 @@ base_changed:
            if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
                xmlFree((xmlChar *) atts[i]);
     }
+
+    /*
+     * We can't switch from one entity to another in the middle
+     * of a start tag
+     */
+    if (inputNr != ctxt->inputNr) {
+        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                   "Start tag doesn't start and stop in the same entity\n");
+       return(NULL);
+    }
+
     ctxt->input->cur = ctxt->input->base + cur;
     ctxt->input->line = oldline;
     ctxt->input->col = oldcol;
@@ -9657,6 +9853,7 @@ static void
 xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
                 const xmlChar *URI, int line, int nsNr, int tlen) {
     const xmlChar *name;
+    size_t curLength;
 
     GROW;
     if ((RAW != '<') || (NXT(1) != '/')) {
@@ -9665,12 +9862,17 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
     }
     SKIP(2);
 
-    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
-        if (ctxt->input->cur[tlen] == '>') {
+    curLength = ctxt->input->end - ctxt->input->cur;
+    if ((tlen > 0) && (curLength >= (size_t)tlen) &&
+        (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
+        if ((curLength >= (size_t)(tlen + 1)) &&
+           (ctxt->input->cur[tlen] == '>')) {
            ctxt->input->cur += tlen + 1;
+           ctxt->input->col += tlen + 1;
            goto done;
        }
        ctxt->input->cur += tlen;
+       ctxt->input->col += tlen;
        name = (xmlChar*)1;
     } else {
        if (prefix == NULL)
@@ -9908,7 +10110,7 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
        if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
                        "detected an error in element content\n");
-           ctxt->instate = XML_PARSER_EOF;
+           xmlHaltParser(ctxt);
             break;
        }
     }
@@ -9943,7 +10145,7 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
        xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
                 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
                          xmlParserMaxDepth);
-       ctxt->instate = XML_PARSER_EOF;
+       xmlHaltParser(ctxt);
        return;
     }
 
@@ -10295,6 +10497,8 @@ xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
            encoding = xmlParseEncName(ctxt);
            if (RAW != '"') {
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+               xmlFree((xmlChar *) encoding);
+               return(NULL);
            } else
                NEXT;
        } else if (RAW == '\''){
@@ -10302,6 +10506,8 @@ xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
            encoding = xmlParseEncName(ctxt);
            if (RAW != '\'') {
                xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+               xmlFree((xmlChar *) encoding);
+               return(NULL);
            } else
                NEXT;
        } else {
@@ -10311,8 +10517,10 @@ xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
         /*
          * Non standard parsing, allowing the user to ignore encoding
          */
-        if (ctxt->options & XML_PARSE_IGNORE_ENC)
-            return(encoding);
+        if (ctxt->options & XML_PARSE_IGNORE_ENC) {
+           xmlFree((xmlChar *) encoding);
+            return(NULL);
+       }
 
        /*
         * UTF-16 encoding stwich has already taken place at this stage,
@@ -10356,7 +10564,11 @@ xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
 
             handler = xmlFindCharEncodingHandler((const char *) encoding);
            if (handler != NULL) {
-               xmlSwitchToEncoding(ctxt, handler);
+               if (xmlSwitchToEncoding(ctxt, handler) < 0) {
+                   /* failed to convert */
+                   ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
+                   return(NULL);
+               }
            } else {
                xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
                        "Unsupported encoding %s\n", encoding);
@@ -10525,7 +10737,8 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
     }
     xmlParseEncodingDecl(ctxt);
-    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
+         (ctxt->instate == XML_PARSER_EOF)) {
        /*
         * The XML REC instructs us to stop parsing right here
         */
@@ -10649,6 +10862,7 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
 
     if (CUR == 0) {
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+       return(-1);
     }
 
     /*
@@ -10666,7 +10880,8 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
         * Note that we will switch encoding on the fly.
         */
        xmlParseXMLDecl(ctxt);
-       if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+       if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
+           (ctxt->instate == XML_PARSER_EOF)) {
            /*
             * The XML REC instructs us to stop parsing right here
             */
@@ -10681,6 +10896,10 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
         ctxt->sax->startDocument(ctxt->userData);
     if (ctxt->instate == XML_PARSER_EOF)
        return(-1);
+    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
+        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
+       ctxt->myDoc->compression = ctxt->input->buf->compressed;
+    }
 
     /*
      * The Misc part of the Prolog
@@ -11031,8 +11250,9 @@ xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
 }
 /**
  * xmlCheckCdataPush:
- * @cur: pointer to the bock of characters
+ * @cur: pointer to the block of characters
  * @len: length of the block in bytes
+ * @complete: 1 if complete CDATA block is passed in, 0 if partial block
  *
  * Check that the block of characters is okay as SCdata content [20]
  *
@@ -11040,7 +11260,7 @@ xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
  *         UTF-8 error occured otherwise
  */
 static int
-xmlCheckCdataPush(const xmlChar *utf, int len) {
+xmlCheckCdataPush(const xmlChar *utf, int len, int complete) {
     int ix;
     unsigned char c;
     int codepoint;
@@ -11058,7 +11278,7 @@ xmlCheckCdataPush(const xmlChar *utf, int len) {
            else
                return(-ix);
        } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
-           if (ix + 2 > len) return(ix);
+           if (ix + 2 > len) return(complete ? -ix : ix);
            if ((utf[ix+1] & 0xc0 ) != 0x80)
                return(-ix);
            codepoint = (utf[ix] & 0x1f) << 6;
@@ -11067,7 +11287,7 @@ xmlCheckCdataPush(const xmlChar *utf, int len) {
                return(-ix);
            ix += 2;
        } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
-           if (ix + 3 > len) return(ix);
+           if (ix + 3 > len) return(complete ? -ix : ix);
            if (((utf[ix+1] & 0xc0) != 0x80) ||
                ((utf[ix+2] & 0xc0) != 0x80))
                    return(-ix);
@@ -11078,7 +11298,7 @@ xmlCheckCdataPush(const xmlChar *utf, int len) {
                return(-ix);
            ix += 3;
        } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
-           if (ix + 4 > len) return(ix);
+           if (ix + 4 > len) return(complete ? -ix : ix);
            if (((utf[ix+1] & 0xc0) != 0x80) ||
                ((utf[ix+2] & 0xc0) != 0x80) ||
                ((utf[ix+3] & 0xc0) != 0x80))
@@ -11256,7 +11476,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                        ctxt->sax->setDocumentLocator(ctxt->userData,
                                                      &xmlDefaultSAXLocator);
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
-                   ctxt->instate = XML_PARSER_EOF;
+                   xmlHaltParser(ctxt);
 #ifdef DEBUG_PUSH
                    xmlGenericError(xmlGenericErrorContext,
                            "PP: entering EOF\n");
@@ -11289,7 +11509,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                             * The XML REC instructs us to stop parsing right
                             * here
                             */
-                           ctxt->instate = XML_PARSER_EOF;
+                           xmlHaltParser(ctxt);
                            return(0);
                        }
                        ctxt->standalone = ctxt->input->standalone;
@@ -11345,7 +11565,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                cur = ctxt->input->cur[0];
                if (cur != '<') {
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
-                   ctxt->instate = XML_PARSER_EOF;
+                   xmlHaltParser(ctxt);
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
                        ctxt->sax->endDocument(ctxt->userData);
                    goto done;
@@ -11377,7 +11597,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                    goto done;
                if (name == NULL) {
                    spacePop(ctxt);
-                   ctxt->instate = XML_PARSER_EOF;
+                   xmlHaltParser(ctxt);
                    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
                        ctxt->sax->endDocument(ctxt->userData);
                    goto done;
@@ -11544,7 +11764,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
                    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
                                "detected an error in element content\n");
-                   ctxt->instate = XML_PARSER_EOF;
+                   xmlHaltParser(ctxt);
                    break;
                }
                break;
@@ -11593,7 +11813,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                        int tmp;
 
                        tmp = xmlCheckCdataPush(ctxt->input->cur,
-                                               XML_PARSER_BIG_BUFFER_SIZE);
+                                               XML_PARSER_BIG_BUFFER_SIZE, 0);
                        if (tmp < 0) {
                            tmp = -tmp;
                            ctxt->input->cur += tmp;
@@ -11616,7 +11836,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                } else {
                    int tmp;
 
-                   tmp = xmlCheckCdataPush(ctxt->input->cur, base);
+                   tmp = xmlCheckCdataPush(ctxt->input->cur, base, 1);
                    if ((tmp < 0) || (tmp != base)) {
                        tmp = -tmp;
                        ctxt->input->cur += tmp;
@@ -11865,7 +12085,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                    goto done;
                } else {
                    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
-                   ctxt->instate = XML_PARSER_EOF;
+                   xmlHaltParser(ctxt);
 #ifdef DEBUG_PUSH
                    xmlGenericError(xmlGenericErrorContext,
                            "PP: entering EOF\n");
@@ -12229,7 +12449,7 @@ xmldecl_done:
        res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
        if (res < 0) {
            ctxt->errNo = XML_PARSER_EOF;
-           ctxt->disableSAX = 1;
+           xmlHaltParser(ctxt);
            return (XML_PARSER_EOF);
        }
         xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
@@ -12283,7 +12503,7 @@ xmldecl_done:
          ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
         ((ctxt->options & XML_PARSE_HUGE) == 0)) {
         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
-        ctxt->instate = XML_PARSER_EOF;
+        xmlHaltParser(ctxt);
     }
     if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
         return(ctxt->errNo);
@@ -12471,25 +12691,47 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
 #endif /* LIBXML_PUSH_ENABLED */
 
 /**
- * xmlStopParser:
+ * xmlHaltParser:
  * @ctxt:  an XML parser context
  *
- * Blocks further parser processing
+ * Blocks further parser processing don't override error
+ * for internal use
  */
-void
-xmlStopParser(xmlParserCtxtPtr ctxt) {
+static void
+xmlHaltParser(xmlParserCtxtPtr ctxt) {
     if (ctxt == NULL)
         return;
     ctxt->instate = XML_PARSER_EOF;
-    ctxt->errNo = XML_ERR_USER_STOP;
     ctxt->disableSAX = 1;
     if (ctxt->input != NULL) {
+        /*
+        * in case there was a specific allocation deallocate before
+        * overriding base
+        */
+        if (ctxt->input->free != NULL) {
+           ctxt->input->free((xmlChar *) ctxt->input->base);
+           ctxt->input->free = NULL;
+       }
        ctxt->input->cur = BAD_CAST"";
        ctxt->input->base = ctxt->input->cur;
     }
 }
 
 /**
+ * xmlStopParser:
+ * @ctxt:  an XML parser context
+ *
+ * Blocks further parser processing
+ */
+void
+xmlStopParser(xmlParserCtxtPtr ctxt) {
+    if (ctxt == NULL)
+        return;
+    xmlHaltParser(ctxt);
+    ctxt->errNo = XML_ERR_USER_STOP;
+}
+
+/**
  * xmlCreateIOParserCtxt:
  * @sax:  a SAX handler
  * @user_data:  The user data returned on SAX callbacks
@@ -12591,6 +12833,9 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
        return(NULL);
     }
 
+    /* We are loading a DTD */
+    ctxt->options |= XML_PARSE_DTDLOAD;
+
     /*
      * Set-up the SAX context
      */
@@ -12718,6 +12963,9 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
        return(NULL);
     }
 
+    /* We are loading a DTD */
+    ctxt->options |= XML_PARSE_DTDLOAD;
+
     /*
      * Set-up the SAX context
      */
@@ -13227,7 +13475,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
     /*
      * Also record the size of the entity parsed
      */
-    if (ctxt->input != NULL) {
+    if (ctxt->input != NULL && oldctxt != NULL) {
        oldctxt->sizeentities += ctxt->input->consumed;
        oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
     }
@@ -13239,9 +13487,11 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
 
     if (sax != NULL)
        ctxt->sax = oldsax;
-    oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
-    oldctxt->node_seq.length = ctxt->node_seq.length;
-    oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
+    if (oldctxt != NULL) {
+        oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
+        oldctxt->node_seq.length = ctxt->node_seq.length;
+        oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
+    }
     ctxt->node_seq.maximum = 0;
     ctxt->node_seq.length = 0;
     ctxt->node_seq.buffer = NULL;
@@ -13607,7 +13857,7 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
            xmlFree((xmlChar *) ctxt->encoding);
         ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
 
-        hdlr = xmlFindCharEncodingHandler(doc->encoding);
+        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
         if (hdlr != NULL) {
             xmlSwitchToEncoding(ctxt, hdlr);
        } else {
@@ -13618,6 +13868,8 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
     xmlCtxtUseOptionsInternal(ctxt, options, NULL);
     xmlDetectSAX2(ctxt);
     ctxt->myDoc = doc;
+    /* parsing in context, i.e. as within existing content */
+    ctxt->instate = XML_PARSER_CONTENT;
 
     fake = xmlNewComment(NULL);
     if (fake == NULL) {
@@ -13653,7 +13905,6 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
            }
            cur = cur->parent;
        }
-       ctxt->instate = XML_PARSER_CONTENT;
     }
 
     if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
@@ -14763,8 +15014,8 @@ xmlCleanupParser(void) {
     xmlSchemaCleanupTypes();
     xmlRelaxNGCleanupTypes();
 #endif
-    xmlCleanupGlobals();
     xmlResetLastError();
+    xmlCleanupGlobals();
     xmlCleanupThreads(); /* must be last if called not from the main thread */
     xmlCleanupMemory();
     xmlParserInitialized = 0;
@@ -14780,7 +15031,7 @@ xmlCleanupParser(void) {
  * DICT_FREE:
  * @str:  a string
  *
- * Free a string if it is not owned by the "dict" dictionnary in the
+ * Free a string if it is not owned by the "dict" dictionary in the
  * current scope
  */
 #define DICT_FREE(str)                                         \
@@ -15213,6 +15464,7 @@ xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int optio
 
     if (cur == NULL)
         return (NULL);
+    xmlInitParser();
 
     ctxt = xmlCreateDocParserCtxt(cur);
     if (ctxt == NULL)
@@ -15235,6 +15487,7 @@ xmlReadFile(const char *filename, const char *encoding, int options)
 {
     xmlParserCtxtPtr ctxt;
 
+    xmlInitParser();
     ctxt = xmlCreateURLParserCtxt(filename, options);
     if (ctxt == NULL)
         return (NULL);
@@ -15258,6 +15511,7 @@ xmlReadMemory(const char *buffer, int size, const char *URL, const char *encodin
 {
     xmlParserCtxtPtr ctxt;
 
+    xmlInitParser();
     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
     if (ctxt == NULL)
         return (NULL);
@@ -15286,6 +15540,7 @@ xmlReadFd(int fd, const char *URL, const char *encoding, int options)
 
     if (fd < 0)
         return (NULL);
+    xmlInitParser();
 
     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
     if (input == NULL)
@@ -15329,6 +15584,7 @@ xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
 
     if (ioread == NULL)
         return (NULL);
+    xmlInitParser();
 
     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
                                          XML_CHAR_ENCODING_NONE);
@@ -15375,6 +15631,7 @@ xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
         return (NULL);
     if (ctxt == NULL)
         return (NULL);
+    xmlInitParser();
 
     xmlCtxtReset(ctxt);
 
@@ -15408,6 +15665,7 @@ xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
         return (NULL);
     if (ctxt == NULL)
         return (NULL);
+    xmlInitParser();
 
     xmlCtxtReset(ctxt);
 
@@ -15444,6 +15702,7 @@ xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
         return (NULL);
     if (buffer == NULL)
         return (NULL);
+    xmlInitParser();
 
     xmlCtxtReset(ctxt);
 
@@ -15488,6 +15747,7 @@ xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
         return (NULL);
     if (ctxt == NULL)
         return (NULL);
+    xmlInitParser();
 
     xmlCtxtReset(ctxt);
 
@@ -15533,6 +15793,7 @@ xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
         return (NULL);
     if (ctxt == NULL)
         return (NULL);
+    xmlInitParser();
 
     xmlCtxtReset(ctxt);