From e5f9650d7abd4f190d4043e102fb87a13dc52413 Mon Sep 17 00:00:00 2001 From: Arshid Date: Fri, 27 Mar 2026 02:57:30 +0530 Subject: [PATCH 1/2] ext/xml: Use zend_hash_lookup() for missing array keys (#21536) --- ext/xml/xml.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 8b3733fd70a05..968fe4695467f 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -554,10 +554,10 @@ static void xml_add_to_info(xml_parser *parser, zend_string *name) SEPARATE_ARRAY(Z_REFVAL(parser->info)); zend_array *arr = Z_ARRVAL_P(Z_REFVAL(parser->info)); - if ((element = zend_hash_find(arr, name)) == NULL) { - zval values; - array_init(&values); - element = zend_hash_update(arr, name, &values); + element = zend_hash_lookup(arr, name); + + if (Z_TYPE_P(element) == IS_NULL) { + array_init(element); } add_next_index_long(element, parser->curtag); From 8df516c2cdcd5917e0f490e45a354245e94630c1 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 26 Mar 2026 22:54:51 +0000 Subject: [PATCH 2/2] ext/xsl: Remove dead code in importStylesheet and use direct property slot access for doXInclude and cloneDocument. (#21533) The node and its document are validated before cloning, making the subsequent NULL checks on nodep and newdoc redundant. Use OBJ_PROP_NUM via XSL_DEFINE_PROP_ACCESSOR for doXInclude and cloneDocument, avoiding zend_string allocation and property hash lookup per call. --- ext/xsl/php_xsl.c | 2 ++ ext/xsl/php_xsl.h | 2 ++ .../special_operations_with_properties.phpt | 21 +++++++--------- ext/xsl/xsltprocessor.c | 24 ++++--------------- 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c index dec7eb501eb2f..ca7fe0fc1517a 100644 --- a/ext/xsl/php_xsl.c +++ b/ext/xsl/php_xsl.c @@ -144,6 +144,8 @@ zend_object *xsl_objects_new(zend_class_entry *class_type) } #endif +XSL_DEFINE_PROP_ACCESSOR(do_xinclude, "doXInclude", 0) +XSL_DEFINE_PROP_ACCESSOR(clone_document, "cloneDocument", 1) XSL_DEFINE_PROP_ACCESSOR(max_template_depth, "maxTemplateDepth", 2) XSL_DEFINE_PROP_ACCESSOR(max_template_vars, "maxTemplateVars", 3) diff --git a/ext/xsl/php_xsl.h b/ext/xsl/php_xsl.h index 36bd9cc728444..e0171ce9590ca 100644 --- a/ext/xsl/php_xsl.h +++ b/ext/xsl/php_xsl.h @@ -79,6 +79,8 @@ void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs); zval *xsl_prop_max_template_depth(zend_object *object); zval *xsl_prop_max_template_vars(zend_object *object); +zval *xsl_prop_do_xinclude(zend_object *object); +zval *xsl_prop_clone_document(zend_object *object); PHP_MINIT_FUNCTION(xsl); PHP_MSHUTDOWN_FUNCTION(xsl); diff --git a/ext/xsl/tests/special_operations_with_properties.phpt b/ext/xsl/tests/special_operations_with_properties.phpt index b7904fad8d866..efd6765c34f7f 100644 --- a/ext/xsl/tests/special_operations_with_properties.phpt +++ b/ext/xsl/tests/special_operations_with_properties.phpt @@ -29,11 +29,8 @@ echo "--- Unset cloneDocument ---\n"; $xslt = new XSLTProcessor; $xslt->registerPHPFunctions(); unset($xslt->cloneDocument); -try { - $xslt->importStylesheet($xsl); -} catch (Error $e) { - echo $e->getMessage(), "\n"; -} +$xslt->importStylesheet($xsl); +echo $xslt->transformToXml($xml); echo "--- Unset doXInclude ---\n"; @@ -41,11 +38,7 @@ $xslt = new XSLTProcessor; $xslt->registerPHPFunctions(); unset($xslt->doXInclude); $xslt->importStylesheet($xsl); -try { - echo $xslt->transformToXml($xml); -} catch (Error $e) { - echo $e->getMessage(), "\n"; -} +echo $xslt->transformToXml($xml); echo "--- Make properties references ---\n"; @@ -59,9 +52,13 @@ echo $xslt->transformToXml($xml); ?> --EXPECT-- --- Unset cloneDocument --- -Typed property XSLTProcessor::$cloneDocument must not be accessed before initialization +Called test + +hello --- Unset doXInclude --- -Typed property XSLTProcessor::$doXInclude must not be accessed before initialization +Called test + +hello --- Make properties references --- Called test diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index d06d008176172..fe7ed9cd2bb45 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -167,8 +167,7 @@ PHP_METHOD(XSLTProcessor, importStylesheet) xsltStylesheetPtr sheetp; bool clone_docu = false; xmlNode *nodep = NULL; - zval *cloneDocu, rv, clone_zv, owner_zv; - zend_string *member; + zval *cloneDocu, clone_zv, owner_zv; id = ZEND_THIS; if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &docp) == FAILURE) { @@ -216,15 +215,7 @@ PHP_METHOD(XSLTProcessor, importStylesheet) ZVAL_OBJ(&clone_zv, clone); nodep = php_libxml_import_node(&clone_zv); - if (nodep) { - newdoc = nodep->doc; - } - if (newdoc == NULL) { - OBJ_RELEASE(clone); - zend_argument_type_error(1, "must be a valid XML node"); - RETURN_THROWS(); - } - + newdoc = nodep->doc; php_libxml_node_object *clone_lxml_obj = Z_LIBXML_NODE_P(&clone_zv); PHP_LIBXML_SANITIZE_GLOBALS(parse); @@ -259,10 +250,8 @@ PHP_METHOD(XSLTProcessor, importStylesheet) intern->sheet_ref_obj->refcount++; OBJ_RELEASE(clone); - member = ZSTR_INIT_LITERAL("cloneDocument", 0); - cloneDocu = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_R, NULL, &rv); + cloneDocu = xsl_prop_clone_document(Z_OBJ_P(id)); clone_docu = zend_is_true(cloneDocu); - zend_string_release_ex(member, 0); if (!clone_docu) { /* Check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation. * xsl:key elements may only occur at the top level. Furthermore, all elements at the top level must be in a @@ -302,8 +291,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl xmlNodePtr node = NULL; xsltTransformContextPtr ctxt; php_libxml_node_object *object; - zval *doXInclude, rv; - zend_string *member; + zval *doXInclude; FILE *f; int secPrefsError = 0; xsltSecurityPrefsPtr secPrefs = NULL; @@ -359,10 +347,8 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl } } - member = ZSTR_INIT_LITERAL("doXInclude", 0); - doXInclude = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_R, NULL, &rv); + doXInclude = xsl_prop_do_xinclude(Z_OBJ_P(id)); ctxt->xinclude = zend_is_true(doXInclude); - zend_string_release_ex(member, 0); zval *max_template_depth = xsl_prop_max_template_depth(Z_OBJ_P(id)); ZEND_ASSERT(Z_TYPE_P(max_template_depth) == IS_LONG);