Merge branch 'PHP-8.1' into PHP-8.2

* PHP-8.1:
  Fix GH-10234: Setting DOMAttr::textContent results in an empty attribute value
This commit is contained in:
Niels Dossche 2023-05-29 14:12:19 +02:00
commit 9ff1ea6077
3 changed files with 110 additions and 4 deletions

2
NEWS
View File

@ -8,6 +8,8 @@ PHP NEWS
- DOM:
. Fixed bugs GH-11288 and GH-11289 and GH-11290 and GH-9142 (DOMExceptions
and segfaults with replaceWith). (nielsdos)
. Fixed bug GH-10234 (Setting DOMAttr::textContent results in an empty
attribute value). (nielsdos)
- Opcache:
. Fix allocation loop in zend_shared_alloc_startup(). (nielsdos)

View File

@ -769,17 +769,28 @@ int dom_node_text_content_write(dom_object *obj, zval *newval)
return FAILURE;
}
if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE) {
const xmlChar *xmlChars = (const xmlChar *) ZSTR_VAL(str);
int type = nodep->type;
/* We can't directly call xmlNodeSetContent, because it might encode the string through
* xmlStringLenGetNodeList for types XML_DOCUMENT_FRAG_NODE, XML_ELEMENT_NODE, XML_ATTRIBUTE_NODE.
* See tree.c:xmlNodeSetContent in libxml.
* In these cases we need to use a text node to avoid the encoding.
* For the other cases, we *can* rely on xmlNodeSetContent because it is either a no-op, or handles
* the content without encoding. */
if (type == XML_DOCUMENT_FRAG_NODE || type == XML_ELEMENT_NODE || type == XML_ATTRIBUTE_NODE) {
if (nodep->children) {
node_list_unlink(nodep->children);
php_libxml_node_free_list((xmlNodePtr) nodep->children);
nodep->children = NULL;
}
xmlNode *textNode = xmlNewText(xmlChars);
xmlAddChild(nodep, textNode);
} else {
xmlNodeSetContent(nodep, xmlChars);
}
/* we have to use xmlNodeAddContent() to get the same behavior as with xmlNewText() */
xmlNodeSetContent(nodep, (xmlChar *) "");
xmlNodeAddContent(nodep, (xmlChar *) ZSTR_VAL(str));
zend_string_release_ex(str, 0);
return SUCCESS;

View File

@ -0,0 +1,93 @@
--TEST--
GH-10234 (Setting DOMAttr::textContent results in an empty attribute value.)
--EXTENSIONS--
dom
--FILE--
<?php
$document = new DOMDocument();
$document->loadXML('<element attribute="value"/>');
$attribute = $document->documentElement->getAttributeNode('attribute');
echo "-- Attribute tests --\n";
var_dump($document->saveHTML());
var_dump($attribute->textContent);
$attribute->textContent = 'new value';
var_dump($attribute->textContent);
var_dump($document->saveHTML());
$attribute->textContent = 'hello & world';
var_dump($attribute->textContent);
var_dump($document->saveHTML());
$attribute->textContent = '<b>hi</b>';
var_dump($attribute->textContent);
var_dump($document->saveHTML());
$attribute->textContent = 'quote "test"';
var_dump($attribute->textContent);
var_dump($document->saveHTML());
$attribute->textContent = "quote 'test'";
var_dump($attribute->textContent);
var_dump($document->saveHTML());
$attribute->textContent = "quote '\"test\"'";
var_dump($attribute->textContent);
var_dump($document->saveHTML());
echo "-- Document element tests --\n";
$document->documentElement->textContent = 'hello & world';
var_dump($document->documentElement->textContent);
var_dump($document->saveHTML());
$document->documentElement->textContent = '<b>hi</b>';
var_dump($document->documentElement->textContent);
var_dump($document->saveHTML());
$document->documentElement->textContent = 'quote "test"';
var_dump($document->documentElement->textContent);
var_dump($document->saveHTML());
$document->documentElement->textContent = "quote 'test'";
var_dump($document->documentElement->textContent);
var_dump($document->saveHTML());
?>
--EXPECT--
-- Attribute tests --
string(38) "<element attribute="value"></element>
"
string(5) "value"
string(9) "new value"
string(42) "<element attribute="new value"></element>
"
string(13) "hello & world"
string(50) "<element attribute="hello &amp; world"></element>
"
string(9) "<b>hi</b>"
string(54) "<element attribute="&lt;b&gt;hi&lt;/b&gt;"></element>
"
string(12) "quote "test""
string(45) "<element attribute='quote "test"'></element>
"
string(12) "quote 'test'"
string(45) "<element attribute="quote 'test'"></element>
"
string(14) "quote '"test"'"
string(57) "<element attribute="quote '&quot;test&quot;'"></element>
"
-- Document element tests --
string(13) "hello & world"
string(74) "<element attribute="quote '&quot;test&quot;'">hello &amp; world</element>
"
string(9) "<b>hi</b>"
string(78) "<element attribute="quote '&quot;test&quot;'">&lt;b&gt;hi&lt;/b&gt;</element>
"
string(12) "quote "test""
string(69) "<element attribute="quote '&quot;test&quot;'">quote "test"</element>
"
string(12) "quote 'test'"
string(69) "<element attribute="quote '&quot;test&quot;'">quote 'test'</element>
"