From cff2546f13503ac028e4c1f63c7b6d85f2f2d777 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Mon, 11 Mar 2013 15:57:55 +0800 Subject: [PATCH] Cache presence of '<' in entities content slightly modify how ent->checked is used, and use the lowest bit to keep the information --- SAX2.c | 4 +++- include/libxml/entities.h | 3 ++- parser.c | 30 ++++++++++++++++++------------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/SAX2.c b/SAX2.c index ce7a5d6b..c7ecd7f3 100644 --- a/SAX2.c +++ b/SAX2.c @@ -605,7 +605,9 @@ xmlSAX2GetEntity(void *ctx, const xmlChar *name) } ret->owner = 1; if (ret->checked == 0) { - ret->checked = ctxt->nbentities - oldnbent + 1; + ret->checked = (ctxt->nbentities - oldnbent + 1) * 2; + if ((ret->content != NULL) && (xmlStrchr(ret->content, '<'))) + ret->checked |= 1; } } return(ret); diff --git a/include/libxml/entities.h b/include/libxml/entities.h index cefb97f7..1e911897 100644 --- a/include/libxml/entities.h +++ b/include/libxml/entities.h @@ -58,7 +58,8 @@ struct _xmlEntity { int owner; /* does the entity own the childrens */ int checked; /* was the entity content checked */ /* this is also used to count entites - * references done from that entity */ + * references done from that entity + * and if it contains '<' */ }; /* diff --git a/parser.c b/parser.c index 362186be..2304e577 100644 --- a/parser.c +++ b/parser.c @@ -170,7 +170,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, /* * use the number of parsed entities in the replacement */ - size = ent->checked; + size = ent->checked / 2; /* * The amount of data parsed counting entities size only once @@ -2736,7 +2736,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR)) goto int_error; if (ent != NULL) - ctxt->nbentities += ent->checked; + ctxt->nbentities += ent->checked / 2; if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { if (ent->content != NULL) { @@ -2787,7 +2787,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) goto int_error; if (ent != NULL) - ctxt->nbentities += ent->checked; + ctxt->nbentities += ent->checked / 2; if (ent != NULL) { if (ent->content == NULL) { xmlLoadEntityContent(ctxt, ent); @@ -4050,8 +4050,10 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { rep = xmlStringDecodeEntities(ctxt, ent->content, XML_SUBSTITUTE_REF, 0, 0, 0); - ent->checked = ctxt->nbentities - oldnbent + 1; + ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; if (rep != NULL) { + if (xmlStrchr(rep, '<')) + ent->checked |= 1; xmlFree(rep); rep = NULL; } @@ -7217,7 +7219,9 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { * Store the number of entities needing parsing for this entity * content and do checkings */ - ent->checked = ctxt->nbentities - oldnbent + 1; + ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; + if ((ent->content != NULL) && (xmlStrchr(ent->content, '<'))) + ent->checked |= 1; if (ret == XML_ERR_ENTITY_LOOP) { xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); xmlFreeNodeList(list); @@ -7282,9 +7286,9 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { list = NULL; } if (ent->checked == 0) - ent->checked = 1; + ent->checked = 2; } else if (ent->checked != 1) { - ctxt->nbentities += ent->checked; + ctxt->nbentities += ent->checked / 2; } /* @@ -7645,11 +7649,13 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { * not contain a <. */ else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) && - (ent != NULL) && (ent->content != NULL) && - (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && - (xmlStrchr(ent->content, '<'))) { - xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, - "'<' in entity '%s' is not allowed in attributes values\n", name); + (ent != NULL) && + (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) { + if ((ent->checked & 1) || ((ent->checked == 0) && + (ent->content != NULL) &&(xmlStrchr(ent->content, '<')))) { + xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, + "'<' in entity '%s' is not allowed in attributes values\n", name); + } } /*