Skip to content

Commit ec5cc51

Browse files
committed
Throw when making a duplicate attribute using rename
1 parent 021af6b commit ec5cc51

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

ext/dom/element.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,15 @@ PHP_METHOD(DOM_Element, rename)
18791879
goto cleanup;
18801880
}
18811881

1882+
/* Check for duplicate attributes. */
1883+
if (nodep->type == XML_ATTRIBUTE_NODE) {
1884+
xmlAttrPtr existing = xmlHasNsProp(nodep->parent, localname, namespace_uri && ZSTR_VAL(namespace_uri)[0] != '\0' ? BAD_CAST ZSTR_VAL(namespace_uri) : NULL);
1885+
if (existing != NULL && existing != (xmlAttrPtr) nodep) {
1886+
php_dom_throw_error_with_message(INVALID_MODIFICATION_ERR, "An attribute with the given name in the given namespace already exists", /* strict */ true);
1887+
goto cleanup;
1888+
}
1889+
}
1890+
18821891
php_libxml_invalidate_node_list_cache(intern->document);
18831892

18841893
php_dom_libxml_ns_mapper *ns_mapper = php_dom_get_ns_mapper(intern);
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
--TEST--
2+
Renaming an attribute node to a name that already exists
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$dom = DOM\XMLDocument::createFromString(<<<XML
9+
<!DOCTYPE root [
10+
<!ELEMENT implied-attribute ANY>
11+
<!ATTLIST implied-attribute hello CDATA #FIXED "world">
12+
]>
13+
<root a="b" c="d" xmlns:ns1="urn:a" ns1:foo="bar">
14+
<implied-attribute my-attr="x"/>
15+
<implied-attribute my-attr="x"/>
16+
</root>
17+
XML, LIBXML_DTDATTR);
18+
19+
$root = $dom->documentElement;
20+
try {
21+
$root->attributes[0]->rename(NULL, 'c');
22+
} catch (DOMException $e) {
23+
echo $e->getMessage(), "\n";
24+
}
25+
try {
26+
$root->attributes[0]->rename(NULL, 'c');
27+
} catch (DOMException $e) {
28+
echo $e->getMessage(), "\n";
29+
}
30+
try {
31+
$root->attributes[1]->rename(NULL, 'a');
32+
} catch (DOMException $e) {
33+
echo $e->getMessage(), "\n";
34+
}
35+
try {
36+
$root->attributes[1]->rename('urn:a', 'foo');
37+
} catch (DOMException $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
try {
41+
$root->attributes[3]->rename('', 'a');
42+
} catch (DOMException $e) {
43+
echo $e->getMessage(), "\n";
44+
}
45+
try {
46+
$root->firstElementChild->attributes[0]->rename(NULL, 'hello');
47+
} catch (DOMException $e) {
48+
echo $e->getMessage(), "\n";
49+
}
50+
try {
51+
$root->firstElementChild->attributes[1]->rename(NULL, 'my-attr');
52+
} catch (DOMException $e) {
53+
echo $e->getMessage(), "\n";
54+
}
55+
56+
// This is here to validate that nothing actually changed
57+
echo $dom->saveXML();
58+
59+
?>
60+
--EXPECT--
61+
An attribute with the given name in the given namespace already exists
62+
An attribute with the given name in the given namespace already exists
63+
An attribute with the given name in the given namespace already exists
64+
An attribute with the given name in the given namespace already exists
65+
An attribute with the given name in the given namespace already exists
66+
An attribute with the given name in the given namespace already exists
67+
<?xml version="1.0" encoding="UTF-8"?>
68+
<!DOCTYPE root [
69+
<!ELEMENT implied-attribute ANY>
70+
<!ATTLIST implied-attribute hello CDATA #FIXED "world">
71+
]>
72+
<root xmlns:ns1="urn:a" a="b" c="d" ns1:foo="bar">
73+
<implied-attribute my-attr="x" hello="world"/>
74+
<implied-attribute my-attr="x" hello="world"/>
75+
</root>

ext/dom/tests/modern/extensions/node_renaming_errors.phpt renamed to ext/dom/tests/modern/extensions/node_renaming_validation_erors.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Node renaming errors
2+
Node renaming validation errors
33
--EXTENSIONS--
44
dom
55
--FILE--

0 commit comments

Comments
 (0)