mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2024-10-26 12:25:09 +03:00
entities: Use flags to store '<' check results
Instead of abusing the LSB of the "checked" member, store the result of testing for occurrence of '<' character in "flags". Also use the flags in xmlParseStringEntityRef instead of rescanning every time.
This commit is contained in:
parent
481d79d44c
commit
7e3f469be9
@ -11,6 +11,8 @@
|
|||||||
* content.
|
* content.
|
||||||
*/
|
*/
|
||||||
#define XML_ENT_PARSED (1<<0)
|
#define XML_ENT_PARSED (1<<0)
|
||||||
|
#define XML_ENT_CHECKED_LT (1<<1)
|
||||||
|
#define XML_ENT_CONTAINS_LT (1<<2)
|
||||||
|
|
||||||
XML_HIDDEN xmlChar *
|
XML_HIDDEN xmlChar *
|
||||||
xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input);
|
xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input);
|
||||||
|
68
parser.c
68
parser.c
@ -158,7 +158,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
|
|||||||
if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
|
if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
|
||||||
(ent->content != NULL) && (ent->checked == 0) &&
|
(ent->content != NULL) && (ent->checked == 0) &&
|
||||||
(ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
|
(ctxt->errNo != XML_ERR_ENTITY_LOOP)) {
|
||||||
unsigned long oldnbent = ctxt->nbentities, diff;
|
unsigned long oldnbent = ctxt->nbentities;
|
||||||
xmlChar *rep;
|
xmlChar *rep;
|
||||||
|
|
||||||
ent->checked = 1;
|
ent->checked = 1;
|
||||||
@ -171,13 +171,8 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
|
|||||||
ent->content[0] = 0;
|
ent->content[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
diff = ctxt->nbentities - oldnbent + 1;
|
ent->checked = ctxt->nbentities - oldnbent + 1;
|
||||||
if (diff > INT_MAX / 2)
|
|
||||||
diff = INT_MAX / 2;
|
|
||||||
ent->checked = diff * 2;
|
|
||||||
if (rep != NULL) {
|
if (rep != NULL) {
|
||||||
if (xmlStrchr(rep, '<'))
|
|
||||||
ent->checked |= 1;
|
|
||||||
xmlFree(rep);
|
xmlFree(rep);
|
||||||
rep = NULL;
|
rep = NULL;
|
||||||
}
|
}
|
||||||
@ -244,7 +239,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
|
|||||||
/*
|
/*
|
||||||
* use the number of parsed entities in the replacement
|
* use the number of parsed entities in the replacement
|
||||||
*/
|
*/
|
||||||
size = ent->checked / 2;
|
size = ent->checked;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The amount of data parsed counting entities size only once
|
* The amount of data parsed counting entities size only once
|
||||||
@ -2714,7 +2709,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
ent = xmlParseStringEntityRef(ctxt, &str);
|
ent = xmlParseStringEntityRef(ctxt, &str);
|
||||||
xmlParserEntityCheck(ctxt, 0, ent, 0);
|
xmlParserEntityCheck(ctxt, 0, ent, 0);
|
||||||
if (ent != NULL)
|
if (ent != NULL)
|
||||||
ctxt->nbentities += ent->checked / 2;
|
ctxt->nbentities += ent->checked;
|
||||||
if ((ent != NULL) &&
|
if ((ent != NULL) &&
|
||||||
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
|
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
|
||||||
if (ent->content != NULL) {
|
if (ent->content != NULL) {
|
||||||
@ -2767,7 +2762,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
ent = xmlParseStringPEReference(ctxt, &str);
|
ent = xmlParseStringPEReference(ctxt, &str);
|
||||||
xmlParserEntityCheck(ctxt, 0, ent, 0);
|
xmlParserEntityCheck(ctxt, 0, ent, 0);
|
||||||
if (ent != NULL)
|
if (ent != NULL)
|
||||||
ctxt->nbentities += ent->checked / 2;
|
ctxt->nbentities += ent->checked;
|
||||||
if (ent != NULL) {
|
if (ent != NULL) {
|
||||||
if (ent->content == NULL) {
|
if (ent->content == NULL) {
|
||||||
/*
|
/*
|
||||||
@ -4067,20 +4062,15 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
|
|||||||
*/
|
*/
|
||||||
if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
|
if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
|
||||||
(ent->content != NULL) && (ent->checked == 0)) {
|
(ent->content != NULL) && (ent->checked == 0)) {
|
||||||
unsigned long oldnbent = ctxt->nbentities, diff;
|
unsigned long oldnbent = ctxt->nbentities;
|
||||||
|
|
||||||
++ctxt->depth;
|
++ctxt->depth;
|
||||||
rep = xmlStringDecodeEntities(ctxt, ent->content,
|
rep = xmlStringDecodeEntities(ctxt, ent->content,
|
||||||
XML_SUBSTITUTE_REF, 0, 0, 0);
|
XML_SUBSTITUTE_REF, 0, 0, 0);
|
||||||
--ctxt->depth;
|
--ctxt->depth;
|
||||||
|
|
||||||
diff = ctxt->nbentities - oldnbent + 1;
|
ent->checked = ctxt->nbentities - oldnbent + 1;
|
||||||
if (diff > INT_MAX / 2)
|
|
||||||
diff = INT_MAX / 2;
|
|
||||||
ent->checked = diff * 2;
|
|
||||||
if (rep != NULL) {
|
if (rep != NULL) {
|
||||||
if (xmlStrchr(rep, '<'))
|
|
||||||
ent->checked |= 1;
|
|
||||||
xmlFree(rep);
|
xmlFree(rep);
|
||||||
rep = NULL;
|
rep = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -7233,7 +7223,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
if (((ent->flags & XML_ENT_PARSED) == 0) &&
|
if (((ent->flags & XML_ENT_PARSED) == 0) &&
|
||||||
((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
|
((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
|
||||||
(ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
|
(ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
|
||||||
unsigned long oldnbent = ctxt->nbentities, diff;
|
unsigned long oldnbent = ctxt->nbentities;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a bit hackish but this seems the best
|
* This is a bit hackish but this seems the best
|
||||||
@ -7275,12 +7265,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
* Store the number of entities needing parsing for this entity
|
* Store the number of entities needing parsing for this entity
|
||||||
* content and do checkings
|
* content and do checkings
|
||||||
*/
|
*/
|
||||||
diff = ctxt->nbentities - oldnbent + 1;
|
ent->checked = ctxt->nbentities - oldnbent + 1;
|
||||||
if (diff > INT_MAX / 2)
|
|
||||||
diff = INT_MAX / 2;
|
|
||||||
ent->checked = diff * 2;
|
|
||||||
if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
|
|
||||||
ent->checked |= 1;
|
|
||||||
if (ret == XML_ERR_ENTITY_LOOP) {
|
if (ret == XML_ERR_ENTITY_LOOP) {
|
||||||
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
||||||
xmlHaltParser(ctxt);
|
xmlHaltParser(ctxt);
|
||||||
@ -7345,12 +7330,12 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
list = NULL;
|
list = NULL;
|
||||||
}
|
}
|
||||||
if (ent->checked == 0)
|
if (ent->checked == 0)
|
||||||
ent->checked = 2;
|
ent->checked = 1;
|
||||||
|
|
||||||
/* Prevent entity from being parsed and expanded twice (Bug 760367). */
|
/* Prevent entity from being parsed and expanded twice (Bug 760367). */
|
||||||
was_checked = 0;
|
was_checked = 0;
|
||||||
} else if (ent->checked != 1) {
|
} else {
|
||||||
ctxt->nbentities += ent->checked / 2;
|
ctxt->nbentities += ent->checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -7716,13 +7701,16 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
|
|||||||
* not contain a <.
|
* not contain a <.
|
||||||
*/
|
*/
|
||||||
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
|
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
|
||||||
(ent != NULL) &&
|
|
||||||
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
|
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
|
||||||
if (((ent->checked & 1) || (ent->checked == 0)) &&
|
if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
|
||||||
(ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
|
if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
|
||||||
xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
|
ent->flags |= XML_ENT_CONTAINS_LT;
|
||||||
"'<' in entity '%s' is not allowed in attributes values\n", name);
|
ent->flags |= XML_ENT_CHECKED_LT;
|
||||||
}
|
}
|
||||||
|
if (ent->flags & XML_ENT_CONTAINS_LT)
|
||||||
|
xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
|
||||||
|
"'<' in entity '%s' is not allowed in attributes "
|
||||||
|
"values\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -7910,12 +7898,16 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
|
|||||||
* not contain a <.
|
* not contain a <.
|
||||||
*/
|
*/
|
||||||
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
|
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
|
||||||
(ent != NULL) && (ent->content != NULL) &&
|
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
|
||||||
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
|
if ((ent->flags & XML_ENT_CHECKED_LT) == 0) {
|
||||||
(xmlStrchr(ent->content, '<'))) {
|
if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
|
||||||
xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
|
ent->flags |= XML_ENT_CONTAINS_LT;
|
||||||
"'<' in entity '%s' is not allowed in attributes values\n",
|
ent->flags |= XML_ENT_CHECKED_LT;
|
||||||
name);
|
}
|
||||||
|
if (ent->flags & XML_ENT_CONTAINS_LT)
|
||||||
|
xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
|
||||||
|
"'<' in entity '%s' is not allowed in attributes "
|
||||||
|
"values\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user