Merge "Merge branch 'tizen_base' into tizen" into tizen
[platform/upstream/libxml2.git] / parser.c
index 1d93967..1c5e036 100644 (file)
--- a/parser.c
+++ b/parser.c
  * daniel@veillard.com
  */
 
+/* To avoid EBCDIC trouble when parsing on zOS */
+#if defined(__MVS__)
+#pragma convert("ISO8859-1")
+#endif
+
 #define IN_LIBXML
 #include "libxml.h"
 
-#if defined(WIN32) && !defined (__CYGWIN__)
+#if defined(_WIN32) && !defined (__CYGWIN__)
 #define XML_DIR_SEP '\\'
 #else
 #define XML_DIR_SEP '/'
@@ -43,6 +48,7 @@
 #include <limits.h>
 #include <string.h>
 #include <stdarg.h>
+#include <stddef.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/threads.h>
 #include <libxml/globals.h>
@@ -94,6 +100,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 +144,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 +356,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 +542,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 +568,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 +596,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 +634,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 +674,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 +704,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 +734,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 +763,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 +788,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 +817,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,
@@ -1078,7 +1093,12 @@ typedef xmlDefAttrs *xmlDefAttrsPtr;
 struct _xmlDefAttrs {
     int nbAttrs;       /* number of defaulted attributes on that element */
     int maxAttrs;       /* the size of the array */
-    const xmlChar *values[5]; /* array of localname/prefix/values/external */
+#if __STDC_VERSION__ >= 199901L
+    /* Using a C99 flexible array member avoids UBSan errors. */
+    const xmlChar *values[]; /* array of localname/prefix/values/external */
+#else
+    const xmlChar *values[5];
+#endif
 };
 
 /**
@@ -1315,7 +1335,7 @@ xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
         return;
 
     xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
-                     (void *) (long) type);
+                     (void *) (ptrdiff_t) type);
     return;
 
 mem_error:
@@ -1334,7 +1354,7 @@ xmlCleanSpecialAttrCallback(void *payload, void *data,
                             const xmlChar *unused ATTRIBUTE_UNUSED) {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
 
-    if (((long) payload) == XML_ATTRIBUTE_CDATA) {
+    if (((ptrdiff_t) payload) == XML_ATTRIBUTE_CDATA) {
         xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
     }
 }
@@ -1771,7 +1791,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;
@@ -1846,7 +1866,7 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
     ctxt->name = value;
     ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
     ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
-    ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
+    ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (ptrdiff_t) nsNr;
     return (ctxt->nameNr++);
 mem_error:
     xmlErrMemory(ctxt, NULL);
@@ -2006,6 +2026,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 && \
@@ -2027,10 +2048,8 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
 
 #define SKIP(val) do {                                                 \
     ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);                  \
-    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);    \
-    if ((*ctxt->input->cur == 0) &&                                    \
-        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))           \
-           xmlPopInput(ctxt);                                          \
+    if (*ctxt->input->cur == 0)                                                \
+        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);                  \
   } while (0)
 
 #define SKIPL(val) do {                                                        \
@@ -2042,10 +2061,8 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
        ctxt->nbChars++;                                                \
        ctxt->input->cur++;                                             \
     }                                                                  \
-    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);    \
-    if ((*ctxt->input->cur == 0) &&                                    \
-        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))           \
-           xmlPopInput(ctxt);                                          \
+    if (*ctxt->input->cur == 0)                                                \
+        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);                  \
   } while (0)
 
 #define SHRINK if ((ctxt->progressive == 0) &&                         \
@@ -2055,10 +2072,9 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
 
 static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
     xmlParserInputShrink(ctxt->input);
-    if ((*ctxt->input->cur == 0) &&
-        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
-           xmlPopInput(ctxt);
-  }
+    if (*ctxt->input->cur == 0)
+        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+}
 
 #define GROW if ((ctxt->progressive == 0) &&                           \
                 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))   \
@@ -2073,12 +2089,18 @@ 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 != NULL) && (*ctxt->input->cur == 0) &&
-        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
-           xmlPopInput(ctxt);
+    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);
 }
 
 #define SKIP_BLANKS xmlSkipBlankChars(ctxt)
@@ -2098,7 +2120,6 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) {
        ctxt->input->line++; ctxt->input->col = 1;                      \
     } else ctxt->input->col++;                                         \
     ctxt->input->cur += l;                             \
-    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);    \
   } while (0)
 
 #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
@@ -2148,24 +2169,35 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
        }
        ctxt->input->cur = cur;
     } else {
-       int cur;
-       do {
-           cur = CUR;
-           while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
+        int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1));
+
+       while (1) {
+            if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */
                NEXT;
-               cur = CUR;
-               res++;
-           }
-           while ((cur == 0) && (ctxt->inputNr > 1) &&
-                  (ctxt->instate != XML_PARSER_COMMENT)) {
-               xmlPopInput(ctxt);
-               cur = CUR;
-           }
-           /*
-            * Need to handle support of entities branching here
-            */
-           if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
-       } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
+           } else if (CUR == '%') {
+                /*
+                 * Need to handle support of entities branching here
+                 */
+               if ((expandPE == 0) || (IS_BLANK_CH(NXT(1))) || (NXT(1) == 0))
+                    break;
+               xmlParsePEReference(ctxt);
+            } else if (CUR == 0) {
+                if (ctxt->inputNr <= 1)
+                    break;
+                xmlPopInput(ctxt);
+            } else {
+                break;
+            }
+
+            /*
+             * Also increase the counter when entering or exiting a PERef.
+             * The spec says: "When a parameter-entity reference is recognized
+             * in the DTD and included, its replacement text MUST be enlarged
+             * by the attachment of one leading and one following space (#x20)
+             * character."
+             */
+           res++;
+        }
     }
     return(res);
 }
@@ -2191,10 +2223,13 @@ xmlPopInput(xmlParserCtxtPtr ctxt) {
     if (xmlParserDebugEntities)
        xmlGenericError(xmlGenericErrorContext,
                "Popping input %d\n", ctxt->inputNr);
+    if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) &&
+        (ctxt->instate != XML_PARSER_EOF))
+        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+                    "Unfinished entity outside the DTD");
     xmlFreeInputStream(inputPop(ctxt));
-    if ((*ctxt->input->cur == 0) &&
-        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
-           return(xmlPopInput(ctxt));
+    if (*ctxt->input->cur == 0)
+        xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
     return(CUR);
 }
 
@@ -2220,6 +2255,13 @@ xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
        xmlGenericError(xmlGenericErrorContext,
                "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
     }
+    if (((ctxt->inputNr > 40) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
+        (ctxt->inputNr > 1024)) {
+        xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+        while (ctxt->inputNr > 1)
+            xmlFreeInputStream(inputPop(ctxt));
+       return(-1);
+    }
     ret = inputPush(ctxt, input);
     if (ctxt->instate == XML_PARSER_EOF)
         return(-1);
@@ -2425,57 +2467,6 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
 }
 
 /**
- * xmlNewBlanksWrapperInputStream:
- * @ctxt:  an XML parser context
- * @entity:  an Entity pointer
- *
- * Create a new input stream for wrapping
- * blanks around a PEReference
- *
- * Returns the new input stream or NULL
- */
-
-static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
-
-static xmlParserInputPtr
-xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
-    xmlParserInputPtr input;
-    xmlChar *buffer;
-    size_t length;
-    if (entity == NULL) {
-       xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-                   "xmlNewBlanksWrapperInputStream entity\n");
-       return(NULL);
-    }
-    if (xmlParserDebugEntities)
-       xmlGenericError(xmlGenericErrorContext,
-               "new blanks wrapper for entity: %s\n", entity->name);
-    input = xmlNewInputStream(ctxt);
-    if (input == NULL) {
-       return(NULL);
-    }
-    length = xmlStrlen(entity->name) + 5;
-    buffer = xmlMallocAtomic(length);
-    if (buffer == NULL) {
-       xmlErrMemory(ctxt, NULL);
-        xmlFree(input);
-       return(NULL);
-    }
-    buffer [0] = ' ';
-    buffer [1] = '%';
-    buffer [length-3] = ';';
-    buffer [length-2] = ' ';
-    buffer [length-1] = 0;
-    memcpy(buffer + 2, entity->name, length - 5);
-    input->free = deallocblankswrapper;
-    input->base = buffer;
-    input->cur = buffer;
-    input->length = length;
-    input->end = &buffer[length];
-    return(input);
-}
-
-/**
  * xmlParserHandlePEReference:
  * @ctxt:  the parser context
  *
@@ -2509,11 +2500,6 @@ xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
  */
 void
 xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
-    const xmlChar *name;
-    xmlEntityPtr entity = NULL;
-    xmlParserInputPtr input;
-
-    if (RAW != '%') return;
     switch(ctxt->instate) {
        case XML_PARSER_CDATA_SECTION:
            return;
@@ -2568,128 +2554,7 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
             return;
     }
 
-    NEXT;
-    name = xmlParseName(ctxt);
-    if (xmlParserDebugEntities)
-       xmlGenericError(xmlGenericErrorContext,
-               "PEReference: %s\n", name);
-    if (name == NULL) {
-       xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
-    } else {
-       if (RAW == ';') {
-           NEXT;
-           if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
-               entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
-           if (ctxt->instate == XML_PARSER_EOF)
-               return;
-           if (entity == NULL) {
-
-               /*
-                * [ WFC: Entity Declared ]
-                * In a document without any DTD, a document with only an
-                * internal DTD subset which contains no parameter entity
-                * references, or a document with "standalone='yes'", ...
-                * ... The declaration of a parameter entity must precede
-                * any reference to it...
-                */
-               if ((ctxt->standalone == 1) ||
-                   ((ctxt->hasExternalSubset == 0) &&
-                    (ctxt->hasPErefs == 0))) {
-                   xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
-                        "PEReference: %%%s; not found\n", name);
-               } else {
-                   /*
-                    * [ VC: Entity Declared ]
-                    * In a document with an external subset or external
-                    * parameter entities with "standalone='no'", ...
-                    * ... The declaration of a parameter entity must precede
-                    * any reference to it...
-                    */
-                   if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
-                       xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
-                                        "PEReference: %%%s; not found\n",
-                                        name, NULL);
-                   } else
-                       xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
-                                     "PEReference: %%%s; not found\n",
-                                     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)
-                       return;
-           } else {
-               if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
-                   (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
-                   xmlChar start[4];
-                   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.
-                    */
-                   input = xmlNewEntityInputStream(ctxt, entity);
-                   if (xmlPushInput(ctxt, input) < 0)
-                       return;
-
-                   /*
-                    * Get the 4 first bytes and decode the charset
-                    * if enc != XML_CHAR_ENCODING_NONE
-                    * plug some encoding conversion routines.
-                    * Note that, since we may have some non-UTF8
-                    * encoding (like UTF16, bug 135229), the 'length'
-                    * is not known, but we can calculate based upon
-                    * the amount of data in the buffer.
-                    */
-                   GROW
-                    if (ctxt->instate == XML_PARSER_EOF)
-                        return;
-                   if ((ctxt->input->end - ctxt->input->cur)>=4) {
-                       start[0] = RAW;
-                       start[1] = NXT(1);
-                       start[2] = NXT(2);
-                       start[3] = NXT(3);
-                       enc = xmlDetectCharEncoding(start, 4);
-                       if (enc != XML_CHAR_ENCODING_NONE) {
-                           xmlSwitchEncoding(ctxt, enc);
-                       }
-                   }
-
-                   if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
-                       (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
-                       (IS_BLANK_CH(NXT(5)))) {
-                       xmlParseTextDecl(ctxt);
-                   }
-               } else {
-                   xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
-                            "PEReference: %s is not a parameter entity\n",
-                                     name);
-               }
-           }
-       } else {
-           xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
-       }
-    }
+    xmlParsePEReference(ctxt);
 }
 
 /*
@@ -2771,9 +2636,9 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
        if (c == 0) break;
         if ((c == '&') && (str[1] == '#')) {
            int val = xmlParseStringCharRef(ctxt, &str);
-           if (val != 0) {
-               COPY_BUF(0,buffer,nbchars,val);
-           }
+           if (val == 0)
+                goto int_error;
+           COPY_BUF(0,buffer,nbchars,val);
            if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
                growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
            }
@@ -2783,9 +2648,6 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
                        "String decoding Entity Reference: %.30s\n",
                        str);
            ent = xmlParseStringEntityRef(ctxt, &str);
-           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;
@@ -2799,26 +2661,27 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
                } else {
                    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
                            "predefined entity has no content\n");
+                    goto int_error;
                }
            } else if ((ent != NULL) && (ent->content != NULL)) {
                ctxt->depth++;
                rep = xmlStringDecodeEntities(ctxt, ent->content, what,
                                              0, 0, 0);
                ctxt->depth--;
-
-               if (rep != NULL) {
-                   current = rep;
-                   while (*current != 0) { /* non input consuming loop */
-                       buffer[nbchars++] = *current++;
-                       if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
-                           if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
-                               goto int_error;
-                           growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
-                       }
-                   }
-                   xmlFree(rep);
-                   rep = NULL;
-               }
+               if (rep == NULL)
+                    goto int_error;
+
+                current = rep;
+                while (*current != 0) { /* non input consuming loop */
+                    buffer[nbchars++] = *current++;
+                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
+                            goto int_error;
+                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+                    }
+                }
+                xmlFree(rep);
+                rep = NULL;
            } else if (ent != NULL) {
                int i = xmlStrlen(ent->name);
                const xmlChar *cur = ent->name;
@@ -2836,32 +2699,44 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
                xmlGenericError(xmlGenericErrorContext,
                        "String decoding PE Reference: %.30s\n", str);
            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,
                                              0, 0, 0);
                ctxt->depth--;
-               if (rep != NULL) {
-                   current = rep;
-                   while (*current != 0) { /* non input consuming loop */
-                       buffer[nbchars++] = *current++;
-                       if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
-                           if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
-                               goto int_error;
-                           growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
-                       }
-                   }
-                   xmlFree(rep);
-                   rep = NULL;
-               }
+               if (rep == NULL)
+                    goto int_error;
+                current = rep;
+                while (*current != 0) { /* non input consuming loop */
+                    buffer[nbchars++] = *current++;
+                    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                        if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
+                            goto int_error;
+                        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+                    }
+                }
+                xmlFree(rep);
+                rep = NULL;
            }
        } else {
            COPY_BUF(l,buffer,nbchars,c);
@@ -3369,13 +3244,6 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
            len += l;
            NEXTL(l);
            c = CUR_CHAR(l);
-           if (c == 0) {
-               count = 0;
-               GROW;
-                if (ctxt->instate == XML_PARSER_EOF)
-                    return(NULL);
-               c = CUR_CHAR(l);
-           }
        }
     }
     if ((len > XML_MAX_NAME_LENGTH) &&
@@ -3383,6 +3251,16 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
         xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
         return(NULL);
     }
+    if (ctxt->input->cur - ctxt->input->base < len) {
+        /*
+         * There were a couple of bugs where PERefs lead to to a change
+         * of the buffer. Check the buffer size to avoid passing an invalid
+         * pointer to xmlDictLookup.
+         */
+        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+                    "unexpected change of input buffer");
+        return (NULL);
+    }
     if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
         return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
@@ -3455,7 +3333,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 +3343,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 +3365,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 +3386,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 +3406,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 +3418,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 +3448,7 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
            return(ret);
        }
     }
+complex:
     return(xmlParseNCNameComplex(ctxt));
 }
 
@@ -3599,7 +3486,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;
     }
@@ -3846,10 +3733,8 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
     ctxt->instate = XML_PARSER_ENTITY_VALUE;
     input = ctxt->input;
     GROW;
-    if (ctxt->instate == XML_PARSER_EOF) {
-        xmlFree(buf);
-        return(NULL);
-    }
+    if (ctxt->instate == XML_PARSER_EOF)
+        goto error;
     NEXT;
     c = CUR_CHAR(l);
     /*
@@ -3870,18 +3755,12 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
            tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
            if (tmp == NULL) {
                xmlErrMemory(ctxt, NULL);
-               xmlFree(buf);
-               return(NULL);
+                goto error;
            }
            buf = tmp;
        }
        COPY_BUF(l,buf,len,c);
        NEXTL(l);
-       /*
-        * Pop-up of finished entities.
-        */
-       while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
-           xmlPopInput(ctxt);
 
        GROW;
        c = CUR_CHAR(l);
@@ -3891,10 +3770,13 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
        }
     }
     buf[len] = 0;
-    if (ctxt->instate == XML_PARSER_EOF) {
-        xmlFree(buf);
-        return(NULL);
+    if (ctxt->instate == XML_PARSER_EOF)
+        goto error;
+    if (c != stop) {
+        xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
+        goto error;
     }
+    NEXT;
 
     /*
      * Raise problem w.r.t. '&' and '%' being used in non-entities
@@ -3906,20 +3788,25 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
        if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
            xmlChar *name;
            xmlChar tmp = *cur;
+            int nameOk = 0;
 
            cur++;
            name = xmlParseStringName(ctxt, &cur);
-            if ((name == NULL) || (*cur != ';')) {
+            if (name != NULL) {
+                nameOk = 1;
+                xmlFree(name);
+            }
+            if ((nameOk == 0) || (*cur != ';')) {
                xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
            "EntityValue: '%c' forbidden except for entities references\n",
                                  tmp);
+                goto error;
            }
            if ((tmp == '%') && (ctxt->inSubset == 1) &&
                (ctxt->inputNr == 1)) {
                xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
+                goto error;
            }
-           if (name != NULL)
-               xmlFree(name);
            if (*cur == 0)
                break;
        }
@@ -3928,26 +3815,24 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
 
     /*
      * Then PEReference entities are substituted.
+     *
+     * NOTE: 4.4.7 Bypassed
+     * When a general entity reference appears in the EntityValue in
+     * an entity declaration, it is bypassed and left as is.
+     * so XML_SUBSTITUTE_REF is not set here.
      */
-    if (c != stop) {
-       xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
-       xmlFree(buf);
-    } else {
-       NEXT;
-       /*
-        * NOTE: 4.4.7 Bypassed
-        * When a general entity reference appears in the EntityValue in
-        * an entity declaration, it is bypassed and left as is.
-        * so XML_SUBSTITUTE_REF is not set here.
-        */
-       ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
-                                     0, 0, 0);
-       if (orig != NULL)
-           *orig = buf;
-       else
-           xmlFree(buf);
+    ++ctxt->depth;
+    ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
+                                  0, 0, 0);
+    --ctxt->depth;
+    if (orig != NULL) {
+        *orig = buf;
+        buf = NULL;
     }
 
+error:
+    if (buf != NULL)
+        xmlFree(buf);
     return(ret);
 }
 
@@ -4066,9 +3951,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 +3991,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) {
@@ -4113,7 +4002,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
                                ent->checked |= 1;
                            xmlFree(rep);
                            rep = NULL;
-                       }
+                       } else {
+                            ent->content[0] = 0;
+                        }
                    }
 
                    /*
@@ -4537,7 +4428,7 @@ get_more:
            if (*in == ']') {
                if ((in[1] == ']') && (in[2] == '>')) {
                    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
-                   ctxt->input->cur = in;
+                   ctxt->input->cur = in + 1;
                    return;
                }
                in++;
@@ -4730,22 +4621,20 @@ xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
     *publicID = NULL;
     if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
         SKIP(6);
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after 'SYSTEM'\n");
        }
-        SKIP_BLANKS;
        URI = xmlParseSystemLiteral(ctxt);
        if (URI == NULL) {
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
         }
     } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
         SKIP(6);
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                    "Space required after 'PUBLIC'\n");
        }
-        SKIP_BLANKS;
        *publicID = xmlParsePubidLiteral(ctxt);
        if (*publicID == NULL) {
            xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
@@ -4754,26 +4643,20 @@ xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
            /*
             * We don't handle [83] so "S SystemLiteral" is required.
             */
-           if (!IS_BLANK_CH(CUR)) {
+           if (SKIP_BLANKS == 0) {
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                        "Space required after the Public Identifier\n");
            }
        } else {
            /*
             * We handle [83] so we return immediately, if
-            * "S SystemLiteral" is not detected. From a purely parsing
-            * point of view that's a nice mess.
+            * "S SystemLiteral" is not detected. We skip blanks if no
+             * system literal was found, but this is harmless since we must
+             * be at the end of a NotationDecl.
             */
-           const xmlChar *ptr;
-           GROW;
-
-           ptr = CUR_PTR;
-           if (!IS_BLANK_CH(*ptr)) return(NULL);
-
-           while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
-           if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
+           if (SKIP_BLANKS == 0) return(NULL);
+           if ((CUR != '\'') && (CUR != '"')) return(NULL);
        }
-        SKIP_BLANKS;
        URI = xmlParseSystemLiteral(ctxt);
        if (URI == NULL) {
            xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
@@ -4903,7 +4786,8 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
     } else {
        if (inputid != ctxt->input->id) {
            xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-               "Comment doesn't start and stop in the same entity\n");
+                          "Comment doesn't start and stop in the same"
+                           " entity\n");
        }
         NEXT;
        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
@@ -5051,7 +4935,8 @@ get_more:
                if (in[2] == '>') {
                    if (ctxt->input->id != inputid) {
                        xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-                       "comment doesn't start and stop in the same entity\n");
+                                      "comment doesn't start and stop in the"
+                                       " same entity\n");
                    }
                    SKIP(3);
                    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
@@ -5219,7 +5104,7 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
     int count = 0;
 
     if ((RAW == '<') && (NXT(1) == '?')) {
-       xmlParserInputPtr input = ctxt->input;
+       int inputid = ctxt->input->id;
        state = ctxt->instate;
         ctxt->instate = XML_PARSER_PI;
        /*
@@ -5235,9 +5120,10 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
         target = xmlParsePITarget(ctxt);
        if (target != NULL) {
            if ((RAW == '?') && (NXT(1) == '>')) {
-               if (input != ctxt->input) {
+               if (inputid != ctxt->input->id) {
                    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-           "PI declaration doesn't start and stop in the same entity\n");
+                                  "PI declaration doesn't start and stop in"
+                                   " the same entity\n");
                }
                SKIP(2);
 
@@ -5258,12 +5144,10 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
                ctxt->instate = state;
                return;
            }
-           cur = CUR;
-           if (!IS_BLANK(cur)) {
+           if (SKIP_BLANKS == 0) {
                xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
                          "ParsePI: PI %s space expected\n", target);
            }
-            SKIP_BLANKS;
            cur = CUR_CHAR(l);
            while (IS_CHAR(cur) && /* checked */
                   ((cur != '?') || (NXT(1) != '>'))) {
@@ -5319,9 +5203,10 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
                      "ParsePI: PI %s never end ...\n", target);
            } else {
-               if (input != ctxt->input) {
-                   xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-           "PI declaration doesn't start and stop in the same entity\n");
+               if (inputid != ctxt->input->id) {
+                   xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                                  "PI declaration doesn't start and stop in"
+                                   " the same entity\n");
                }
                SKIP(2);
 
@@ -5377,32 +5262,30 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
     xmlChar *Systemid;
 
     if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
-       xmlParserInputPtr input = ctxt->input;
+       int inputid = ctxt->input->id;
        SHRINK;
        SKIP(10);
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after '<!NOTATION'\n");
            return;
        }
-       SKIP_BLANKS;
 
         name = xmlParseName(ctxt);
        if (name == NULL) {
            xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
            return;
        }
-       if (!IS_BLANK_CH(CUR)) {
-           xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-                    "Space required after the NOTATION name'\n");
-           return;
-       }
        if (xmlStrchr(name, ':') != NULL) {
            xmlNsErr(ctxt, XML_NS_ERR_COLON,
                     "colons are forbidden from notation names '%s'\n",
                     name, NULL, NULL);
        }
-       SKIP_BLANKS;
+       if (SKIP_BLANKS == 0) {
+           xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+                    "Space required after the NOTATION name'\n");
+           return;
+       }
 
        /*
         * Parse the IDs.
@@ -5411,9 +5294,10 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
        SKIP_BLANKS;
 
        if (RAW == '>') {
-           if (input != ctxt->input) {
-               xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-       "Notation declaration doesn't start and stop in the same entity\n");
+           if (inputid != ctxt->input->id) {
+               xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                              "Notation declaration doesn't start and stop"
+                               " in the same entity\n");
            }
            NEXT;
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
@@ -5457,25 +5341,22 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
     const xmlChar *ndata = NULL;
     int isParameter = 0;
     xmlChar *orig = NULL;
-    int skipped;
 
     /* GROW; done in the caller */
     if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
-       xmlParserInputPtr input = ctxt->input;
+       int inputid = ctxt->input->id;
        SHRINK;
        SKIP(8);
-       skipped = SKIP_BLANKS;
-       if (skipped == 0) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after '<!ENTITY'\n");
        }
 
        if (RAW == '%') {
            NEXT;
-           skipped = SKIP_BLANKS;
-           if (skipped == 0) {
+           if (SKIP_BLANKS == 0) {
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-                              "Space required after '%'\n");
+                              "Space required after '%%'\n");
            }
            isParameter = 1;
        }
@@ -5491,8 +5372,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
                     "colons are forbidden from entities names '%s'\n",
                     name, NULL, NULL);
        }
-        skipped = SKIP_BLANKS;
-       if (skipped == 0) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after the entity name\n");
        }
@@ -5603,18 +5483,16 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
                        xmlFreeURI(uri);
                    }
                }
-               if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
+               if ((RAW != '>') && (SKIP_BLANKS == 0)) {
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                                   "Space required before 'NDATA'\n");
                }
-               SKIP_BLANKS;
                if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
                    SKIP(5);
-                   if (!IS_BLANK_CH(CUR)) {
+                   if (SKIP_BLANKS == 0) {
                        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                                       "Space required after 'NDATA'\n");
                    }
-                   SKIP_BLANKS;
                    ndata = xmlParseName(ctxt);
                    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
                        (ctxt->sax->unparsedEntityDecl != NULL))
@@ -5653,15 +5531,17 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
            }
        }
        if (ctxt->instate == XML_PARSER_EOF)
-           return;
+           goto done;
        SKIP_BLANKS;
        if (RAW != '>') {
            xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
                    "xmlParseEntityDecl: entity %s not terminated\n", name);
+           xmlHaltParser(ctxt);
        } else {
-           if (input != ctxt->input) {
+           if (inputid != ctxt->input->id) {
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-       "Entity declaration doesn't start and stop in the same entity\n");
+                              "Entity declaration doesn't start and stop in"
+                               " the same entity\n");
            }
            NEXT;
        }
@@ -5683,17 +5563,17 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
                    cur = xmlSAX2GetEntity(ctxt, name);
                }
            }
-            if (cur != NULL) {
-               if (cur->orig != NULL)
-                   xmlFree(orig);
-               else
-                   cur->orig = orig;
-           } else
-               xmlFree(orig);
+            if ((cur != NULL) && (cur->orig == NULL)) {
+               cur->orig = orig;
+                orig = NULL;
+           }
        }
+
+done:
        if (value != NULL) xmlFree(value);
        if (URI != NULL) xmlFree(URI);
        if (literal != NULL) xmlFree(literal);
+        if (orig != NULL) xmlFree(orig);
     }
 }
 
@@ -5744,11 +5624,10 @@ xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
     if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
        SKIP(6);
        val = XML_ATTRIBUTE_FIXED;
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after '#FIXED'\n");
        }
-       SKIP_BLANKS;
     }
     ret = xmlParseAttValue(ctxt);
     ctxt->instate = XML_PARSER_DTD;
@@ -5920,12 +5799,11 @@ int
 xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
     if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
        SKIP(8);
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after 'NOTATION'\n");
            return(0);
        }
-        SKIP_BLANKS;
        *tree = xmlParseNotationType(ctxt);
        if (*tree == NULL) return(0);
        return(XML_ATTRIBUTE_NOTATION);
@@ -6029,14 +5907,13 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
     xmlEnumerationPtr tree;
 
     if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
-       xmlParserInputPtr input = ctxt->input;
+       int inputid = ctxt->input->id;
 
        SKIP(9);
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                                 "Space required after '<!ATTLIST'\n");
        }
-        SKIP_BLANKS;
         elemName = xmlParseName(ctxt);
        if (elemName == NULL) {
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
@@ -6046,7 +5923,6 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
        SKIP_BLANKS;
        GROW;
        while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
-           const xmlChar *check = CUR_PTR;
            int type;
            int def;
            xmlChar *defaultValue = NULL;
@@ -6060,12 +5936,11 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
                break;
            }
            GROW;
-           if (!IS_BLANK_CH(CUR)) {
+           if (SKIP_BLANKS == 0) {
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                        "Space required after the attribute name\n");
                break;
            }
-           SKIP_BLANKS;
 
            type = xmlParseAttributeType(ctxt, &tree);
            if (type <= 0) {
@@ -6073,14 +5948,13 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
            }
 
            GROW;
-           if (!IS_BLANK_CH(CUR)) {
+           if (SKIP_BLANKS == 0) {
                xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                               "Space required after the attribute type\n");
                if (tree != NULL)
                    xmlFreeEnumeration(tree);
                break;
            }
-           SKIP_BLANKS;
 
            def = xmlParseDefaultDecl(ctxt, &defaultValue);
            if (def <= 0) {
@@ -6095,7 +5969,7 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
 
            GROW;
             if (RAW != '>') {
-               if (!IS_BLANK_CH(CUR)) {
+               if (SKIP_BLANKS == 0) {
                    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                        "Space required after the attribute default value\n");
                    if (defaultValue != NULL)
@@ -6104,16 +5978,6 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
                        xmlFreeEnumeration(tree);
                    break;
                }
-               SKIP_BLANKS;
-           }
-           if (check == CUR_PTR) {
-               xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
-                           "in xmlParseAttributeListDecl\n");
-               if (defaultValue != NULL)
-                   xmlFree(defaultValue);
-               if (tree != NULL)
-                   xmlFreeEnumeration(tree);
-               break;
            }
            if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
                (ctxt->sax->attributeDecl != NULL))
@@ -6135,10 +5999,10 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
            GROW;
        }
        if (RAW == '>') {
-           if (input != ctxt->input) {
-               xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-    "Attribute list declaration doesn't start and stop in the same entity\n",
-                                 NULL, NULL);
+           if (inputid != ctxt->input->id) {
+               xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                               "Attribute list declaration doesn't start and"
+                               " stop in the same entity\n");
            }
            NEXT;
        }
@@ -6175,10 +6039,10 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
        SKIP_BLANKS;
        SHRINK;
        if (RAW == ')') {
-           if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
-               xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-"Element content declaration doesn't start and stop in the same entity\n",
-                                 NULL, NULL);
+           if (ctxt->input->id != inputchk) {
+               xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                               "Element content declaration doesn't start and"
+                               " stop in the same entity\n");
            }
            NEXT;
            ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
@@ -6219,7 +6083,7 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
            if (elem == NULL) {
                xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
                        "xmlParseElementMixedContentDecl : Name expected\n");
-               xmlFreeDocElementContent(ctxt->myDoc, cur);
+               xmlFreeDocElementContent(ctxt->myDoc, ret);
                return(NULL);
            }
            SKIP_BLANKS;
@@ -6234,10 +6098,10 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
             }
             if (ret != NULL)
                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
-           if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
-               xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-"Element content declaration doesn't start and stop in the same entity\n",
-                                NULL, NULL);
+           if (ctxt->input->id != inputchk) {
+               xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                               "Element content declaration doesn't start and"
+                               " stop in the same entity\n");
            }
            SKIP(2);
        } else {
@@ -6477,10 +6341,10 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
        if (last != NULL)
            last->parent = cur;
     }
-    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
-       xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-"Element content declaration doesn't start and stop in the same entity\n",
-                        NULL, NULL);
+    if (ctxt->input->id != inputchk) {
+       xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                       "Element content declaration doesn't start and stop in"
+                       " the same entity\n");
     }
     NEXT;
     if (RAW == '?') {
@@ -6653,27 +6517,24 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
 
     /* GROW; done in the caller */
     if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
-       xmlParserInputPtr input = ctxt->input;
+       int inputid = ctxt->input->id;
 
        SKIP(9);
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after 'ELEMENT'\n");
+           return(-1);
        }
-        SKIP_BLANKS;
         name = xmlParseName(ctxt);
        if (name == NULL) {
            xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
                           "xmlParseElementDecl: no name for Element\n");
            return(-1);
        }
-       while ((RAW == 0) && (ctxt->inputNr > 1))
-           xmlPopInput(ctxt);
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space required after the element name\n");
        }
-        SKIP_BLANKS;
        if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
            SKIP(5);
            /*
@@ -6705,12 +6566,6 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
        }
 
        SKIP_BLANKS;
-       /*
-        * Pop-up of finished entities.
-        */
-       while ((RAW == 0) && (ctxt->inputNr > 1))
-           xmlPopInput(ctxt);
-       SKIP_BLANKS;
 
        if (RAW != '>') {
            xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
@@ -6718,9 +6573,10 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
                xmlFreeDocElementContent(ctxt->myDoc, content);
            }
        } else {
-           if (input != ctxt->input) {
+           if (inputid != ctxt->input->id) {
                xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
-    "Element declaration doesn't start and stop in the same entity\n");
+                               "Element declaration doesn't start and stop in"
+                               " the same entity\n");
            }
 
            NEXT;
@@ -6769,11 +6625,13 @@ 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,
-           "All markup of the conditional section is not in the same entity\n",
-                                    NULL, NULL);
+               xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                              "All markup of the conditional section is not"
+                               " in the same entity\n");
            }
            NEXT;
        }
@@ -6786,6 +6644,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
                    "Entering INCLUDE Conditional Section\n");
        }
 
+        SKIP_BLANKS;
+        GROW;
        while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
                (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
            const xmlChar *check = CUR_PTR;
@@ -6793,21 +6653,15 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
            if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
                xmlParseConditionalSections(ctxt);
-           } else if (IS_BLANK_CH(CUR)) {
-               NEXT;
-           } else if (RAW == '%') {
-               xmlParsePEReference(ctxt);
            } else
                xmlParseMarkupDecl(ctxt);
 
-           /*
-            * Pop-up of finished entities.
-            */
-           while ((RAW == 0) && (ctxt->inputNr > 1))
-               xmlPopInput(ctxt);
+            SKIP_BLANKS;
+            GROW;
 
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
                xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+               xmlHaltParser(ctxt);
                break;
            }
        }
@@ -6829,11 +6683,13 @@ 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,
-           "All markup of the conditional section is not in the same entity\n",
-                                    NULL, NULL);
+               xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                              "All markup of the conditional section is not"
+                               " in the same entity\n");
            }
            NEXT;
        }
@@ -6884,6 +6740,8 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
 
     } else {
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
+       xmlHaltParser(ctxt);
+       return;
     }
 
     if (RAW == 0)
@@ -6893,11 +6751,13 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
        xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
     } else {
        if (ctxt->input->id != id) {
-           xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
-       "All markup of the conditional section is not in the same entity\n",
-                                NULL, NULL);
+           xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+                          "All markup of the conditional section is not in"
+                           " the same entity\n");
        }
-        SKIP(3);
+       if ((ctxt-> instate != XML_PARSER_EOF) &&
+           ((ctxt->input->cur + 3) <= ctxt->input->end))
+           SKIP(3);
     }
 }
 
@@ -6952,12 +6812,13 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
            xmlParsePI(ctxt);
        }
     }
+
     /*
-     * This is only for internal subset. On external entities,
-     * the replacement is done before parsing stage
+     * detect requirement to exit there and act accordingly
+     * and avoid having instate overriden later on
      */
-    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
-       xmlParsePEReference(ctxt);
+    if (ctxt->instate == XML_PARSER_EOF)
+        return;
 
     /*
      * Conditional sections are allowed from entities included
@@ -6996,11 +6857,10 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
        return;
     }
 
-    if (!IS_BLANK_CH(CUR)) {
+    if (SKIP_BLANKS == 0) {
        xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                       "Space needed after '<?xml'\n");
     }
-    SKIP_BLANKS;
 
     /*
      * We may have the VersionInfo here.
@@ -7009,7 +6869,7 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
     if (version == NULL)
        version = xmlCharStrdup(XML_DEFAULT_VERSION);
     else {
-       if (!IS_BLANK_CH(CUR)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "Space needed here\n");
        }
@@ -7083,7 +6943,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;
        }
     }
@@ -7100,27 +6960,19 @@ xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
 
     ctxt->instate = XML_PARSER_DTD;
     ctxt->external = 1;
+    SKIP_BLANKS;
     while (((RAW == '<') && (NXT(1) == '?')) ||
            ((RAW == '<') && (NXT(1) == '!')) ||
-          (RAW == '%') || IS_BLANK_CH(CUR)) {
+          (RAW == '%')) {
        const xmlChar *check = CUR_PTR;
        unsigned int cons = ctxt->input->consumed;
 
        GROW;
         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
            xmlParseConditionalSections(ctxt);
-       } else if (IS_BLANK_CH(CUR)) {
-           NEXT;
-       } else if (RAW == '%') {
-            xmlParsePEReference(ctxt);
        } else
            xmlParseMarkupDecl(ctxt);
-
-       /*
-        * Pop-up of finished entities.
-        */
-       while ((RAW == 0) && (ctxt->inputNr > 1))
-           xmlPopInput(ctxt);
+        SKIP_BLANKS;
 
        if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
            xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
@@ -7235,7 +7087,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;
@@ -7348,6 +7201,9 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
        }
        if (ent->checked == 0)
            ent->checked = 2;
+
+        /* Prevent entity from being parsed and expanded twice (Bug 760367). */
+        was_checked = 0;
     } else if (ent->checked != 1) {
        ctxt->nbentities += ent->checked / 2;
     }
@@ -7984,12 +7840,14 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
     NEXT;
     name = xmlParseName(ctxt);
     if (name == NULL) {
-       xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
-                      "xmlParsePEReference: no name\n");
+       xmlFatalErrMsg(ctxt, XML_ERR_PEREF_NO_NAME, "PEReference: no name\n");
        return;
     }
+    if (xmlParserDebugEntities)
+       xmlGenericError(xmlGenericErrorContext,
+               "PEReference: %s\n", name);
     if (RAW != ';') {
-       xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
+       xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
         return;
     }
 
@@ -8031,10 +7889,15 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
             * ... The declaration of a parameter entity must
             * precede any reference to it...
             */
-           xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
-                         "PEReference: %%%s; not found\n",
-                         name, NULL);
-           ctxt->valid = 0;
+            if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
+                xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
+                                 "PEReference: %%%s; not found\n",
+                                 name, NULL);
+            } else
+                xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
+                              "PEReference: %%%s; not found\n",
+                              name, NULL);
+            ctxt->valid = 0;
        }
        xmlParserEntityCheck(ctxt, 0, NULL, 0);
     } else {
@@ -8046,33 +7909,54 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
            xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
                  "Internal: %%%s; is not a parameter entity\n",
                          name, NULL);
-       } else if (ctxt->input->free != deallocblankswrapper) {
-           input = xmlNewBlanksWrapperInputStream(ctxt, entity);
-           if (xmlPushInput(ctxt, input) < 0)
-               return;
        } else {
-           /*
-            * TODO !!!
-            * handle the extra spaces added before and after
-            * c.f. http://www.w3.org/TR/REC-xml#as-PE
-            */
+            xmlChar start[4];
+            xmlCharEncoding enc;
+
+           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;
+
            input = xmlNewEntityInputStream(ctxt, entity);
-           if (xmlPushInput(ctxt, input) < 0)
+           if (xmlPushInput(ctxt, input) < 0) {
+                xmlFreeInputStream(input);
                return;
-           if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
-               (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
-               (IS_BLANK_CH(NXT(5)))) {
-               xmlParseTextDecl(ctxt);
-               if (ctxt->errNo ==
-                   XML_ERR_UNSUPPORTED_ENCODING) {
-                   /*
-                    * The XML REC instructs us to stop parsing
-                    * right here
-                    */
-                   ctxt->instate = XML_PARSER_EOF;
-                   return;
-               }
-           }
+            }
+
+           if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) {
+                /*
+                 * Get the 4 first bytes and decode the charset
+                 * if enc != XML_CHAR_ENCODING_NONE
+                 * plug some encoding conversion routines.
+                 * Note that, since we may have some non-UTF8
+                 * encoding (like UTF16, bug 135229), the 'length'
+                 * is not known, but we can calculate based upon
+                 * the amount of data in the buffer.
+                 */
+                GROW
+                if (ctxt->instate == XML_PARSER_EOF)
+                    return;
+                if ((ctxt->input->end - ctxt->input->cur)>=4) {
+                    start[0] = RAW;
+                    start[1] = NXT(1);
+                    start[2] = NXT(2);
+                    start[3] = NXT(3);
+                    enc = xmlDetectCharEncoding(start, 4);
+                    if (enc != XML_CHAR_ENCODING_NONE) {
+                        xmlSwitchEncoding(ctxt, enc);
+                    }
+                }
+
+                if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
+                    (IS_BLANK_CH(NXT(5)))) {
+                    xmlParseTextDecl(ctxt);
+                }
+            }
        }
     }
     ctxt->hasPErefs = 1;
@@ -8248,6 +8132,7 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
        entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
     if (ctxt->instate == XML_PARSER_EOF) {
        xmlFree(name);
+       *str = ptr;
        return(NULL);
     }
     if (entity == NULL) {
@@ -8386,6 +8271,7 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
      * Is there any DTD definition ?
      */
     if (RAW == '[') {
+        int baseInputNr = ctxt->inputNr;
         ctxt->instate = XML_PARSER_DTD;
         NEXT;
        /*
@@ -8393,7 +8279,8 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
         * PEReferences.
         * Subsequence (markupdecl | PEReference | S)*
         */
-       while ((RAW != ']') && (ctxt->instate != XML_PARSER_EOF)) {
+       while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
+               (ctxt->instate != XML_PARSER_EOF)) {
            const xmlChar *check = CUR_PTR;
            unsigned int cons = ctxt->input->consumed;
 
@@ -8401,16 +8288,13 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
            xmlParseMarkupDecl(ctxt);
            xmlParsePEReference(ctxt);
 
-           /*
-            * Pop-up of finished entities.
-            */
-           while ((RAW == 0) && (ctxt->inputNr > 1))
-               xmlPopInput(ctxt);
-
            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
                xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
             "xmlParseInternalSubset: error detected in Markup declaration\n");
-               break;
+                if (ctxt->inputNr > baseInputNr)
+                    xmlPopInput(ctxt);
+                else
+                   break;
            }
        }
        if (RAW == ']') {
@@ -8424,6 +8308,7 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
      */
     if (RAW != '>') {
        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+       return;
     }
     NEXT;
 }
@@ -8487,7 +8372,7 @@ xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
        ctxt->instate = XML_PARSER_CONTENT;
     } else {
        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
-              "Specification mandate value for attribute %s\n", name);
+              "Specification mandates value for attribute %s\n", name);
        return(NULL);
     }
 
@@ -8644,11 +8529,10 @@ failed:
        GROW
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
            break;
-       if (!IS_BLANK_CH(RAW)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "attributes construct error\n");
        }
-       SKIP_BLANKS;
         if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
             (attname == NULL) && (attvalue == NULL)) {
            xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
@@ -8774,7 +8658,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
  */
@@ -9186,8 +9070,8 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
     if (ctxt->attsSpecial != NULL) {
         int type;
 
-        type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
-                                            pref, elem, *prefix, name);
+        type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial,
+                                                 pref, elem, *prefix, name);
         if (type != 0)
             normalize = 1;
     }
@@ -9220,7 +9104,7 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
         ctxt->instate = XML_PARSER_CONTENT;
     } else {
         xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
-                          "Specification mandate value for attribute %s\n",
+                          "Specification mandates value for attribute %s\n",
                           name);
         return (NULL);
     }
@@ -9303,9 +9187,8 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
     xmlChar *attvalue;
     const xmlChar **atts = ctxt->atts;
     int maxatts = ctxt->maxatts;
-    int nratts, nbatts, nbdef;
-    int i, j, nbNs, attval, oldline, oldcol;
-    const xmlChar *base;
+    int nratts, nbatts, nbdef, inputid;
+    int i, j, nbNs, attval;
     unsigned long cur;
     int nsNr = ctxt->nsNr;
 
@@ -9319,12 +9202,9 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
      *       The Shrinking is only possible once the full set of attribute
      *       callbacks have been done.
      */
-reparse:
     SHRINK;
-    base = ctxt->input->base;
     cur = ctxt->input->cur - ctxt->input->base;
-    oldline = ctxt->input->line;
-    oldcol = ctxt->input->col;
+    inputid = ctxt->input->id;
     nbatts = 0;
     nratts = 0;
     nbdef = 0;
@@ -9348,7 +9228,6 @@ reparse:
      */
     SKIP_BLANKS;
     GROW;
-    if (ctxt->input->base != base) goto base_changed;
 
     while (((RAW != '>') &&
           ((RAW != '/') || (NXT(1) != '>')) &&
@@ -9359,201 +9238,181 @@ reparse:
 
        attname = xmlParseAttribute2(ctxt, prefix, localname,
                                     &aprefix, &attvalue, &len, &alloc);
-       if (ctxt->input->base != base) {
-           if ((attvalue != NULL) && (alloc != 0))
-               xmlFree(attvalue);
-           attvalue = NULL;
-           goto base_changed;
-       }
-        if ((attname != NULL) && (attvalue != NULL)) {
-           if (len < 0) len = xmlStrlen(attvalue);
-            if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
-               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) {
-                       xmlNsErr(ctxt, XML_WAR_NS_URI,
-                                "xmlns: '%s' is not a valid URI\n",
-                                          URL, NULL, NULL);
-                   } else {
-                       if (uri->scheme == NULL) {
-                           xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
-                                     "xmlns: URI %s is not absolute\n",
-                                     URL, NULL, NULL);
-                       }
-                       xmlFreeURI(uri);
-                   }
-                   if (URL == ctxt->str_xml_ns) {
-                       if (attname != ctxt->str_xml) {
-                           xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
-                        "xml namespace URI cannot be the default namespace\n",
-                                    NULL, NULL, NULL);
-                       }
-                       goto skip_default_ns;
-                   }
-                   if ((len == 29) &&
-                       (xmlStrEqual(URL,
-                                BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
-                       xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
-                            "reuse of the xmlns namespace name is forbidden\n",
-                                NULL, NULL, NULL);
-                       goto skip_default_ns;
-                   }
-               }
-               /*
-                * check that it's not a defined namespace
-                */
-               for (j = 1;j <= nbNs;j++)
-                   if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
-                       break;
-               if (j <= nbNs)
-                   xmlErrAttributeDup(ctxt, NULL, attname);
-               else
-                   if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
-skip_default_ns:
-               if (alloc != 0) xmlFree(attvalue);
-               if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
-                   break;
-               if (!IS_BLANK_CH(RAW)) {
-                   xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-                                  "attributes construct error\n");
-                   break;
-               }
-               SKIP_BLANKS;
-               continue;
-           }
-            if (aprefix == ctxt->str_xmlns) {
-               const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
-               xmlURIPtr uri;
-
-                if (attname == ctxt->str_xml) {
-                   if (URL != ctxt->str_xml_ns) {
-                       xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
-                                "xml namespace prefix mapped to wrong URI\n",
-                                NULL, NULL, NULL);
-                   }
-                   /*
-                    * Do not keep a namespace definition node
-                    */
-                   goto skip_ns;
-               }
+        if ((attname == NULL) || (attvalue == NULL))
+            goto next_attr;
+       if (len < 0) len = xmlStrlen(attvalue);
+
+        if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
+            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) {
+                    xmlNsErr(ctxt, XML_WAR_NS_URI,
+                             "xmlns: '%s' is not a valid URI\n",
+                                       URL, NULL, NULL);
+                } else {
+                    if (uri->scheme == NULL) {
+                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
+                                  "xmlns: URI %s is not absolute\n",
+                                  URL, NULL, NULL);
+                    }
+                    xmlFreeURI(uri);
+                }
                 if (URL == ctxt->str_xml_ns) {
-                   if (attname != ctxt->str_xml) {
-                       xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
-                                "xml namespace URI mapped to wrong prefix\n",
-                                NULL, NULL, NULL);
-                   }
-                   goto skip_ns;
-               }
-                if (attname == ctxt->str_xmlns) {
-                   xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
-                            "redefinition of the xmlns prefix is forbidden\n",
-                            NULL, NULL, NULL);
-                   goto skip_ns;
-               }
-               if ((len == 29) &&
-                   (xmlStrEqual(URL,
-                                BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
-                   xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
-                            "reuse of the xmlns namespace name is forbidden\n",
-                            NULL, NULL, NULL);
-                   goto skip_ns;
-               }
-               if ((URL == NULL) || (URL[0] == 0)) {
-                   xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
-                            "xmlns:%s: Empty XML namespace is not allowed\n",
-                                 attname, NULL, NULL);
-                   goto skip_ns;
-               } else {
-                   uri = xmlParseURI((const char *) URL);
-                   if (uri == NULL) {
-                       xmlNsErr(ctxt, XML_WAR_NS_URI,
-                            "xmlns:%s: '%s' is not a valid URI\n",
-                                          attname, URL, NULL);
-                   } else {
-                       if ((ctxt->pedantic) && (uri->scheme == NULL)) {
-                           xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
-                                     "xmlns:%s: URI %s is not absolute\n",
-                                     attname, URL, NULL);
-                       }
-                       xmlFreeURI(uri);
-                   }
-               }
-
-               /*
-                * check that it's not a defined namespace
-                */
-               for (j = 1;j <= nbNs;j++)
-                   if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
-                       break;
-               if (j <= nbNs)
-                   xmlErrAttributeDup(ctxt, aprefix, attname);
-               else
-                   if (nsPush(ctxt, attname, URL) > 0) nbNs++;
-skip_ns:
-               if (alloc != 0) xmlFree(attvalue);
-               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;
-               continue;
-           }
+                    if (attname != ctxt->str_xml) {
+                        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+                     "xml namespace URI cannot be the default namespace\n",
+                                 NULL, NULL, NULL);
+                    }
+                    goto next_attr;
+                }
+                if ((len == 29) &&
+                    (xmlStrEqual(URL,
+                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
+                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+                         "reuse of the xmlns namespace name is forbidden\n",
+                             NULL, NULL, NULL);
+                    goto next_attr;
+                }
+            }
+            /*
+             * check that it's not a defined namespace
+             */
+            for (j = 1;j <= nbNs;j++)
+                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
+                    break;
+            if (j <= nbNs)
+                xmlErrAttributeDup(ctxt, NULL, attname);
+            else
+                if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
+
+        } else if (aprefix == ctxt->str_xmlns) {
+            const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
+            xmlURIPtr uri;
+
+            if (attname == ctxt->str_xml) {
+                if (URL != ctxt->str_xml_ns) {
+                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+                             "xml namespace prefix mapped to wrong URI\n",
+                             NULL, NULL, NULL);
+                }
+                /*
+                 * Do not keep a namespace definition node
+                 */
+                goto next_attr;
+            }
+            if (URL == ctxt->str_xml_ns) {
+                if (attname != ctxt->str_xml) {
+                    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+                             "xml namespace URI mapped to wrong prefix\n",
+                             NULL, NULL, NULL);
+                }
+                goto next_attr;
+            }
+            if (attname == ctxt->str_xmlns) {
+                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+                         "redefinition of the xmlns prefix is forbidden\n",
+                         NULL, NULL, NULL);
+                goto next_attr;
+            }
+            if ((len == 29) &&
+                (xmlStrEqual(URL,
+                             BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
+                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+                         "reuse of the xmlns namespace name is forbidden\n",
+                         NULL, NULL, NULL);
+                goto next_attr;
+            }
+            if ((URL == NULL) || (URL[0] == 0)) {
+                xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+                         "xmlns:%s: Empty XML namespace is not allowed\n",
+                              attname, NULL, NULL);
+                goto next_attr;
+            } else {
+                uri = xmlParseURI((const char *) URL);
+                if (uri == NULL) {
+                    xmlNsErr(ctxt, XML_WAR_NS_URI,
+                         "xmlns:%s: '%s' is not a valid URI\n",
+                                       attname, URL, NULL);
+                } else {
+                    if ((ctxt->pedantic) && (uri->scheme == NULL)) {
+                        xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
+                                  "xmlns:%s: URI %s is not absolute\n",
+                                  attname, URL, NULL);
+                    }
+                    xmlFreeURI(uri);
+                }
+            }
 
-           /*
-            * Add the pair to atts
-            */
-           if ((atts == NULL) || (nbatts + 5 > maxatts)) {
-               if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
-                   if (attvalue[len] == 0)
-                       xmlFree(attvalue);
-                   goto failed;
-               }
-               maxatts = ctxt->maxatts;
-               atts = ctxt->atts;
-           }
-           ctxt->attallocs[nratts++] = alloc;
-           atts[nbatts++] = attname;
-           atts[nbatts++] = aprefix;
-           atts[nbatts++] = NULL; /* the URI will be fetched later */
-           atts[nbatts++] = attvalue;
-           attvalue += len;
-           atts[nbatts++] = attvalue;
-           /*
-            * tag if some deallocation is needed
-            */
-           if (alloc != 0) attval = 1;
-       } else {
-           if ((attvalue != NULL) && (attvalue[len] == 0))
-               xmlFree(attvalue);
-       }
+            /*
+             * check that it's not a defined namespace
+             */
+            for (j = 1;j <= nbNs;j++)
+                if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
+                    break;
+            if (j <= nbNs)
+                xmlErrAttributeDup(ctxt, aprefix, attname);
+            else
+                if (nsPush(ctxt, attname, URL) > 0) nbNs++;
+
+        } else {
+            /*
+             * Add the pair to atts
+             */
+            if ((atts == NULL) || (nbatts + 5 > maxatts)) {
+                if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
+                    goto next_attr;
+                }
+                maxatts = ctxt->maxatts;
+                atts = ctxt->atts;
+            }
+            ctxt->attallocs[nratts++] = alloc;
+            atts[nbatts++] = attname;
+            atts[nbatts++] = aprefix;
+            /*
+             * The namespace URI field is used temporarily to point at the
+             * base of the current input buffer for non-alloced attributes.
+             * When the input buffer is reallocated, all the pointers become
+             * invalid, but they can be reconstructed later.
+             */
+            if (alloc)
+                atts[nbatts++] = NULL;
+            else
+                atts[nbatts++] = ctxt->input->base;
+            atts[nbatts++] = attvalue;
+            attvalue += len;
+            atts[nbatts++] = attvalue;
+            /*
+             * tag if some deallocation is needed
+             */
+            if (alloc != 0) attval = 1;
+            attvalue = NULL; /* moved into atts */
+        }
 
-failed:
+next_attr:
+        if ((attvalue != NULL) && (alloc != 0)) {
+            xmlFree(attvalue);
+            attvalue = NULL;
+        }
 
        GROW
         if (ctxt->instate == XML_PARSER_EOF)
             break;
-       if (ctxt->input->base != base) goto base_changed;
        if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
            break;
-       if (!IS_BLANK_CH(RAW)) {
+       if (SKIP_BLANKS == 0) {
            xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
                           "attributes construct error\n");
            break;
        }
-       SKIP_BLANKS;
         if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
             (attname == NULL) && (attvalue == NULL)) {
            xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
@@ -9561,7 +9420,27 @@ failed:
            break;
        }
         GROW;
-       if (ctxt->input->base != base) goto base_changed;
+    }
+
+    if (ctxt->input->id != inputid) {
+        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+                    "Unexpected change of input\n");
+        localname = NULL;
+        goto done;
+    }
+
+    /* Reconstruct attribute value pointers. */
+    for (i = 0, j = 0; j < nratts; i += 5, j++) {
+        if (atts[i+2] != NULL) {
+            /*
+             * Arithmetic on dangling pointers is technically undefined
+             * behavior, but well...
+             */
+            ptrdiff_t offset = ctxt->input->base - atts[i+2];
+            atts[i+2]  = NULL;    /* Reset repurposed namespace URI */
+            atts[i+3] += offset;  /* value */
+            atts[i+4] += offset;  /* valuend */
+        }
     }
 
     /*
@@ -9708,6 +9587,7 @@ failed:
                          nsname, 0, NULL, nbatts / 5, nbdef, atts);
     }
 
+done:
     /*
      * Free up attribute allocated strings if needed
      */
@@ -9718,23 +9598,6 @@ failed:
     }
 
     return(localname);
-
-base_changed:
-    /*
-     * the attribute strings are valid iif the base didn't changed
-     */
-    if (attval != 0) {
-       for (i = 3,j = 0; j < nratts;i += 5,j++)
-           if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
-               xmlFree((xmlChar *) atts[i]);
-    }
-    ctxt->input->cur = ctxt->input->base + cur;
-    ctxt->input->line = oldline;
-    ctxt->input->col = oldcol;
-    if (ctxt->wellFormed == 1) {
-       goto reparse;
-    }
-    return(NULL);
 }
 
 /**
@@ -9756,6 +9619,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 +9628,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;
@@ -9999,17 +9866,12 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
        }
 
        GROW;
-       /*
-        * Pop-up of finished entities.
-        */
-       while ((RAW == 0) && (ctxt->inputNr > 1))
-           xmlPopInput(ctxt);
        SHRINK;
 
        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 +9906,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 +10258,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 +10267,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 +10325,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 +10498,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 +10623,7 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
 
     if (CUR == 0) {
        xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+       return(-1);
     }
 
     /*
@@ -10769,7 +10641,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,16 +11011,17 @@ 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]
  *
  * Returns the number of bytes to pass if okay, a negative index where an
- *         UTF-8 error occured otherwise
+ *         UTF-8 error occurred 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 +11039,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 +11048,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 +11059,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))
@@ -11286,13 +11160,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
        if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
            return(0);
 
-
-       /*
-        * Pop-up of finished entities.
-        */
-       while ((RAW == 0) && (ctxt->inputNr > 1))
-           xmlPopInput(ctxt);
-
        if (ctxt->input == NULL) break;
        if (ctxt->input->buf == NULL)
            avail = ctxt->input->length -
@@ -11363,7 +11230,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 +11263,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 +11319,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 +11351,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;
@@ -11643,15 +11510,10 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                    ctxt->checkIndex = 0;
                    xmlParseCharData(ctxt, 0);
                }
-               /*
-                * Pop-up of finished entities.
-                */
-               while ((RAW == 0) && (ctxt->inputNr > 1))
-                   xmlPopInput(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;
                }
                break;
@@ -11670,9 +11532,10 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
                }
                if (ctxt->sax2) {
                    xmlParseEndTag2(ctxt,
-                          (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
-                          (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
-                      (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
+                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
+                           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
+                           (int) (ptrdiff_t)
+                                ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
                    nameNsPop(ctxt);
                }
 #ifdef LIBXML_SAX1_ENABLED
@@ -11700,7 +11563,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 +11586,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 +11835,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 +12199,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 +12253,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 +12441,50 @@ 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;
+    while (ctxt->inputNr > 1)
+        xmlFreeInputStream(inputPop(ctxt));
     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;
+        ctxt->input->end = 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,21 +13228,23 @@ 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);
     }
     /*
      * And record the last error if any
      */
-    if (ctxt->lastError.code != XML_ERR_OK)
+    if ((oldctxt != NULL) && (ctxt->lastError.code != XML_ERR_OK))
         xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
 
     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 +14720,6 @@ xmlInitParser(void) {
 #ifdef LIBXML_XPATH_ENABLED
        xmlXPathInit();
 #endif
-#ifdef LIBXML_CATALOG_ENABLED
-        xmlInitializeCatalog();
-#endif
        xmlParserInitialized = 1;
 #ifdef LIBXML_THREAD_ENABLED
     }
@@ -14897,7 +14784,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)                                         \