1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-10-26 12:25:09 +03:00

entities: Add XML_ENT_PARSED flag

To check whether an entity was already parsed, the code previously
tested whether "checked" was non-zero or "children" was non-null. The
"children" check could be unreliable because an empty entity also
results in an empty (NULL) node list. Use a separate flag to make this
check more reliable.
This commit is contained in:
Nick Wellnhofer 2022-12-19 15:26:46 +01:00
parent f34f184f8e
commit 481d79d44c
3 changed files with 20 additions and 8 deletions

View File

@ -4,6 +4,14 @@
#include <libxml/tree.h>
#include <libxml/xmlstring.h>
/*
* Entity flags
*
* XML_ENT_PARSED: The entity was parsed and `children` points to the
* content.
*/
#define XML_ENT_PARSED (1<<0)
XML_HIDDEN xmlChar *
xmlEncodeAttributeEntities(xmlDocPtr doc, const xmlChar *input);

View File

@ -78,6 +78,7 @@
#include "private/buf.h"
#include "private/dict.h"
#include "private/enc.h"
#include "private/entities.h"
#include "private/error.h"
#include "private/globals.h"
#include "private/html.h"
@ -7203,7 +7204,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
if (ent == NULL) return;
if (!ctxt->wellFormed)
return;
was_checked = ent->checked;
was_checked = ent->flags & XML_ENT_PARSED;
/* special case of predefined entities */
if ((ent->name == NULL) ||
@ -7229,8 +7230,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
* far more secure as the parser will only process data coming from
* the document entity by default.
*/
if (((ent->checked == 0) ||
((ent->children == NULL) && (ctxt->options & XML_PARSE_NOENT))) &&
if (((ent->flags & XML_ENT_PARSED) == 0) &&
((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
(ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
unsigned long oldnbent = ctxt->nbentities, diff;
@ -7270,6 +7270,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
"invalid entity type found\n", NULL);
}
ent->flags |= XML_ENT_PARSED;
/*
* Store the number of entities needing parsing for this entity
* content and do checkings
@ -7292,9 +7293,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
}
if ((ret == XML_ERR_OK) && (list != NULL)) {
if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
(ent->children == NULL)) {
if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
ent->children = list;
/*
* Prune it directly in the generated document

8
tree.c
View File

@ -1411,7 +1411,8 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
if (val != NULL) xmlFree(val);
goto out;
}
else if ((ent != NULL) && (ent->children == NULL)) {
else if ((ent != NULL) &&
((ent->flags & XML_ENT_PARSED) == 0)) {
xmlNodePtr temp;
/* Set to non-NULL value to avoid recursion. */
@ -1419,6 +1420,7 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
ent->children = xmlStringGetNodeList(doc,
(const xmlChar*)node->content);
ent->owner = 1;
ent->flags |= XML_ENT_PARSED;
temp = ent->children;
while (temp) {
temp->parent = (xmlNodePtr)ent;
@ -1607,7 +1609,8 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
node = xmlNewReference(doc, val);
if (node == NULL)
goto out;
if ((ent != NULL) && (ent->children == NULL)) {
if ((ent != NULL) &&
((ent->flags & XML_ENT_PARSED) == 0)) {
xmlNodePtr temp;
/* Set to non-NULL value to avoid recursion. */
@ -1615,6 +1618,7 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
ent->children = xmlStringGetNodeList(doc,
(const xmlChar*)node->content);
ent->owner = 1;
ent->flags |= XML_ENT_PARSED;
temp = ent->children;
while (temp) {
temp->parent = (xmlNodePtr)ent;