1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix serialization of entity references in attributes (#13884)

This commit is contained in:
Niels Dossche
2024-04-05 19:58:01 +02:00
committed by GitHub
parent 536305436f
commit 0a0e8064e0
3 changed files with 62 additions and 13 deletions

View File

@@ -196,13 +196,21 @@ static zend_result dom_html5_serialize_element_start(dom_html5_serialize_context
TRY(ctx->write_string(ctx->application_data, (const char *) attr->name));
}
}
TRY(ctx->write_string_len(ctx->application_data, "=\"", strlen("=\"")));
xmlChar *content = xmlNodeGetContent((const xmlNode *) attr);
if (content != NULL) {
zend_result result = dom_html5_escape_string(ctx, (const char *) content, true);
xmlFree(content);
TRY(result);
for (xmlNodePtr child = attr->children; child != NULL; child = child->next) {
if (child->type == XML_TEXT_NODE) {
if (child->content != NULL) {
TRY(dom_html5_escape_string(ctx, (const char *) child->content, true));
}
} else if (child->type == XML_ENTITY_REF_NODE) {
TRY(ctx->write_string_len(ctx->application_data, "&", strlen("&")));
TRY(dom_html5_escape_string(ctx, (const char *) child->name, true));
TRY(ctx->write_string_len(ctx->application_data, ";", strlen(";")));
}
}
TRY(ctx->write_string_len(ctx->application_data, "\"", strlen("\"")));
}

View File

@@ -0,0 +1,29 @@
--TEST--
Serialize entity reference within attribute
--EXTENSIONS--
dom
--FILE--
<?php
$xml = DOM\XMLDocument::createFromString(<<<XML
<!DOCTYPE root [
<!ENTITY foo "foo">
]>
<root><el x="&foo;bar&foo;"/></root>
XML);
$el = $xml->documentElement->firstChild;
echo $xml->saveXML(), "\n";
$html = DOM\HTMLDocument::createEmpty();
$html->append($html->importNode($el, true));
echo $html->saveHTML(), "\n";
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY foo "foo">
]>
<root><el x="&foo;bar&foo;"/></root>
<el x="&foo;bar&foo;"></el>

View File

@@ -542,6 +542,24 @@ static zend_always_inline int dom_xml_serialize_text_node(xmlOutputBufferPtr out
return dom_xml_common_text_serialization(out, (const char *) text->content, false);
}
static int dom_xml_serialize_attribute_node_value(xmlOutputBufferPtr out, xmlAttrPtr attr)
{
TRY(xmlOutputBufferWriteString(out, (const char *) attr->name));
TRY(xmlOutputBufferWrite(out, strlen("=\""), "=\""));
for (xmlNodePtr child = attr->children; child != NULL; child = child->next) {
if (child->type == XML_TEXT_NODE) {
if (child->content != NULL) {
TRY(dom_xml_common_text_serialization(out, (const char *) child->content, true));
}
} else if (child->type == XML_ENTITY_REF_NODE) {
TRY(xmlOutputBufferWrite(out, strlen("&"), "&"));
TRY(dom_xml_common_text_serialization(out, (const char *) child->name, true));
TRY(xmlOutputBufferWrite(out, strlen(";"), ";"));
}
}
return xmlOutputBufferWrite(out, strlen("\""), "\"");
}
/* Spec says to do nothing, but that's inconsistent/wrong, see https://github.com/w3c/DOM-Parsing/issues/28 */
static int dom_xml_serialize_attribute_node(xmlOutputBufferPtr out, xmlNodePtr attr)
{
@@ -549,10 +567,7 @@ static int dom_xml_serialize_attribute_node(xmlOutputBufferPtr out, xmlNodePtr a
TRY(xmlOutputBufferWriteString(out, (const char *) attr->ns->prefix));
TRY(xmlOutputBufferWrite(out, strlen(":"), ":"));
}
TRY(xmlOutputBufferWriteString(out, (const char *) attr->name));
TRY(xmlOutputBufferWrite(out, strlen("=\""), "=\""));
TRY(dom_xml_common_text_serialization(out, (const char *) dom_get_attribute_value((xmlAttrPtr) attr), true));
return xmlOutputBufferWrite(out, strlen("\""), "\"");
return dom_xml_serialize_attribute_node_value(out, (xmlAttrPtr) attr);
}
/* https://w3c.github.io/DOM-Parsing/#dfn-xml-serializing-a-comment-node */
@@ -730,10 +745,7 @@ static int dom_xml_serialize_attributes(
* => N/A */
/* 3.9. Append the following strings to result, in the order listed: */
TRY(xmlOutputBufferWriteString(out, (const char *) attr->name));
TRY(xmlOutputBufferWrite(out, strlen("=\""), "=\""));
TRY(dom_xml_common_text_serialization(out, (const char *) dom_get_attribute_value(attr), true));
TRY(xmlOutputBufferWrite(out, strlen("\""), "\""));
dom_xml_serialize_attribute_node_value(out, attr);
}
/* 4. Return the value of result.