Commit 8df516c2cdc for php.net

commit 8df516c2cdcd5917e0f490e45a354245e94630c1
Author: David CARLIER <devnexen@gmail.com>
Date:   Thu Mar 26 22:54:51 2026 +0000

    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.

diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c
index dec7eb501eb..ca7fe0fc151 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 36bd9cc7284..e0171ce9590 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 b7904fad8d8..efd6765c34f 100644
--- a/ext/xsl/tests/special_operations_with_properties.phpt
+++ b/ext/xsl/tests/special_operations_with_properties.phpt
@@ -29,11 +29,8 @@ function test() {
 $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 @@ function test() {
 $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 @@ function test() {
 ?>
 --EXPECT--
 --- Unset cloneDocument ---
-Typed property XSLTProcessor::$cloneDocument must not be accessed before initialization
+Called test
+<?xml version="1.0"?>
+hello
 --- Unset doXInclude ---
-Typed property XSLTProcessor::$doXInclude must not be accessed before initialization
+Called test
+<?xml version="1.0"?>
+hello
 --- Make properties references ---
 Called test
 <?xml version="1.0"?>
diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c
index d06d0081761..fe7ed9cd2bb 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);