Skip to content

Fix XML serializer errata: xmlns="" serialization should be allowed #15894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions ext/dom/tests/modern/xml/serialize_empty_xmlns.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
XML serializer spec errata: xmlns="" serialization should be allowed
--EXTENSIONS--
dom
--FILE--
<?php

// Should be allowed
$dom = Dom\XMLDocument::createFromString('<root><x xmlns=""/></root>');
var_dump($dom->documentElement->innerHTML);

// Should not be allowed
$dom = Dom\XMLDocument::createFromString('<root><x/></root>');
$x = $dom->documentElement->firstChild;
$x->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:a', '');
try {
var_dump($dom->documentElement->innerHTML);
} catch (DOMException $e) {
echo $e->getMessage(), "\n";
}

?>
--EXPECT--
string(13) "<x xmlns=""/>"
The resulting XML serialization is not well-formed
18 changes: 10 additions & 8 deletions ext/dom/xml_serializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ static int dom_xml_serialize_attribute_node_value(xmlOutputBufferPtr out, xmlAtt
/* These steps are from the attribute serialization algorithm's well-formed checks.
* Note that this does not return a boolean but an int to be compatible with the TRY/TRY_CLEANUP interface
* that we do for compatibility with libxml's interfaces. */
static zend_always_inline int dom_xml_check_xmlns_attribute_requirements(const xmlAttr *attr)
static zend_always_inline int dom_xml_check_xmlns_attribute_requirements(const xmlAttr *attr, const xmlChar *candidate_prefix)
{
const xmlChar *attr_value = dom_get_attribute_value(attr);

Expand All @@ -609,8 +609,9 @@ static zend_always_inline int dom_xml_check_xmlns_attribute_requirements(const x
return -1;
}

/* 3.5.2.3. If the require well-formed flag is set and the value of attr's value attribute is the empty string */
if (*attr_value == '\0') {
/* 3.5.2.3. If the require well-formed flag is set and the value of attr's value attribute is the empty string.
* Errata: an "xmlns" attribute is allowed but not one with a prefix, so the idea in the spec is right but the description isn't. */
if (*attr_value == '\0' && candidate_prefix != NULL) {
return -1;
}

Expand Down Expand Up @@ -790,15 +791,16 @@ static int dom_xml_serialize_attributes(
}
}

if (require_well_formed) {
/* 3.5.2.2 and 3.5.2.3 are done by this call. */
TRY_OR_CLEANUP(dom_xml_check_xmlns_attribute_requirements(attr));
}

/* 3.5.2.4. the attr's prefix matches the string "xmlns", then let candidate prefix be the string "xmlns". */
if (attr->ns->prefix != NULL && strcmp((const char *) attr->ns->prefix, "xmlns") == 0) {
candidate_prefix = BAD_CAST "xmlns";
}

/* Errata: step 3.5.2.3 can only really be checked if we already know the candidate prefix. */
if (require_well_formed) {
/* 3.5.2.2 and 3.5.2.3 are done by this call. */
TRY_OR_CLEANUP(dom_xml_check_xmlns_attribute_requirements(attr, candidate_prefix));
}
}
/* 3.5.3. Otherwise, the attribute namespace in not the XMLNS namespace. Run these steps: */
else if (candidate_prefix == NULL) { /* https://github.com/w3c/DOM-Parsing/issues/29 */
Expand Down
Loading