mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2024-12-25 23:21:26 +03:00
strengthen some of the internal parser limits, add an XML_PARSE_HUGE
* include/libxml/parser.h parser.c xmllint.c: strengthen some of the internal parser limits, add an XML_PARSE_HUGE option to bypass them all. More internal parser limits will still need to be added. Daniel svn path=/trunk/; revision=3777
This commit is contained in:
parent
bf9c1dad3a
commit
8915c150b5
@ -1,3 +1,10 @@
|
|||||||
|
Tue Aug 26 15:02:58 CEST 2008 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
|
* include/libxml/parser.h parser.c xmllint.c: strengthen some
|
||||||
|
of the internal parser limits, add an XML_PARSE_HUGE option
|
||||||
|
to bypass them all. More internal parser limits will still need
|
||||||
|
to be added.
|
||||||
|
|
||||||
Tue Aug 26 09:42:08 CEST 2008 Daniel Veillard <daniel@veillard.com>
|
Tue Aug 26 09:42:08 CEST 2008 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
* Makefile.am: add the testchar to 'make check'
|
* Makefile.am: add the testchar to 'make check'
|
||||||
|
@ -1094,7 +1094,8 @@ typedef enum {
|
|||||||
the tree allowed afterwards (will possibly
|
the tree allowed afterwards (will possibly
|
||||||
crash if you try to modify the tree) */
|
crash if you try to modify the tree) */
|
||||||
XML_PARSE_OLD10 = 1<<17,/* parse using XML-1.0 before update 5 */
|
XML_PARSE_OLD10 = 1<<17,/* parse using XML-1.0 before update 5 */
|
||||||
XML_PARSE_NOBASEFIX = 1<<18 /* do not fixup XINCLUDE xml:base uris */
|
XML_PARSE_NOBASEFIX = 1<<18,/* do not fixup XINCLUDE xml:base uris */
|
||||||
|
XML_PARSE_HUGE = 1<<19 /* relax any hardcoded limit from the parser */
|
||||||
} xmlParserOption;
|
} xmlParserOption;
|
||||||
|
|
||||||
XMLPUBFUN void XMLCALL
|
XMLPUBFUN void XMLCALL
|
||||||
|
72
parser.c
72
parser.c
@ -83,11 +83,12 @@
|
|||||||
/**
|
/**
|
||||||
* xmlParserMaxDepth:
|
* xmlParserMaxDepth:
|
||||||
*
|
*
|
||||||
* arbitrary depth limit for the XML documents that we allow to
|
* arbitrary depth limit for the XML documents that we allow to
|
||||||
* process. This is not a limitation of the parser but a safety
|
* process. This is not a limitation of the parser but a safety
|
||||||
* boundary feature.
|
* boundary feature. It can be disabled with the XML_PARSE_HUGE
|
||||||
|
* parser option.
|
||||||
*/
|
*/
|
||||||
unsigned int xmlParserMaxDepth = 1024;
|
unsigned int xmlParserMaxDepth = 256;
|
||||||
|
|
||||||
#define SAX2 1
|
#define SAX2 1
|
||||||
|
|
||||||
@ -1452,9 +1453,10 @@ nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
|
|||||||
ctxt->nodeTab = tmp;
|
ctxt->nodeTab = tmp;
|
||||||
ctxt->nodeMax *= 2;
|
ctxt->nodeMax *= 2;
|
||||||
}
|
}
|
||||||
if (((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) {
|
if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
|
||||||
|
((ctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
|
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||||
"Excessive depth in document: change xmlParserMaxDepth = %d\n",
|
"Excessive depth in document: %d use XML_PARSE_HUGE option\n",
|
||||||
xmlParserMaxDepth);
|
xmlParserMaxDepth);
|
||||||
ctxt->instate = XML_PARSER_EOF;
|
ctxt->instate = XML_PARSER_EOF;
|
||||||
return(0);
|
return(0);
|
||||||
@ -1463,6 +1465,7 @@ nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
|
|||||||
ctxt->node = value;
|
ctxt->node = value;
|
||||||
return (ctxt->nodeNr++);
|
return (ctxt->nodeNr++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nodePop:
|
* nodePop:
|
||||||
* @ctxt: an XML parser context
|
* @ctxt: an XML parser context
|
||||||
@ -2379,7 +2382,8 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
last = str + len;
|
last = str + len;
|
||||||
|
|
||||||
if ((ctxt->depth > 40) || (ctxt->nbentities >= 500000)) {
|
if (((ctxt->depth > 20) || (ctxt->nbentities >= 100000)) &&
|
||||||
|
((ctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
@ -2417,7 +2421,8 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
"String decoding Entity Reference: %.30s\n",
|
"String decoding Entity Reference: %.30s\n",
|
||||||
str);
|
str);
|
||||||
ent = xmlParseStringEntityRef(ctxt, &str);
|
ent = xmlParseStringEntityRef(ctxt, &str);
|
||||||
if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
|
if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
|
||||||
|
(ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
|
||||||
goto int_error;
|
goto int_error;
|
||||||
ctxt->nbentities++;
|
ctxt->nbentities++;
|
||||||
if (ent != NULL)
|
if (ent != NULL)
|
||||||
@ -2505,6 +2510,14 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
c = CUR_SCHAR(str, l);
|
c = CUR_SCHAR(str, l);
|
||||||
else
|
else
|
||||||
c = 0;
|
c = 0;
|
||||||
|
if ((nbchars > 100000) &&
|
||||||
|
(ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
|
||||||
|
((ctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
|
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||||
|
"Excessive lenght of attribute: %d use XML_PARSE_HUGE option\n",
|
||||||
|
nbchars);
|
||||||
|
goto int_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buffer[nbchars++] = 0;
|
buffer[nbchars++] = 0;
|
||||||
return(buffer);
|
return(buffer);
|
||||||
@ -3647,6 +3660,13 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
|
|||||||
}
|
}
|
||||||
GROW;
|
GROW;
|
||||||
c = CUR_CHAR(l);
|
c = CUR_CHAR(l);
|
||||||
|
if ((len > 100000) &&
|
||||||
|
((ctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
|
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||||
|
"Excessive lenght of attribute: %d use XML_PARSE_HUGE option\n",
|
||||||
|
len);
|
||||||
|
goto int_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((in_space) && (normalize)) {
|
if ((in_space) && (normalize)) {
|
||||||
while (buf[len - 1] == 0x20) len--;
|
while (buf[len - 1] == 0x20) len--;
|
||||||
@ -3669,6 +3689,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
|
|||||||
|
|
||||||
mem_error:
|
mem_error:
|
||||||
xmlErrMemory(ctxt, NULL);
|
xmlErrMemory(ctxt, NULL);
|
||||||
|
int_error:
|
||||||
if (buf != NULL)
|
if (buf != NULL)
|
||||||
xmlFree(buf);
|
xmlFree(buf);
|
||||||
if (rep != NULL)
|
if (rep != NULL)
|
||||||
@ -6494,7 +6515,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
if (!ctxt->wellFormed)
|
if (!ctxt->wellFormed)
|
||||||
return;
|
return;
|
||||||
ctxt->nbentities++;
|
ctxt->nbentities++;
|
||||||
if (ctxt->nbentities >= 500000) {
|
if ((ctxt->nbentities >= 100000) &&
|
||||||
|
((ctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -9135,10 +9157,11 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
|||||||
xmlNodePtr ret;
|
xmlNodePtr ret;
|
||||||
int nsNr = ctxt->nsNr;
|
int nsNr = ctxt->nsNr;
|
||||||
|
|
||||||
if ((unsigned int) ctxt->nameNr > xmlParserMaxDepth) {
|
if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
|
||||||
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
|
((ctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
"Excessive depth in document: change xmlParserMaxDepth = %d\n",
|
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||||
xmlParserMaxDepth);
|
"Excessive depth in document: %d use XML_PARSE_HUGE option\n",
|
||||||
|
xmlParserMaxDepth);
|
||||||
ctxt->instate = XML_PARSER_EOF;
|
ctxt->instate = XML_PARSER_EOF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -11826,7 +11849,8 @@ xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
|
|||||||
|
|
||||||
if (ctx == NULL) return(-1);
|
if (ctx == NULL) return(-1);
|
||||||
|
|
||||||
if ((ctx->depth > 40) || (ctx->nbentities >= 500000)) {
|
if (((ctx->depth > 20) || (ctx->nbentities >= 100000)) &&
|
||||||
|
((ctx->options & XML_PARSE_HUGE) == 0)) {
|
||||||
return(XML_ERR_ENTITY_LOOP);
|
return(XML_ERR_ENTITY_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12036,13 +12060,12 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|||||||
xmlChar start[4];
|
xmlChar start[4];
|
||||||
xmlCharEncoding enc;
|
xmlCharEncoding enc;
|
||||||
|
|
||||||
if ((depth > 40) ||
|
if (((depth > 20) ||
|
||||||
((oldctxt != NULL) && (oldctxt->nbentities >= 500000))) {
|
((oldctxt != NULL) && (oldctxt->nbentities >= 100000))) &&
|
||||||
|
((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
return(XML_ERR_ENTITY_LOOP);
|
return(XML_ERR_ENTITY_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (list != NULL)
|
if (list != NULL)
|
||||||
*list = NULL;
|
*list = NULL;
|
||||||
if ((URL == NULL) && (ID == NULL))
|
if ((URL == NULL) && (ID == NULL))
|
||||||
@ -12282,7 +12305,8 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
|
|||||||
int size;
|
int size;
|
||||||
xmlParserErrors ret = XML_ERR_OK;
|
xmlParserErrors ret = XML_ERR_OK;
|
||||||
|
|
||||||
if ((oldctxt->depth > 40) || (oldctxt->nbentities >= 500000)) {
|
if (((oldctxt->depth > 20) || (oldctxt->nbentities >= 100000)) &&
|
||||||
|
((oldctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||||
return(XML_ERR_ENTITY_LOOP);
|
return(XML_ERR_ENTITY_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12661,7 +12685,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
|
|||||||
int size;
|
int size;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (depth > 40) {
|
if (depth > 20) {
|
||||||
return(XML_ERR_ENTITY_LOOP);
|
return(XML_ERR_ENTITY_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13971,6 +13995,14 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi
|
|||||||
ctxt->options |= XML_PARSE_OLD10;
|
ctxt->options |= XML_PARSE_OLD10;
|
||||||
options -= XML_PARSE_OLD10;
|
options -= XML_PARSE_OLD10;
|
||||||
}
|
}
|
||||||
|
if (options & XML_PARSE_NOBASEFIX) {
|
||||||
|
ctxt->options |= XML_PARSE_NOBASEFIX;
|
||||||
|
options -= XML_PARSE_NOBASEFIX;
|
||||||
|
}
|
||||||
|
if (options & XML_PARSE_HUGE) {
|
||||||
|
ctxt->options |= XML_PARSE_HUGE;
|
||||||
|
options -= XML_PARSE_HUGE;
|
||||||
|
}
|
||||||
ctxt->linenumbers = 1;
|
ctxt->linenumbers = 1;
|
||||||
return (options);
|
return (options);
|
||||||
}
|
}
|
||||||
|
@ -2833,6 +2833,7 @@ static void usage(const char *name) {
|
|||||||
printf("\t--copy : used to test the internal copy implementation\n");
|
printf("\t--copy : used to test the internal copy implementation\n");
|
||||||
#endif /* LIBXML_TREE_ENABLED */
|
#endif /* LIBXML_TREE_ENABLED */
|
||||||
printf("\t--recover : output what was parsable on broken XML documents\n");
|
printf("\t--recover : output what was parsable on broken XML documents\n");
|
||||||
|
printf("\t--huge : remove any internal arbitrary parser limits\n");
|
||||||
printf("\t--noent : substitute entity references by their value\n");
|
printf("\t--noent : substitute entity references by their value\n");
|
||||||
printf("\t--noout : don't output the result tree\n");
|
printf("\t--noout : don't output the result tree\n");
|
||||||
printf("\t--path 'paths': provide a set of paths for resources\n");
|
printf("\t--path 'paths': provide a set of paths for resources\n");
|
||||||
@ -2972,6 +2973,9 @@ main(int argc, char **argv) {
|
|||||||
(!strcmp(argv[i], "--recover"))) {
|
(!strcmp(argv[i], "--recover"))) {
|
||||||
recovery++;
|
recovery++;
|
||||||
options |= XML_PARSE_RECOVER;
|
options |= XML_PARSE_RECOVER;
|
||||||
|
} else if ((!strcmp(argv[i], "-huge")) ||
|
||||||
|
(!strcmp(argv[i], "--huge"))) {
|
||||||
|
options |= XML_PARSE_HUGE;
|
||||||
} else if ((!strcmp(argv[i], "-noent")) ||
|
} else if ((!strcmp(argv[i], "-noent")) ||
|
||||||
(!strcmp(argv[i], "--noent"))) {
|
(!strcmp(argv[i], "--noent"))) {
|
||||||
noent++;
|
noent++;
|
||||||
|
Loading…
Reference in New Issue
Block a user