aboutsummaryrefslogtreecommitdiffstats
path: root/parser.c
diff options
context:
space:
mode:
authorakirilov <akirilov@google.com>2018-06-01 13:46:04 -0700
committersyphyr <syphyr@gmail.com>2018-09-06 04:08:09 +0200
commit126c3993d2ad55db2abfe80e3d671bf584e7b13b (patch)
treef4464c225863c997e3f99d9897131f9f28df76fe /parser.c
parent521b88fbb6d18312923f0df653d045384b500ffc (diff)
downloadandroid_external_libxml2-126c3993d2ad55db2abfe80e3d671bf584e7b13b.tar.gz
android_external_libxml2-126c3993d2ad55db2abfe80e3d671bf584e7b13b.tar.bz2
android_external_libxml2-126c3993d2ad55db2abfe80e3d671bf584e7b13b.zip
Merge to pi-dev and restore Android.mk Bug: 79662501 Bug: 36809766 Bug: 36810305 Bug: 62151041 Test: manually verify functionality for regression Change-Id: Ife351c91c932eb92992656f8ea5c08724a220306 (cherry picked from commit 4e91cfdbb1a8624e5cd5a850d6e17da11d1e34a8)
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c1310
1 files changed, 527 insertions, 783 deletions
diff --git a/parser.c b/parser.c
index 63ae15f0..ca9fde2c 100644
--- a/parser.c
+++ b/parser.c
@@ -30,10 +30,15 @@
* 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>
@@ -77,12 +83,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-#ifdef HAVE_LZMA_H
-#include <lzma.h>
-#endif
#include "buf.h"
#include "enc.h"
@@ -149,7 +149,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF, 0, 0, 0);
--ctxt->depth;
- if (ctxt->errNo == XML_ERR_ENTITY_LOOP) {
+ if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
ent->content[0] = 0;
}
@@ -1087,7 +1087,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
};
/**
@@ -1324,7 +1329,7 @@ xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
return;
xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
- (void *) (long) type);
+ (void *) (ptrdiff_t) type);
return;
mem_error:
@@ -1343,7 +1348,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);
}
}
@@ -1855,7 +1860,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);
@@ -2037,10 +2042,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 { \
@@ -2052,10 +2055,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) && \
@@ -2065,10 +2066,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)) \
@@ -2080,7 +2080,8 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) {
if (((curEnd > (unsigned long) XML_MAX_LOOKUP_LIMIT) ||
(curBase > (unsigned long) XML_MAX_LOOKUP_LIMIT)) &&
- ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) &&
+ ((ctxt->input->buf) &&
+ (ctxt->input->buf->readcallback != xmlInputReadCallbackNop)) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
xmlHaltParser(ctxt);
@@ -2093,9 +2094,8 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
return;
}
- if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
- (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
- xmlPopInput(ctxt);
+ if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0))
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
}
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
@@ -2115,7 +2115,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)
@@ -2165,26 +2164,35 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
}
ctxt->input->cur = cur;
} else {
- int cur;
- do {
- cur = CUR;
- while ((IS_BLANK_CH(cur) && /* CHECKED tstblanks.xml */
- (ctxt->instate != XML_PARSER_EOF))) {
+ 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 */
- (ctxt->instate != XML_PARSER_EOF));
+ } 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);
}
@@ -2210,10 +2218,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);
}
@@ -2239,6 +2250,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);
@@ -2444,57 +2462,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
*
@@ -2528,11 +2495,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;
@@ -2587,128 +2549,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);
}
/*
@@ -2790,9 +2631,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);
}
@@ -2802,9 +2643,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;
@@ -2818,30 +2656,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 ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
- (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
- goto int_error;
-
- if (rep != NULL) {
- current = rep;
- while (*current != 0) { /* non input consuming loop */
- 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;
@@ -2859,8 +2694,6 @@ 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;
@@ -2886,19 +2719,19 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
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);
@@ -3406,13 +3239,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) &&
@@ -3420,15 +3246,18 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
return(NULL);
}
- if (ctxt->input->cur > ctxt->input->base && (*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) {
- if (ctxt->input->base > ctxt->input->cur - (len + 1)) {
- return(NULL);
- }
- return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
- }
- if (ctxt->input->base > ctxt->input->cur - len) {
- 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));
}
@@ -3541,9 +3370,9 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
*/
ctxt->input->cur -= l;
GROW;
- ctxt->input->cur += l;
if (ctxt->instate == XML_PARSER_EOF)
return(NULL);
+ ctxt->input->cur += l;
c = CUR_CHAR(l);
}
}
@@ -3899,10 +3728,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);
/*
@@ -3923,18 +3750,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);
@@ -3944,10 +3765,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
@@ -3959,20 +3783,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;
}
@@ -3981,28 +3810,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.
- */
- ++ctxt->depth;
- ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
- 0, 0, 0);
- --ctxt->depth;
- 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);
}
@@ -4172,7 +3997,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
ent->checked |= 1;
xmlFree(rep);
rep = NULL;
- }
+ } else {
+ ent->content[0] = 0;
+ }
}
/*
@@ -4596,7 +4423,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++;
@@ -4789,22 +4616,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);
@@ -4813,26 +4638,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);
@@ -4962,7 +4781,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) &&
@@ -5110,7 +4930,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) &&
@@ -5278,7 +5099,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;
/*
@@ -5294,9 +5115,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);
@@ -5317,12 +5139,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) != '>'))) {
@@ -5378,9 +5198,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);
@@ -5436,32 +5257,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.
@@ -5470,9 +5289,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) &&
@@ -5516,23 +5336,20 @@ 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");
}
@@ -5550,8 +5367,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");
}
@@ -5662,18 +5478,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))
@@ -5712,16 +5526,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;
}
@@ -5743,17 +5558,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);
}
}
@@ -5804,11 +5619,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;
@@ -5980,12 +5794,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);
@@ -6089,14 +5902,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,
@@ -6106,7 +5918,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;
@@ -6120,12 +5931,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) {
@@ -6133,14 +5943,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) {
@@ -6155,7 +5964,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)
@@ -6164,16 +5973,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))
@@ -6195,10 +5994,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;
}
@@ -6235,10 +6034,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);
@@ -6279,7 +6078,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;
@@ -6294,10 +6093,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 {
@@ -6537,10 +6336,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 == '?') {
@@ -6713,28 +6512,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);
/*
@@ -6766,12 +6561,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);
@@ -6779,9 +6568,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;
@@ -6834,9 +6624,9 @@ xmlParseConditionalSections(xmlParserCtxtPtr 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;
}
@@ -6849,6 +6639,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;
@@ -6856,18 +6648,11 @@ 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);
@@ -6897,9 +6682,9 @@ xmlParseConditionalSections(xmlParserCtxtPtr 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;
}
@@ -6961,9 +6746,9 @@ 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");
}
if ((ctxt-> instate != XML_PARSER_EOF) &&
((ctxt->input->cur + 3) <= ctxt->input->end))
@@ -7031,13 +6816,6 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
return;
/*
- * This is only for internal subset. On external entities,
- * the replacement is done before parsing stage
- */
- if ((ctxt->external == 0) && (ctxt->inputNr == 1))
- xmlParsePEReference(ctxt);
-
- /*
* Conditional sections are allowed from entities included
* by PE References in the internal subset.
*/
@@ -7074,11 +6852,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.
@@ -7087,7 +6864,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");
}
@@ -7178,27 +6955,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);
@@ -7420,6 +7189,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
(ret != XML_WAR_UNDECLARED_ENTITY)) {
xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
"Entity '%s' failed to parse\n", ent->name);
+ if (ent->content != NULL)
+ ent->content[0] = 0;
xmlParserEntityCheck(ctxt, 0, ent, 0);
} else if (list != NULL) {
xmlFreeNodeList(list);
@@ -7427,6 +7198,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;
}
@@ -8063,12 +7837,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;
}
@@ -8110,10 +7886,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 {
@@ -8125,41 +7906,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 {
+ 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;
- /*
- * TODO !!!
- * handle the extra spaces added before and after
- * c.f. http://www.w3.org/TR/REC-xml#as-PE
- */
+ ((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
- */
- xmlHaltParser(ctxt);
- 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;
@@ -8335,6 +8129,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) {
@@ -8473,6 +8268,7 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
* Is there any DTD definition ?
*/
if (RAW == '[') {
+ int baseInputNr = ctxt->inputNr;
ctxt->instate = XML_PARSER_DTD;
NEXT;
/*
@@ -8480,7 +8276,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;
@@ -8488,16 +8285,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 == ']') {
@@ -8575,7 +8369,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);
}
@@ -8732,11 +8526,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,
@@ -9274,8 +9067,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;
}
@@ -9308,7 +9101,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);
}
@@ -9391,9 +9184,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, inputNr;
- const xmlChar *base;
+ int nratts, nbatts, nbdef, inputid;
+ int i, j, nbNs, attval;
unsigned long cur;
int nsNr = ctxt->nsNr;
@@ -9407,13 +9199,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;
- inputNr = ctxt->inputNr;
- oldline = ctxt->input->line;
- oldcol = ctxt->input->col;
+ inputid = ctxt->input->id;
nbatts = 0;
nratts = 0;
nbdef = 0;
@@ -9437,8 +9225,6 @@ reparse:
*/
SKIP_BLANKS;
GROW;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- goto base_changed;
while (((RAW != '>') &&
((RAW != '/') || (NXT(1) != '>')) &&
@@ -9449,211 +9235,181 @@ reparse:
attname = xmlParseAttribute2(ctxt, prefix, localname,
&aprefix, &attvalue, &len, &alloc);
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr)) {
- 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 ((attvalue != NULL) && (alloc != 0)) {
- xmlFree(attvalue);
- attvalue = NULL;
- }
- if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
- break;
- if (!IS_BLANK_CH(RAW)) {
- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "attributes construct error\n");
- break;
- }
- SKIP_BLANKS;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- goto base_changed;
- continue;
- }
- if (aprefix == ctxt->str_xmlns) {
- 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 ((attvalue != NULL) && (alloc != 0)) {
- xmlFree(attvalue);
- attvalue = NULL;
- }
- if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
- break;
- if (!IS_BLANK_CH(RAW)) {
- xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
- "attributes construct error\n");
- break;
- }
- SKIP_BLANKS;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- goto base_changed;
- continue;
- }
+ if (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) || (inputNr != ctxt->inputNr))
- 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,
@@ -9661,8 +9417,27 @@ failed:
break;
}
GROW;
- if ((ctxt->input->base != base) || (inputNr != ctxt->inputNr))
- 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 */
+ }
}
/*
@@ -9809,6 +9584,7 @@ failed:
nsname, 0, NULL, nbatts / 5, nbdef, atts);
}
+done:
/*
* Free up attribute allocated strings if needed
*/
@@ -9819,34 +9595,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]);
- }
-
- /*
- * We can't switch from one entity to another in the middle
- * of a start tag
- */
- if (inputNr != ctxt->inputNr) {
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "Start tag doesn't start and stop in the same entity\n");
- return(NULL);
- }
-
- ctxt->input->cur = ctxt->input->base + cur;
- ctxt->input->line = oldline;
- ctxt->input->col = oldcol;
- if (ctxt->wellFormed == 1) {
- goto reparse;
- }
- return(NULL);
}
/**
@@ -10115,11 +9863,6 @@ 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)) {
@@ -11272,7 +11015,7 @@ xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
* 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, int complete) {
@@ -11414,13 +11157,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 -
@@ -11771,11 +11507,6 @@ 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");
@@ -11798,9 +11529,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
@@ -12486,6 +12218,7 @@ xmldecl_done:
/* TODO 2.6.0 */
xmlGenericError(xmlGenericErrorContext,
"xmlParseChunk: encoder error\n");
+ xmlHaltParser(ctxt);
return(XML_ERR_INVALID_ENCODING);
}
xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
@@ -12718,6 +12451,8 @@ xmlHaltParser(xmlParserCtxtPtr ctxt) {
return;
ctxt->instate = XML_PARSER_EOF;
ctxt->disableSAX = 1;
+ while (ctxt->inputNr > 1)
+ xmlFreeInputStream(inputPop(ctxt));
if (ctxt->input != NULL) {
/*
* in case there was a specific allocation deallocate before
@@ -12729,6 +12464,7 @@ xmlHaltParser(xmlParserCtxtPtr ctxt) {
}
ctxt->input->cur = BAD_CAST"";
ctxt->input->base = ctxt->input->cur;
+ ctxt->input->end = ctxt->input->cur;
}
}
@@ -13497,7 +13233,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
/*
* 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)
@@ -13631,6 +13367,7 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
ctxt->userData = ctxt;
if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
ctxt->dict = oldctxt->dict;
+ ctxt->input_id = oldctxt->input_id + 1;
ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
@@ -13884,6 +13621,7 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
xmlDetectSAX2(ctxt);
ctxt->myDoc = doc;
/* parsing in context, i.e. as within existing content */
+ ctxt->input_id = 2;
ctxt->instate = XML_PARSER_CONTENT;
fake = xmlNewComment(NULL);
@@ -14096,6 +13834,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
newDoc->oldNs = doc->oldNs;
}
ctxt->instate = XML_PARSER_CONTENT;
+ ctxt->input_id = 2;
ctxt->depth = depth;
/*
@@ -14256,6 +13995,11 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
if (pctx != NULL) {
ctxt->options = pctx->options;
ctxt->_private = pctx->_private;
+ /*
+ * this is a subparser of pctx, so the input_id should be
+ * incremented to distinguish from main entity
+ */
+ ctxt->input_id = pctx->input_id + 1;
}
uri = xmlBuildURI(URL, base);
@@ -15137,7 +14881,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
xmlInitNodeInfoSeq(&ctxt->node_seq);
if (ctxt->attsDefault != NULL) {
- xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
+ xmlHashFree(ctxt->attsDefault, xmlHashDefaultDeallocator);
ctxt->attsDefault = NULL;
}
if (ctxt->attsSpecial != NULL) {