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:
@@ -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("\"")));
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user