summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorMike Hommey <glandium@debian.org>2006-10-26 11:17:37 +0200
committerMike Hommey <glandium@debian.org>2006-10-26 11:17:37 +0200
commit968041a8b2ec86c39b5074024ce97d136ecd9a95 (patch)
tree6971d7bce63213fd376b0e66311d0c67a8da4d64 /parser.c
parenta7e9d3f37d5e9fba4b9acaa43e7c12b6d9a669ae (diff)
downloadlibxml2-upstream/2.6.27.dfsg.tar.gz
Load /tmp/libxml2-2.6.27 intoupstream/2.6.27.dfsg
libxml2/branches/upstream/current.
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c197
1 files changed, 151 insertions, 46 deletions
diff --git a/parser.c b/parser.c
index 12b2d7f..bd44585 100644
--- a/parser.c
+++ b/parser.c
@@ -807,6 +807,12 @@ xmlHasFeature(xmlFeature feature)
#else
return(0);
#endif
+ case XML_WITH_ZLIB:
+#ifdef LIBXML_ZLIB_ENABLED
+ return(1);
+#else
+ return(0);
+#endif
default:
break;
}
@@ -1442,7 +1448,7 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
if (ctxt->spaceNr > 0)
ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
else
- ctxt->space = NULL;
+ ctxt->space = &ctxt->spaceTab[0];
ret = ctxt->spaceTab[ctxt->spaceNr];
ctxt->spaceTab[ctxt->spaceNr] = -1;
return(ret);
@@ -2356,7 +2362,8 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
/*
* Check for xml:space value.
*/
- if (*(ctxt->space) == 1)
+ if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
+ (*(ctxt->space) == -2))
return(0);
/*
@@ -2485,10 +2492,12 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
buffer[len] = 0;
}
- /* nasty but well=formed
if ((c == ':') && (*cur == 0)) {
+ if (buffer != NULL)
+ xmlFree(buffer);
+ *prefix = NULL;
return(xmlStrdup(name));
- } */
+ }
if (buffer == NULL)
ret = xmlStrndup(buf, len);
@@ -3500,9 +3509,13 @@ get_more_space:
if (ctxt->sax->ignorableWhitespace != NULL)
ctxt->sax->ignorableWhitespace(ctxt->userData,
tmp, nbchar);
- } else if (ctxt->sax->characters != NULL)
- ctxt->sax->characters(ctxt->userData,
- tmp, nbchar);
+ } else {
+ if (ctxt->sax->characters != NULL)
+ ctxt->sax->characters(ctxt->userData,
+ tmp, nbchar);
+ if (*ctxt->space == -1)
+ *ctxt->space = -2;
+ }
} else if ((ctxt->sax != NULL) &&
(ctxt->sax->characters != NULL)) {
ctxt->sax->characters(ctxt->userData,
@@ -3549,9 +3562,13 @@ get_more:
if (ctxt->sax->ignorableWhitespace != NULL)
ctxt->sax->ignorableWhitespace(ctxt->userData,
tmp, nbchar);
- } else if (ctxt->sax->characters != NULL)
- ctxt->sax->characters(ctxt->userData,
- tmp, nbchar);
+ } else {
+ if (ctxt->sax->characters != NULL)
+ ctxt->sax->characters(ctxt->userData,
+ tmp, nbchar);
+ if (*ctxt->space == -1)
+ *ctxt->space = -2;
+ }
line = ctxt->input->line;
col = ctxt->input->col;
} else if (ctxt->sax != NULL) {
@@ -3634,6 +3651,10 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
} else {
if (ctxt->sax->characters != NULL)
ctxt->sax->characters(ctxt->userData, buf, nbchar);
+ if ((ctxt->sax->characters !=
+ ctxt->sax->ignorableWhitespace) &&
+ (*ctxt->space == -1))
+ *ctxt->space = -2;
}
}
nbchar = 0;
@@ -3658,6 +3679,9 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
} else {
if (ctxt->sax->characters != NULL)
ctxt->sax->characters(ctxt->userData, buf, nbchar);
+ if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
+ (*ctxt->space == -1))
+ *ctxt->space = -2;
}
}
}
@@ -5923,10 +5947,13 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
ctxt->sax->characters(ctxt->userData, out, i);
}
} else {
+ int was_checked;
+
ent = xmlParseEntityRef(ctxt);
if (ent == NULL) return;
if (!ctxt->wellFormed)
return;
+ was_checked = ent->checked;
if ((ent->name != NULL) &&
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
xmlNodePtr list = NULL;
@@ -5938,8 +5965,9 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
* where the ent->children is filled with the result from
* the parsing.
*/
- if (ent->children == NULL) {
+ if (ent->checked == 0) {
xmlChar *value;
+
value = ent->content;
/*
@@ -6074,15 +6102,69 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
list = NULL;
}
}
+ ent->checked = 1;
+ }
+
+ if (ent->children == NULL) {
+ /*
+ * Probably running in SAX mode and the callbacks don't
+ * build the entity content. So unless we already went
+ * though parsing for first checking go though the entity
+ * content to generate callbacks associated to the entity
+ */
+ if (was_checked == 1) {
+ void *user_data;
+ /*
+ * This is a bit hackish but this seems the best
+ * way to make sure both SAX and DOM entity support
+ * behaves okay.
+ */
+ if (ctxt->userData == ctxt)
+ user_data = NULL;
+ else
+ user_data = ctxt->userData;
+
+ if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
+ ctxt->depth++;
+ ret = xmlParseBalancedChunkMemoryInternal(ctxt,
+ ent->content, user_data, NULL);
+ ctxt->depth--;
+ } else if (ent->etype ==
+ XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
+ ctxt->depth++;
+ ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
+ ctxt->sax, user_data, ctxt->depth,
+ ent->URI, ent->ExternalID, NULL);
+ ctxt->depth--;
+ } else {
+ ret = XML_ERR_ENTITY_PE_INTERNAL;
+ xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "invalid entity type found\n", NULL);
+ }
+ if (ret == XML_ERR_ENTITY_LOOP) {
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ return;
+ }
+ }
+ if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
+ (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
+ /*
+ * Entity reference callback comes second, it's somewhat
+ * superfluous but a compatibility to historical behaviour
+ */
+ ctxt->sax->reference(ctxt->userData, ent->name);
+ }
+ return;
}
if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
- (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
+ (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
/*
* Create a node.
*/
ctxt->sax->reference(ctxt->userData, ent->name);
return;
- } else if (ctxt->replaceEntities) {
+ }
+ if ((ctxt->replaceEntities) || (ent->children == NULL)) {
/*
* There is a problem on the handling of _private for entities
* (bug 155816): Should we copy the content of the field from
@@ -6206,31 +6288,6 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
ctxt->nodemem = 0;
ctxt->nodelen = 0;
return;
- } else {
- /*
- * Probably running in SAX mode
- */
- xmlParserInputPtr input;
-
- input = xmlNewEntityInputStream(ctxt, ent);
- xmlPushInput(ctxt, input);
- if ((ent->etype == XML_EXTERNAL_GENERAL_PARSED_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 (input->standalone == 1) {
- xmlFatalErr(ctxt, XML_ERR_EXT_ENTITY_STANDALONE,
- NULL);
- }
- }
- return;
}
}
} else {
@@ -6337,7 +6394,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
if ((ctxt->inSubset == 0) &&
(ctxt->sax != NULL) &&
(ctxt->sax->reference != NULL)) {
- ctxt->sax->reference(ctxt, name);
+ ctxt->sax->reference(ctxt->userData, name);
}
}
ctxt->valid = 0;
@@ -7808,7 +7865,7 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
const xmlChar **atts = ctxt->atts;
int maxatts = ctxt->maxatts;
int nratts, nbatts, nbdef;
- int i, j, nbNs, attval;
+ int i, j, nbNs, attval, oldline, oldcol;
const xmlChar *base;
unsigned long cur;
int nsNr = ctxt->nsNr;
@@ -7827,6 +7884,8 @@ reparse:
SHRINK;
base = ctxt->input->base;
cur = ctxt->input->cur - ctxt->input->base;
+ oldline = ctxt->input->line;
+ oldcol = ctxt->input->col;
nbatts = 0;
nratts = 0;
nbdef = 0;
@@ -7861,6 +7920,12 @@ 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)) {
@@ -8152,6 +8217,8 @@ base_changed:
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;
}
@@ -8349,7 +8416,8 @@ void
xmlParseContent(xmlParserCtxtPtr ctxt) {
GROW;
while ((RAW != 0) &&
- ((RAW != '<') || (NXT(1) != '/'))) {
+ ((RAW != '<') || (NXT(1) != '/')) &&
+ (ctxt->instate != XML_PARSER_EOF)) {
const xmlChar *test = CUR_PTR;
unsigned int cons = ctxt->input->consumed;
const xmlChar *cur = ctxt->input->cur;
@@ -8442,6 +8510,14 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
xmlNodePtr ret;
int nsNr = ctxt->nsNr;
+ if ((unsigned int) ctxt->nameNr > xmlParserMaxDepth) {
+ xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
+ "Excessive depth in document: change xmlParserMaxDepth = %d\n",
+ xmlParserMaxDepth);
+ ctxt->instate = XML_PARSER_EOF;
+ return;
+ }
+
/* Capture start position */
if (ctxt->record_info) {
node_info.begin_pos = ctxt->input->consumed +
@@ -8451,6 +8527,8 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
if (ctxt->spaceNr == 0)
spacePush(ctxt, -1);
+ else if (*ctxt->space == -2)
+ spacePush(ctxt, -1);
else
spacePush(ctxt, *ctxt->space);
@@ -9767,6 +9845,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
}
if (ctxt->spaceNr == 0)
spacePush(ctxt, -1);
+ else if (*ctxt->space == -2)
+ spacePush(ctxt, -1);
else
spacePush(ctxt, *ctxt->space);
#ifdef LIBXML_SAX1_ENABLED
@@ -10759,7 +10839,7 @@ xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
* Load and parse a DTD
*
* Returns the resulting xmlDtdPtr or NULL in case of error.
- * @input will be freed at parsing end.
+ * @input will be freed by the function in any case.
*/
xmlDtdPtr
@@ -10775,6 +10855,7 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
ctxt = xmlNewParserCtxt();
if (ctxt == NULL) {
+ xmlFreeParserInputBuffer(input);
return(NULL);
}
@@ -10796,6 +10877,7 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
if (pinput == NULL) {
if (sax != NULL) ctxt->sax = NULL;
+ xmlFreeParserInputBuffer(input);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
@@ -10919,7 +11001,8 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
*/
if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
- input = ctxt->sax->resolveEntity(ctxt, ExternalID, systemIdCanonic);
+ input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
+ systemIdCanonic);
if (input == NULL) {
if (sax != NULL) ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
@@ -11032,6 +11115,8 @@ xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
int ret = 0;
xmlChar start[4];
xmlCharEncoding enc;
+ xmlParserInputPtr inputStream;
+ char *directory = NULL;
if (ctx == NULL) return(-1);
@@ -11046,11 +11131,27 @@ xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
return(-1);
-
- ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);
- if (ctxt == NULL) return(-1);
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ return(-1);
+ }
+
ctxt->userData = ctxt;
ctxt->_private = ctx->_private;
+
+ inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
+ if (inputStream == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(-1);
+ }
+
+ inputPush(ctxt, inputStream);
+
+ if ((ctxt->directory == NULL) && (directory == NULL))
+ directory = xmlParserGetDirectory((char *)URL);
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = directory;
+
oldsax = ctxt->sax;
ctxt->sax = ctx->sax;
xmlDetectSAX2(ctxt);
@@ -11897,6 +11998,9 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
} else {
ctxt->myDoc = newDoc;
newDoc->children->doc = doc;
+ /* Ensure that doc has XML spec namespace */
+ xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
+ newDoc->oldNs = doc->oldNs;
}
ctxt->instate = XML_PARSER_CONTENT;
ctxt->depth = depth;
@@ -11957,6 +12061,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
+ newDoc->oldNs = NULL;
xmlFreeDoc(newDoc);
return(ret);