Skip to content

Commit 6ef3863

Browse files
committed
Factor out nsDef allocation into dom_alloc_ns_decl helper.
1 parent 6c4c5e3 commit 6ef3863

1 file changed

Lines changed: 31 additions & 25 deletions

File tree

ext/dom/node.c

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,65 +2103,71 @@ PHP_METHOD(DOMNode, lookupNamespaceURI)
21032103
}
21042104
/* }}} end dom_node_lookup_namespace_uri */
21052105

2106+
/* Allocate, track and prepend a temporary nsDef entry for C14N.
2107+
* Returns the new xmlNsPtr for the caller to fill in href/prefix/_private,
2108+
* or NULL on allocation failure. */
2109+
static xmlNsPtr dom_alloc_ns_decl(HashTable *links, xmlNodePtr node)
2110+
{
2111+
xmlNsPtr ns = xmlMalloc(sizeof(*ns));
2112+
if (!ns) {
2113+
return NULL;
2114+
}
2115+
2116+
zval *zv = zend_hash_index_lookup(links, (zend_ulong) node);
2117+
if (Z_ISNULL_P(zv)) {
2118+
ZVAL_LONG(zv, 1);
2119+
} else {
2120+
Z_LVAL_P(zv)++;
2121+
}
2122+
2123+
memset(ns, 0, sizeof(*ns));
2124+
ns->type = XML_LOCAL_NAMESPACE;
2125+
ns->next = node->nsDef;
2126+
node->nsDef = ns;
2127+
2128+
return ns;
2129+
}
2130+
21062131
/* For DOM-built documents (e.g. createElementNS), namespaces live on node->ns
21072132
* without corresponding xmlns attributes. C14N expects nsDef entries, so create
21082133
* temporary ones. The _private field stays NULL to distinguish from attr-based
21092134
* entries during cleanup. */
21102135
static void dom_add_synthetic_ns_decl(HashTable *links, xmlNodePtr node, xmlNsPtr src_ns)
21112136
{
2137+
/* Pre-existing nsDef entries are never filled in for Dom\XMLDocument.
2138+
* This loop guards against duplicates from our own synthetic additions
2139+
* within the same C14N pass (e.g. when an element and its attributes
2140+
* share the same namespace prefix). */
21122141
for (xmlNsPtr existing = node->nsDef; existing; existing = existing->next) {
21132142
if (xmlStrEqual(existing->prefix, src_ns->prefix)) {
21142143
return;
21152144
}
21162145
}
21172146

2118-
xmlNsPtr ns = xmlMalloc(sizeof(*ns));
2147+
xmlNsPtr ns = dom_alloc_ns_decl(links, node);
21192148
if (!ns) {
21202149
return;
21212150
}
21222151

2123-
zval *zv = zend_hash_index_lookup(links, (zend_ulong) node);
2124-
if (Z_ISNULL_P(zv)) {
2125-
ZVAL_LONG(zv, 1);
2126-
} else {
2127-
Z_LVAL_P(zv)++;
2128-
}
2129-
2130-
memset(ns, 0, sizeof(*ns));
2131-
ns->type = XML_LOCAL_NAMESPACE;
21322152
ns->href = xmlStrdup(src_ns->href);
21332153
ns->prefix = src_ns->prefix ? xmlStrdup(src_ns->prefix) : NULL;
2134-
ns->next = node->nsDef;
2135-
node->nsDef = ns;
21362154
}
21372155

21382156
static void dom_relink_ns_decls_element(HashTable *links, xmlNodePtr node)
21392157
{
21402158
if (node->type == XML_ELEMENT_NODE) {
21412159
for (xmlAttrPtr attr = node->properties; attr; attr = attr->next) {
21422160
if (php_dom_ns_is_fast((const xmlNode *) attr, php_dom_ns_is_xmlns_magic_token)) {
2143-
xmlNsPtr ns = xmlMalloc(sizeof(*ns));
2161+
xmlNsPtr ns = dom_alloc_ns_decl(links, node);
21442162
if (!ns) {
21452163
return;
21462164
}
21472165

2148-
zval *zv = zend_hash_index_lookup(links, (zend_ulong) node);
2149-
if (Z_ISNULL_P(zv)) {
2150-
ZVAL_LONG(zv, 1);
2151-
} else {
2152-
Z_LVAL_P(zv)++;
2153-
}
2154-
21552166
bool should_free;
21562167
xmlChar *attr_value = php_libxml_attr_value(attr, &should_free);
21572168

2158-
memset(ns, 0, sizeof(*ns));
2159-
ns->type = XML_LOCAL_NAMESPACE;
21602169
ns->href = should_free ? attr_value : xmlStrdup(attr_value);
21612170
ns->prefix = attr->ns->prefix ? xmlStrdup(attr->name) : NULL;
2162-
ns->next = node->nsDef;
2163-
node->nsDef = ns;
2164-
21652171
ns->_private = attr;
21662172
if (attr->prev) {
21672173
attr->prev = attr->next;

0 commit comments

Comments
 (0)