mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-23 01:52:48 +03:00
Make xmlParseContent and xmlParseElement non-recursive
Split xmlParseElement into subfunctions. Use nameNsPush to store prefix, URI and nsNr on the heap, similar to the push parser. Closes #84.
This commit is contained in:
121
parser.c
121
parser.c
@@ -96,6 +96,12 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
|
|||||||
|
|
||||||
static void xmlHaltParser(xmlParserCtxtPtr ctxt);
|
static void xmlHaltParser(xmlParserCtxtPtr ctxt);
|
||||||
|
|
||||||
|
static int
|
||||||
|
xmlParseElementStart(xmlParserCtxtPtr ctxt);
|
||||||
|
|
||||||
|
static void
|
||||||
|
xmlParseElementEnd(xmlParserCtxtPtr ctxt);
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* *
|
* *
|
||||||
* Arbitrary limits set in the parser. See XML_PARSE_HUGE *
|
* Arbitrary limits set in the parser. See XML_PARSE_HUGE *
|
||||||
@@ -1822,7 +1828,6 @@ nodePop(xmlParserCtxtPtr ctxt)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LIBXML_PUSH_ENABLED
|
|
||||||
/**
|
/**
|
||||||
* nameNsPush:
|
* nameNsPush:
|
||||||
* @ctxt: an XML parser context
|
* @ctxt: an XML parser context
|
||||||
@@ -1858,6 +1863,11 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
|
|||||||
goto mem_error;
|
goto mem_error;
|
||||||
}
|
}
|
||||||
ctxt->pushTab = tmp2;
|
ctxt->pushTab = tmp2;
|
||||||
|
} else if (ctxt->pushTab == NULL) {
|
||||||
|
ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
|
||||||
|
sizeof(ctxt->pushTab[0]));
|
||||||
|
if (ctxt->pushTab == NULL)
|
||||||
|
goto mem_error;
|
||||||
}
|
}
|
||||||
ctxt->nameTab[ctxt->nameNr] = value;
|
ctxt->nameTab[ctxt->nameNr] = value;
|
||||||
ctxt->name = value;
|
ctxt->name = value;
|
||||||
@@ -1869,6 +1879,7 @@ mem_error:
|
|||||||
xmlErrMemory(ctxt, NULL);
|
xmlErrMemory(ctxt, NULL);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
#ifdef LIBXML_PUSH_ENABLED
|
||||||
/**
|
/**
|
||||||
* nameNsPop:
|
* nameNsPop:
|
||||||
* @ctxt: an XML parser context
|
* @ctxt: an XML parser context
|
||||||
@@ -9812,9 +9823,10 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
xmlParseContent(xmlParserCtxtPtr ctxt) {
|
xmlParseContent(xmlParserCtxtPtr ctxt) {
|
||||||
|
int nameNr = ctxt->nameNr;
|
||||||
|
|
||||||
GROW;
|
GROW;
|
||||||
while ((RAW != 0) &&
|
while ((RAW != 0) &&
|
||||||
((RAW != '<') || (NXT(1) != '/')) &&
|
|
||||||
(ctxt->instate != XML_PARSER_EOF)) {
|
(ctxt->instate != XML_PARSER_EOF)) {
|
||||||
const xmlChar *test = CUR_PTR;
|
const xmlChar *test = CUR_PTR;
|
||||||
unsigned int cons = ctxt->input->consumed;
|
unsigned int cons = ctxt->input->consumed;
|
||||||
@@ -9848,7 +9860,13 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
|
|||||||
* Fourth case : a sub-element.
|
* Fourth case : a sub-element.
|
||||||
*/
|
*/
|
||||||
else if (*cur == '<') {
|
else if (*cur == '<') {
|
||||||
xmlParseElement(ctxt);
|
if (NXT(1) == '/') {
|
||||||
|
if (ctxt->nameNr <= nameNr)
|
||||||
|
break;
|
||||||
|
xmlParseElementEnd(ctxt);
|
||||||
|
} else {
|
||||||
|
xmlParseElementStart(ctxt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -9883,7 +9901,7 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
|
|||||||
* xmlParseElement:
|
* xmlParseElement:
|
||||||
* @ctxt: an XML parser context
|
* @ctxt: an XML parser context
|
||||||
*
|
*
|
||||||
* parse an XML element, this is highly recursive
|
* parse an XML element
|
||||||
*
|
*
|
||||||
* [39] element ::= EmptyElemTag | STag content ETag
|
* [39] element ::= EmptyElemTag | STag content ETag
|
||||||
*
|
*
|
||||||
@@ -9895,6 +9913,23 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
xmlParseElement(xmlParserCtxtPtr ctxt) {
|
xmlParseElement(xmlParserCtxtPtr ctxt) {
|
||||||
|
if (xmlParseElementStart(ctxt) != 0)
|
||||||
|
return;
|
||||||
|
xmlParseContent(ctxt);
|
||||||
|
if (ctxt->instate == XML_PARSER_EOF)
|
||||||
|
return;
|
||||||
|
xmlParseElementEnd(ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlParseElementStart:
|
||||||
|
* @ctxt: an XML parser context
|
||||||
|
*
|
||||||
|
* Parse the start of an XML element. Returns -1 in case of error, 0 if an
|
||||||
|
* opening tag was parsed, 1 if an empty element was parsed.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xmlParseElementStart(xmlParserCtxtPtr ctxt) {
|
||||||
const xmlChar *name;
|
const xmlChar *name;
|
||||||
const xmlChar *prefix = NULL;
|
const xmlChar *prefix = NULL;
|
||||||
const xmlChar *URI = NULL;
|
const xmlChar *URI = NULL;
|
||||||
@@ -9909,7 +9944,7 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
|||||||
"Excessive depth in document: %d use XML_PARSE_HUGE option\n",
|
"Excessive depth in document: %d use XML_PARSE_HUGE option\n",
|
||||||
xmlParserMaxDepth);
|
xmlParserMaxDepth);
|
||||||
xmlHaltParser(ctxt);
|
xmlHaltParser(ctxt);
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Capture start position */
|
/* Capture start position */
|
||||||
@@ -9936,12 +9971,17 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
|||||||
name = xmlParseStartTag(ctxt);
|
name = xmlParseStartTag(ctxt);
|
||||||
#endif /* LIBXML_SAX1_ENABLED */
|
#endif /* LIBXML_SAX1_ENABLED */
|
||||||
if (ctxt->instate == XML_PARSER_EOF)
|
if (ctxt->instate == XML_PARSER_EOF)
|
||||||
return;
|
return(-1);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
spacePop(ctxt);
|
spacePop(ctxt);
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
namePush(ctxt, name);
|
if (ctxt->sax2)
|
||||||
|
nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
|
||||||
|
#ifdef LIBXML_SAX1_ENABLED
|
||||||
|
else
|
||||||
|
namePush(ctxt, name);
|
||||||
|
#endif /* LIBXML_SAX1_ENABLED */
|
||||||
ret = ctxt->node;
|
ret = ctxt->node;
|
||||||
|
|
||||||
#ifdef LIBXML_VALID_ENABLED
|
#ifdef LIBXML_VALID_ENABLED
|
||||||
@@ -9982,7 +10022,7 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
|||||||
node_info.node = ret;
|
node_info.node = ret;
|
||||||
xmlParserAddNodeInfo(ctxt, &node_info);
|
xmlParserAddNodeInfo(ctxt, &node_info);
|
||||||
}
|
}
|
||||||
return;
|
return(1);
|
||||||
}
|
}
|
||||||
if (RAW == '>') {
|
if (RAW == '>') {
|
||||||
NEXT1;
|
NEXT1;
|
||||||
@@ -10010,41 +10050,39 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
|||||||
node_info.node = ret;
|
node_info.node = ret;
|
||||||
xmlParserAddNodeInfo(ctxt, &node_info);
|
xmlParserAddNodeInfo(ctxt, &node_info);
|
||||||
}
|
}
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
return(0);
|
||||||
* Parse the content of the element:
|
}
|
||||||
*/
|
|
||||||
xmlParseContent(ctxt);
|
|
||||||
if (ctxt->instate == XML_PARSER_EOF)
|
|
||||||
return;
|
|
||||||
if (!IS_BYTE_CHAR(RAW)) {
|
|
||||||
xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
|
|
||||||
"Premature end of data in tag %s line %d\n",
|
|
||||||
name, line, NULL);
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* end of parsing of this node.
|
* xmlParseElementEnd:
|
||||||
*/
|
* @ctxt: an XML parser context
|
||||||
nodePop(ctxt);
|
*
|
||||||
namePop(ctxt);
|
* Parse the end of an XML element.
|
||||||
spacePop(ctxt);
|
*/
|
||||||
if (nsNr != ctxt->nsNr)
|
static void
|
||||||
nsPop(ctxt, ctxt->nsNr - nsNr);
|
xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
|
||||||
return;
|
xmlParserNodeInfo node_info;
|
||||||
}
|
xmlNodePtr ret = ctxt->node;
|
||||||
|
|
||||||
|
if (ctxt->nameNr <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse the end of tag: '</' should be here.
|
* parse the end of tag: '</' should be here.
|
||||||
*/
|
*/
|
||||||
if (ctxt->sax2) {
|
if (ctxt->sax2) {
|
||||||
xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
|
const xmlChar *prefix = ctxt->pushTab[ctxt->nameNr * 3 - 3];
|
||||||
|
const xmlChar *URI = ctxt->pushTab[ctxt->nameNr * 3 - 2];
|
||||||
|
int nsNr = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 3 - 1];
|
||||||
|
xmlParseEndTag2(ctxt, prefix, URI, 0, nsNr, 0);
|
||||||
namePop(ctxt);
|
namePop(ctxt);
|
||||||
}
|
}
|
||||||
#ifdef LIBXML_SAX1_ENABLED
|
#ifdef LIBXML_SAX1_ENABLED
|
||||||
else
|
else
|
||||||
xmlParseEndTag1(ctxt, line);
|
xmlParseEndTag1(ctxt, 0);
|
||||||
#endif /* LIBXML_SAX1_ENABLED */
|
#endif /* LIBXML_SAX1_ENABLED */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -12361,13 +12399,6 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
ctxt->dictNames = 1;
|
ctxt->dictNames = 1;
|
||||||
ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
|
|
||||||
if (ctxt->pushTab == NULL) {
|
|
||||||
xmlErrMemory(ctxt, NULL);
|
|
||||||
xmlFreeParserInputBuffer(buf);
|
|
||||||
xmlFreeParserCtxt(ctxt);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
if (sax != NULL) {
|
if (sax != NULL) {
|
||||||
#ifdef LIBXML_SAX1_ENABLED
|
#ifdef LIBXML_SAX1_ENABLED
|
||||||
if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
|
if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
|
||||||
@@ -14949,16 +14980,6 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
|
|||||||
|
|
||||||
xmlCtxtReset(ctxt);
|
xmlCtxtReset(ctxt);
|
||||||
|
|
||||||
if (ctxt->pushTab == NULL) {
|
|
||||||
ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
|
|
||||||
sizeof(xmlChar *));
|
|
||||||
if (ctxt->pushTab == NULL) {
|
|
||||||
xmlErrMemory(ctxt, NULL);
|
|
||||||
xmlFreeParserInputBuffer(buf);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
ctxt->directory = NULL;
|
ctxt->directory = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
Bytes: 0xEE 0x5D 0x5D 0x3E
|
Bytes: 0xEE 0x5D 0x5D 0x3E
|
||||||
<d><![CDATA[0000000000000<30>]]>
|
<d><![CDATA[0000000000000<30>]]>
|
||||||
^
|
^
|
||||||
./test/errors/754947.xml:1: parser error : Premature end of data in tag d line 1
|
./test/errors/754947.xml:1: parser error : EndTag: '</' not found
|
||||||
<d><![CDATA[0000000000000<30>]]>
|
<d><![CDATA[0000000000000<30>]]>
|
||||||
^
|
^
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
./test/errors/759398.xml:210: parser error : StartTag: invalid element name
|
./test/errors/759398.xml:210: parser error : StartTag: invalid element name
|
||||||
need to worry about parsers whi<! don't expand PErefs finding
|
need to worry about parsers whi<! don't expand PErefs finding
|
||||||
^
|
^
|
||||||
./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№m line 308 and termdef
|
./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№m line 205 and termdef
|
||||||
and provide access to their content and structure.</termdef> <termdef
|
and provide access to their content and structure.</termdef> <termdef
|
||||||
^
|
^
|
||||||
./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 50 and p
|
./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 205 and p
|
||||||
data and the information it must provide to the application.</p>
|
data and the information it must provide to the application.</p>
|
||||||
^
|
^
|
||||||
./test/errors/759398.xml:316: parser error : Extra content at the end of the document
|
./test/errors/759398.xml:316: parser error : Extra content at the end of the document
|
||||||
|
|||||||
Reference in New Issue
Block a user