mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2026-10-24 01:09:01 +03:00
Normalize entity values in attr in xmlNodeGetContent
Fix https://gitlab.gnome.org/GNOME/libxml2/-/work_items/1118
This commit is contained in:
committed by
Daniel Garcia Moreno
parent
d60b0f747c
commit
a3c31b5392
43
runtest.c
43
runtest.c
@@ -5435,6 +5435,48 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
xmlEntityValueNormTest(const char *filename ATTRIBUTE_UNUSED,
|
||||
const char *result ATTRIBUTE_UNUSED,
|
||||
const char *err ATTRIBUTE_UNUSED,
|
||||
int options ATTRIBUTE_UNUSED) {
|
||||
int ret = 0;
|
||||
xmlAttrPtr prop = NULL;
|
||||
const char *str = "<!DOCTYPE doc [\n"
|
||||
"<!ENTITY d '
'>\n"
|
||||
"<!ENTITY a '
'>\n"
|
||||
"<!ENTITY da '
'>\n"
|
||||
"<!ENTITY b ' '>\n"
|
||||
"]>\n"
|
||||
"<doc a1='&d;' a2='&a;' a3='&da;'\n"
|
||||
"a4='&d;&d;A&a; &a;B&da;'\n"
|
||||
"a5='

A

B
'\n"
|
||||
"a6='&b;'\n"
|
||||
"a7='\n\n&b;xyz'/>";
|
||||
xmlDoc *doc1 = xmlReadDoc(BAD_CAST str, NULL, NULL, 0);
|
||||
xmlDoc *doc2 = xmlReadDoc(BAD_CAST str, NULL, NULL, XML_PARSE_NOENT);
|
||||
|
||||
prop = doc1->children->next->properties;
|
||||
while (prop != NULL) {
|
||||
xmlChar *content1 = xmlGetProp(doc1->children->next, BAD_CAST prop->name);
|
||||
xmlChar *content2 = xmlGetProp(doc2->children->next, BAD_CAST prop->name);
|
||||
|
||||
if (!xmlStrEqual(content1, content2)) {
|
||||
ret = 1;
|
||||
fprintf(stderr, "entity resolution differs %s\n", prop->name);
|
||||
}
|
||||
|
||||
xmlFree(content1);
|
||||
xmlFree(content2);
|
||||
|
||||
prop = prop->next;
|
||||
}
|
||||
|
||||
xmlFreeDoc(doc1);
|
||||
xmlFreeDoc(doc2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
@@ -5684,6 +5726,7 @@ testDesc testDescriptions[] = {
|
||||
xmlTextReaderReadOuterXmlTest, NULL, NULL, NULL, NULL, 0 },
|
||||
#endif
|
||||
{ "xmlCopyEntity children test" , xmlCopyEntityTest, NULL, NULL, NULL, NULL, 0 },
|
||||
{ "xml Entity values normalization" , xmlEntityValueNormTest, NULL, NULL, NULL, NULL, 0 },
|
||||
|
||||
{NULL, NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
58
tree.c
58
tree.c
@@ -77,7 +77,7 @@ xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,
|
||||
static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop);
|
||||
|
||||
static void
|
||||
xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree);
|
||||
xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree, int normalize);
|
||||
|
||||
static void
|
||||
xmlUnlinkNodeInternal(xmlNodePtr cur);
|
||||
@@ -5122,8 +5122,43 @@ xmlNodeBufGetContent(xmlBuffer *buffer, const xmlNode *cur)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: move this to parserInternals?
|
||||
* TODO: This function should also remove leading and trailing
|
||||
* whitespaces, and also group whitespaces together, but right
|
||||
* now the parse doesn't do that with XML_PARSE_NOENT, so this
|
||||
* replacement is consistent with the parser normalization
|
||||
*
|
||||
* Normalize attritube entity values
|
||||
* Replaces any space character with 0x20
|
||||
* https://www.w3.org/TR/REC-xml/#AVNormalize
|
||||
*/
|
||||
static xmlChar *
|
||||
xmlAttrNormalize(xmlChar *src)
|
||||
{
|
||||
xmlChar *out = NULL;
|
||||
xmlChar *dst = NULL;
|
||||
|
||||
if (src == NULL)
|
||||
return(NULL);
|
||||
|
||||
out = src;
|
||||
dst = out;
|
||||
while (*src != 0) {
|
||||
if (*src < 0x20) {
|
||||
src++;
|
||||
*dst++ = 0x20;
|
||||
} else {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
return(out);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xmlBufGetEntityRefContent(xmlBufPtr buf, const xmlNode *ref) {
|
||||
xmlBufGetEntityRefContent(xmlBufPtr buf, const xmlNode *ref, int normalize) {
|
||||
xmlEntityPtr ent;
|
||||
|
||||
if (ref->children != NULL) {
|
||||
@@ -5149,23 +5184,26 @@ xmlBufGetEntityRefContent(xmlBufPtr buf, const xmlNode *ref) {
|
||||
return;
|
||||
|
||||
ent->flags |= XML_ENT_EXPANDING;
|
||||
xmlBufGetChildContent(buf, (xmlNodePtr) ent);
|
||||
xmlBufGetChildContent(buf, (xmlNodePtr) ent, normalize);
|
||||
ent->flags &= ~XML_ENT_EXPANDING;
|
||||
}
|
||||
|
||||
static void
|
||||
xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree) {
|
||||
xmlBufGetChildContent(xmlBufPtr buf, const xmlNode *tree, int normalize) {
|
||||
const xmlNode *cur = tree->children;
|
||||
|
||||
while (cur != NULL) {
|
||||
switch (cur->type) {
|
||||
case XML_TEXT_NODE:
|
||||
case XML_CDATA_SECTION_NODE:
|
||||
xmlBufCat(buf, cur->content);
|
||||
if (normalize)
|
||||
xmlBufCat(buf, xmlAttrNormalize(cur->content));
|
||||
else
|
||||
xmlBufCat(buf, cur->content);
|
||||
break;
|
||||
|
||||
case XML_ENTITY_REF_NODE:
|
||||
xmlBufGetEntityRefContent(buf, cur);
|
||||
xmlBufGetEntityRefContent(buf, cur, normalize);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -5208,9 +5246,11 @@ xmlBufGetNodeContent(xmlBuf *buf, const xmlNode *cur)
|
||||
case XML_HTML_DOCUMENT_NODE:
|
||||
case XML_DOCUMENT_FRAG_NODE:
|
||||
case XML_ELEMENT_NODE:
|
||||
case XML_ATTRIBUTE_NODE:
|
||||
case XML_ENTITY_DECL:
|
||||
xmlBufGetChildContent(buf, cur);
|
||||
xmlBufGetChildContent(buf, cur, 0);
|
||||
break;
|
||||
case XML_ATTRIBUTE_NODE:
|
||||
xmlBufGetChildContent(buf, cur, 1);
|
||||
break;
|
||||
|
||||
case XML_CDATA_SECTION_NODE:
|
||||
@@ -5221,7 +5261,7 @@ xmlBufGetNodeContent(xmlBuf *buf, const xmlNode *cur)
|
||||
break;
|
||||
|
||||
case XML_ENTITY_REF_NODE:
|
||||
xmlBufGetEntityRefContent(buf, cur);
|
||||
xmlBufGetEntityRefContent(buf, cur, 0);
|
||||
break;
|
||||
|
||||
case XML_NAMESPACE_DECL:
|
||||
|
||||
Reference in New Issue
Block a user