Skip to content

Commit 99ec0c1

Browse files
committed
Merge branch 'PHP-8.2'
* PHP-8.2: Fix GH-10234: Setting DOMAttr::textContent results in an empty attribute value
2 parents b884011 + 9ff1ea6 commit 99ec0c1

File tree

2 files changed

+108
-4
lines changed

2 files changed

+108
-4
lines changed

ext/dom/node.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -769,17 +769,28 @@ int dom_node_text_content_write(dom_object *obj, zval *newval)
769769
return FAILURE;
770770
}
771771

772-
if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE) {
772+
const xmlChar *xmlChars = (const xmlChar *) ZSTR_VAL(str);
773+
int type = nodep->type;
774+
775+
/* We can't directly call xmlNodeSetContent, because it might encode the string through
776+
* xmlStringLenGetNodeList for types XML_DOCUMENT_FRAG_NODE, XML_ELEMENT_NODE, XML_ATTRIBUTE_NODE.
777+
* See tree.c:xmlNodeSetContent in libxml.
778+
* In these cases we need to use a text node to avoid the encoding.
779+
* For the other cases, we *can* rely on xmlNodeSetContent because it is either a no-op, or handles
780+
* the content without encoding. */
781+
if (type == XML_DOCUMENT_FRAG_NODE || type == XML_ELEMENT_NODE || type == XML_ATTRIBUTE_NODE) {
773782
if (nodep->children) {
774783
node_list_unlink(nodep->children);
775784
php_libxml_node_free_list((xmlNodePtr) nodep->children);
776785
nodep->children = NULL;
777786
}
787+
788+
xmlNode *textNode = xmlNewText(xmlChars);
789+
xmlAddChild(nodep, textNode);
790+
} else {
791+
xmlNodeSetContent(nodep, xmlChars);
778792
}
779793

780-
/* we have to use xmlNodeAddContent() to get the same behavior as with xmlNewText() */
781-
xmlNodeSetContent(nodep, (xmlChar *) "");
782-
xmlNodeAddContent(nodep, (xmlChar *) ZSTR_VAL(str));
783794
zend_string_release_ex(str, 0);
784795

785796
return SUCCESS;

ext/dom/tests/gh10234.phpt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
--TEST--
2+
GH-10234 (Setting DOMAttr::textContent results in an empty attribute value.)
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
$document = new DOMDocument();
8+
$document->loadXML('<element attribute="value"/>');
9+
$attribute = $document->documentElement->getAttributeNode('attribute');
10+
11+
echo "-- Attribute tests --\n";
12+
13+
var_dump($document->saveHTML());
14+
var_dump($attribute->textContent);
15+
16+
$attribute->textContent = 'new value';
17+
var_dump($attribute->textContent);
18+
var_dump($document->saveHTML());
19+
20+
$attribute->textContent = 'hello & world';
21+
var_dump($attribute->textContent);
22+
var_dump($document->saveHTML());
23+
24+
$attribute->textContent = '<b>hi</b>';
25+
var_dump($attribute->textContent);
26+
var_dump($document->saveHTML());
27+
28+
$attribute->textContent = 'quote "test"';
29+
var_dump($attribute->textContent);
30+
var_dump($document->saveHTML());
31+
32+
$attribute->textContent = "quote 'test'";
33+
var_dump($attribute->textContent);
34+
var_dump($document->saveHTML());
35+
36+
$attribute->textContent = "quote '\"test\"'";
37+
var_dump($attribute->textContent);
38+
var_dump($document->saveHTML());
39+
40+
echo "-- Document element tests --\n";
41+
42+
$document->documentElement->textContent = 'hello & world';
43+
var_dump($document->documentElement->textContent);
44+
var_dump($document->saveHTML());
45+
46+
$document->documentElement->textContent = '<b>hi</b>';
47+
var_dump($document->documentElement->textContent);
48+
var_dump($document->saveHTML());
49+
50+
$document->documentElement->textContent = 'quote "test"';
51+
var_dump($document->documentElement->textContent);
52+
var_dump($document->saveHTML());
53+
54+
$document->documentElement->textContent = "quote 'test'";
55+
var_dump($document->documentElement->textContent);
56+
var_dump($document->saveHTML());
57+
?>
58+
--EXPECT--
59+
-- Attribute tests --
60+
string(38) "<element attribute="value"></element>
61+
"
62+
string(5) "value"
63+
string(9) "new value"
64+
string(42) "<element attribute="new value"></element>
65+
"
66+
string(13) "hello & world"
67+
string(50) "<element attribute="hello &amp; world"></element>
68+
"
69+
string(9) "<b>hi</b>"
70+
string(54) "<element attribute="&lt;b&gt;hi&lt;/b&gt;"></element>
71+
"
72+
string(12) "quote "test""
73+
string(45) "<element attribute='quote "test"'></element>
74+
"
75+
string(12) "quote 'test'"
76+
string(45) "<element attribute="quote 'test'"></element>
77+
"
78+
string(14) "quote '"test"'"
79+
string(57) "<element attribute="quote '&quot;test&quot;'"></element>
80+
"
81+
-- Document element tests --
82+
string(13) "hello & world"
83+
string(74) "<element attribute="quote '&quot;test&quot;'">hello &amp; world</element>
84+
"
85+
string(9) "<b>hi</b>"
86+
string(78) "<element attribute="quote '&quot;test&quot;'">&lt;b&gt;hi&lt;/b&gt;</element>
87+
"
88+
string(12) "quote "test""
89+
string(69) "<element attribute="quote '&quot;test&quot;'">quote "test"</element>
90+
"
91+
string(12) "quote 'test'"
92+
string(69) "<element attribute="quote '&quot;test&quot;'">quote 'test'</element>
93+
"

0 commit comments

Comments
 (0)