[php-src] Issue #22825: `DOMElement::setAttribute()` reaches `EMPTY_SWITCH_DEFAULT_CASE()` with DTD #FIXED default attributes
[email protected] (alexandre-daubois) Mon, 20 Jul 2026 11:41:46 +0000
| Newsgroups | php.bugs |
|---|---|
| Message-ID | <[email protected]> |
Issue: https://github.com/php/php-src/issues/22825
Author: alexandre-daubois
### Description
Originally reported by @ExPatch-LLC
Calling `DOMElement::setAttribute()` with an attribute name that resolves to a DTD #FIXED default attribute reaches an `EMPTY_SWITCH_DEFAULT_CASE()` in `ext/dom/element.c`.
The following code:
```php
<?php
$doc = new DOMDocument();
$doc->loadXML('<!DOCTYPE root [<!ATTLIST root A CDATA #FIXED "d">]><root/>');
$doc->documentElement->setAttribute('A', 'v');
```
Resulted in this output (debug build):
```
php: ext/dom/element.c:469: zim_DOMElement_setAttribute: Assertion `0' failed.
Aborted (core dumped)
```
But I expected this output instead: no crash, a new attribute is created on the element (as happens on 8.1-8.3).
On the legacy (non-spec-compliant) path, `dom_get_attribute_or_nsdecl()` -> `xmlHasNsProp()` falls back to the DTD and returns an `xmlAttribute` node (`XML_ATTRIBUTE_DECL`, type 16). The `switch (attr->type)` in `setAttribute()` only handles `XML_ATTRIBUTE_NODE` and `XML_NAMESPACE_DECL`, so a type-16 node hits the `EMPTY_SWITCH_DEFAULT_CASE()` branch.
This was introduced in 14b6c981c37. Before that, the default branch was a plain `default: break;`, which is why 8.1-8.3 are unaffected.
### PHP Version
```plain
PHP >= 8.4.0
```
### Operating System
_No response_