Bump to libxml2 2.9.4
[platform/upstream/libxml2.git] / parser.c
index 1d93967..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          *
@@ -136,14 +138,20 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
      * entities problems
      */
     if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
-       (ent->content != NULL) && (ent->checked == 0)) {
+       (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) {
@@ -342,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))
@@ -529,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)
@@ -553,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)
 {
@@ -581,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)
 {
@@ -619,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)
 {
@@ -659,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)
 {
@@ -689,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)
@@ -719,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)
 {
@@ -748,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)
 {
@@ -773,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,
@@ -802,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,
@@ -1771,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;
@@ -2006,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 && \
@@ -2073,9 +2083,16 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) {
          ((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);
@@ -2151,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++;
@@ -2165,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);
 }
@@ -2806,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 */
@@ -2843,7 +2866,21 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
                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,
@@ -3455,7 +3492,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
     int len = 0, l;
     int c;
     int count = 0;
-    const xmlChar *end; /* needed because CUR_CHAR() can move cur on \r\n */
+    size_t startPosition = 0;
 
 #ifdef DEBUG
     nbParseNCNameComplex++;
@@ -3465,7 +3502,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
      * Handler for more complex cases
      */
     GROW;
-    end = ctxt->input->cur;
+    startPosition = CUR_PTR - BASE_PTR;
     c = CUR_CHAR(l);
     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
        (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
@@ -3487,14 +3524,19 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
        }
        len += l;
        NEXTL(l);
-       end = ctxt->input->cur;
        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);
-           end = ctxt->input->cur;
            c = CUR_CHAR(l);
        }
     }
@@ -3503,7 +3545,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
         return(NULL);
     }
-    return(xmlDictLookup(ctxt->dict, end - len, len));
+    return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len));
 }
 
 /**
@@ -3523,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;
 
@@ -3535,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) &&
@@ -3562,6 +3607,7 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
            return(ret);
        }
     }
+complex:
     return(xmlParseNCNameComplex(ctxt));
 }
 
@@ -3599,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;
     }
@@ -3940,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
@@ -4066,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 */
@@ -4104,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) {
@@ -5475,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;
        }
@@ -5658,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,
@@ -6659,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);
@@ -6769,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,
@@ -6808,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;
            }
        }
@@ -6829,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,
@@ -6884,6 +6943,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
     } else {
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
+       xmlHaltParser(ctxt);
+       return;
     }
 
     if (RAW == 0)
@@ -6897,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);
     }
 }
 
@@ -6952,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
@@ -7083,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;
        }
     }
@@ -7235,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;
@@ -8069,7 +8141,7 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
                     * The XML REC instructs us to stop parsing
                     * right here
                     */
-                   ctxt->instate = XML_PARSER_EOF;
+                   xmlHaltParser(ctxt);
                    return;
                }
            }
@@ -8424,6 +8496,7 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
      */
     if (RAW != '>') {
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+       return;
     }
     NEXT;
 }
@@ -8774,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
  */
@@ -9304,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;
@@ -9323,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;
@@ -9348,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) != '>')) &&
@@ -9359,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;
@@ -9419,7 +9494,10 @@ 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)) {
@@ -9428,6 +9506,8 @@ skip_default_ns:
                    break;
                }
                SKIP_BLANKS;
+               if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+                   goto base_changed;
                continue;
            }
             if (aprefix == ctxt->str_xmlns) {
@@ -9499,7 +9579,10 @@ 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)) {
@@ -9508,7 +9591,8 @@ skip_ns:
                    break;
                }
                SKIP_BLANKS;
-               if (ctxt->input->base != base) goto base_changed;
+               if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
+                   goto base_changed;
                continue;
            }
 
@@ -9545,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)) {
@@ -9561,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;
     }
 
     /*
@@ -9728,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;
@@ -9756,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) != '/')) {
@@ -9764,8 +9862,11 @@ 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;
@@ -10009,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;
        }
     }
@@ -10044,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;
     }
 
@@ -10396,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 == '\''){
@@ -10403,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 {
@@ -10459,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);
@@ -10628,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
         */
@@ -10752,6 +10862,7 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
 
     if (CUR == 0) {
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+       return(-1);
     }
 
     /*
@@ -10769,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
             */
@@ -11138,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]
  *
@@ -11147,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;
@@ -11165,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;
@@ -11174,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);
@@ -11185,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))
@@ -11363,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");
@@ -11396,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;
@@ -11452,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;
@@ -11484,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;
@@ -11651,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;
@@ -11700,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;
@@ -11723,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;
@@ -11972,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");
@@ -12336,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);
@@ -12390,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);
@@ -12578,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
@@ -13340,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);
     }
@@ -13352,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;
@@ -14830,9 +14967,6 @@ xmlInitParser(void) {
 #ifdef LIBXML_XPATH_ENABLED
        xmlXPathInit();
 #endif
-#ifdef LIBXML_CATALOG_ENABLED
-        xmlInitializeCatalog();
-#endif
        xmlParserInitialized = 1;
 #ifdef LIBXML_THREAD_ENABLED
     }
@@ -14897,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)                                         \