Skip to content

DOMElement::setAttribute() reaches EMPTY_SWITCH_DEFAULT_CASE() with DTD #FIXED default attributes #22825

Description

@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

$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 14b6c98. Before that, the default branch was a plain default: break;, which is why 8.1-8.3 are unaffected.

PHP Version

PHP >= 8.4.0

Operating System

No response

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions