Skip to content

Commit 50fdad8

Browse files
tstarlingnielsdos
authored andcommitted
Set DOMAttr::$value without expanding entities
The manual refers to the DOM Level 3 Core spec which says: "On setting, this creates a Text node with the unparsed contents of the string. I.e. any characters that an XML processor would recognize as markup are instead treated as literal text." PHP is expanding entities when DOMAttr::value is set, which is non-compliant and is a difference in behaviour compared to browser DOM implementations. So, when value is set, remove all children of the attribute node. Then create a single text node and insert that as the only child of the attribute. Add tests.
1 parent 61e1f8a commit 50fdad8

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

ext/dom/attr.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ int dom_attr_value_write(dom_object *obj, zval *newval)
136136
{
137137
zend_string *str;
138138
xmlAttrPtr attrp = (xmlAttrPtr) dom_object_get_node(obj);
139+
xmlNodePtr node, next;
139140

140141
if (attrp == NULL) {
141142
php_dom_throw_error(INVALID_STATE_ERR, 1);
@@ -149,9 +150,17 @@ int dom_attr_value_write(dom_object *obj, zval *newval)
149150

150151
if (attrp->children) {
151152
node_list_unlink(attrp->children);
153+
node = attrp->children;
154+
while (node) {
155+
next = node->next;
156+
xmlUnlinkNode(node);
157+
xmlFreeNode(node);
158+
node = next;
159+
}
152160
}
153161

154-
xmlNodeSetContentLen((xmlNodePtr) attrp, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
162+
node = xmlNewTextLen((xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str));
163+
xmlAddChild((xmlNodePtr) attrp, node);
155164

156165
zend_string_release_ex(str, 0);
157166
return SUCCESS;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
DOMAttr entity expansion
3+
--FILE--
4+
<?php
5+
$doc = new DOMDocument;
6+
$elt = $doc->createElement('elt');
7+
$doc->appendChild($elt);
8+
$elt->setAttribute('a','&');
9+
print $doc->saveXML($elt) . "\n";
10+
11+
$attr = $elt->getAttributeNode('a');
12+
$attr->value = '&amp;';
13+
print $doc->saveXML($elt) . "\n";
14+
15+
$attr->removeChild($attr->firstChild);
16+
print $doc->saveXML($elt) . "\n";
17+
18+
$elt->setAttributeNS('http://www.w3.org/2000/svg', 'svg:id','&amp;');
19+
print $doc->saveXML($elt) . "\n";
20+
21+
$attr = $elt->getAttributeNodeNS('http://www.w3.org/2000/svg', 'id');
22+
$attr->value = '&lt;&amp;';
23+
print $doc->saveXML($elt) . "\n";
24+
25+
--EXPECT--
26+
<elt a="&amp;"/>
27+
<elt a="&amp;amp;"/>
28+
<elt a=""/>
29+
<elt xmlns:svg="http://www.w3.org/2000/svg" a="" svg:id="&amp;amp;"/>
30+
<elt xmlns:svg="http://www.w3.org/2000/svg" a="" svg:id="&amp;lt;&amp;amp;"/>

0 commit comments

Comments
 (0)