From c617afd6d6e46ebbb896bab96761df2168be82d1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:55:33 +0200 Subject: [PATCH 1/3] Fix GH-20009: XMLReader leak on RelaxNG schema failure Closes GH-20014. --- NEWS | 3 +++ ext/xmlreader/php_xmlreader.c | 1 + 2 files changed, 4 insertions(+) diff --git a/NEWS b/NEWS index d1d7335c132e6..c7765950f8cc8 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,9 @@ PHP NEWS . Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()). (alexandre-daubois) +- XMLReader: + . Fixed bug GH-20009 (XMLReader leak on RelaxNG schema failure). (nielsdos) + - Zip: . Fixed bug GH-19688 (Remove pattern overflow in zip addGlob()). (nielsdos) . Fixed bug GH-19932 (Memory leak in zip setEncryptionName()/setEncryptionIndex()). diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index dca1898f1c044..7a50b660fb59d 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -508,6 +508,7 @@ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int t RETURN_TRUE; } else { + xmlRelaxNGFree(schema); php_error_docref(NULL, E_WARNING, "Schema contains errors"); RETURN_FALSE; } From f2aaea053c0825885c4a8ab44c4ecce5005d8316 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 30 Sep 2025 18:10:24 +0200 Subject: [PATCH 2/3] Use faster string construction in ext/dom in some places (#20005) Many tag names are single characters, so we can use the fast string construction. In cases where a NULL name is used we can also use the empty string. This avoids some allocations and some work. --- ext/dom/attr.c | 2 +- ext/dom/documenttype.c | 6 +++++- ext/dom/dom_iterators.c | 4 ++-- ext/dom/element.c | 4 ++-- ext/dom/node.c | 11 +++++++++-- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/ext/dom/attr.c b/ext/dom/attr.c index 5a0900d657eea..3107f5a21a2be 100644 --- a/ext/dom/attr.c +++ b/ext/dom/attr.c @@ -83,7 +83,7 @@ zend_result dom_attr_name_read(dom_object *obj, zval *retval) if (php_dom_follow_spec_intern(obj)) { zend_string *str = dom_node_get_node_name_attribute_or_element((xmlNodePtr) attrp, false); - ZVAL_NEW_STR(retval, str); + ZVAL_STR(retval, str); } else { ZVAL_STRING(retval, (char *) attrp->name); } diff --git a/ext/dom/documenttype.c b/ext/dom/documenttype.c index 63da0306649a9..266c895effb27 100644 --- a/ext/dom/documenttype.c +++ b/ext/dom/documenttype.c @@ -34,7 +34,11 @@ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core- zend_result dom_documenttype_name_read(dom_object *obj, zval *retval) { DOM_PROP_NODE(xmlDtdPtr, dtdptr, obj); - ZVAL_STRING(retval, dtdptr->name ? (char *) (dtdptr->name) : ""); + if (dtdptr->name) { + ZVAL_STRING(retval, (const char *) dtdptr->name); + } else { + ZVAL_EMPTY_STRING(retval); + } return SUCCESS; } diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index 90e973723f6c6..9134b107925a2 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -127,9 +127,9 @@ static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key) if (intern->ptr != NULL) { xmlNodePtr curnode = ((php_libxml_node_ptr *)intern->ptr)->node; if (curnode->type == XML_ATTRIBUTE_NODE && php_dom_follow_spec_intern(intern)) { - ZVAL_NEW_STR(key, dom_node_get_node_name_attribute_or_element(curnode, false)); + ZVAL_STR(key, dom_node_get_node_name_attribute_or_element(curnode, false)); } else { - ZVAL_STRINGL(key, (const char *) curnode->name, xmlStrlen(curnode->name)); + ZVAL_STRINGL_FAST(key, (const char *) curnode->name, xmlStrlen(curnode->name)); } } else { ZVAL_NULL(key); diff --git a/ext/dom/element.c b/ext/dom/element.c index f9aee10802fbb..cf1a762768a87 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -122,7 +122,7 @@ zend_result dom_element_tag_name_read(dom_object *obj, zval *retval) bool uppercase = php_dom_follow_spec_intern(obj) && php_dom_ns_is_html_and_document_is_html(nodep); zend_string *result = dom_node_get_node_name_attribute_or_element((const xmlNode *) nodep, uppercase); - ZVAL_NEW_STR(retval, result); + ZVAL_STR(retval, result); return SUCCESS; } @@ -375,7 +375,7 @@ PHP_METHOD(DOMElement, getAttributeNames) } for (xmlAttrPtr attr = nodep->properties; attr; attr = attr->next) { - ZVAL_NEW_STR(&tmp, dom_node_get_node_name_attribute_or_element((const xmlNode *) attr, false)); + ZVAL_STR(&tmp, dom_node_get_node_name_attribute_or_element((const xmlNode *) attr, false)); zend_hash_next_index_insert(ht, &tmp); } } diff --git a/ext/dom/node.c b/ext/dom/node.c index 61e693fa77630..40aaf27669268 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -52,6 +52,13 @@ zend_string *dom_node_get_node_name_attribute_or_element(const xmlNode *nodep, b if (nodep->ns != NULL && nodep->ns->prefix != NULL) { ret = dom_node_concatenated_name_helper(name_len, (const char *) nodep->name, strlen((const char *) nodep->ns->prefix), (const char *) nodep->ns->prefix); } else { + if (name_len == 1) { + if (uppercase) { + return ZSTR_CHAR(zend_toupper_ascii(*nodep->name)); + } else { + return ZSTR_CHAR((zend_uchar) *nodep->name); + } + } ret = zend_string_init((const char *) nodep->name, name_len, false); } if (uppercase) { @@ -89,7 +96,7 @@ zend_result dom_node_node_name_read(dom_object *obj, zval *retval) uppercase = php_dom_follow_spec_intern(obj) && php_dom_ns_is_html_and_document_is_html(nodep); ZEND_FALLTHROUGH; case XML_ATTRIBUTE_NODE: - ZVAL_NEW_STR(retval, dom_node_get_node_name_attribute_or_element(nodep, uppercase)); + ZVAL_STR(retval, dom_node_get_node_name_attribute_or_element(nodep, uppercase)); break; case XML_NAMESPACE_DECL: { xmlNsPtr ns = nodep->ns; @@ -635,7 +642,7 @@ zend_result dom_node_local_name_read(dom_object *obj, zval *retval) DOM_PROP_NODE(xmlNodePtr, nodep, obj); if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE || nodep->type == XML_NAMESPACE_DECL) { - ZVAL_STRING(retval, (char *) (nodep->name)); + ZVAL_STRING_FAST(retval, (const char *) (nodep->name)); } else { ZVAL_NULL(retval); } From cd9eec79a87b92486c2c594ea07b4c31bf05eb87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 30 Sep 2025 22:17:55 +0200 Subject: [PATCH 3/3] Add Tim as a maintainer of ext/uri [skip-ci] --- .github/CODEOWNERS | 2 +- EXTENSIONS | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 973c9d470dc58..1720a66933385 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -52,7 +52,7 @@ /ext/sockets @devnexen /ext/spl @Girgias /ext/standard @bukka -/ext/uri @kocsismate +/ext/uri @kocsismate @TimWolla /ext/xml @nielsdos /ext/xmlreader @nielsdos /ext/xmlwriter @nielsdos diff --git a/EXTENSIONS b/EXTENSIONS index 01685748b5e09..5cce4ae7c9232 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -506,6 +506,7 @@ STATUS: Working ------------------------------------------------------------------------------- EXTENSION: uri PRIMARY MAINTAINER Máté Kocsis (2025 - 2025) + Tim Düsterhus (2025 - 2025) MAINTENANCE: Maintained STATUS: Working SINCE: 8.5.0