Commit cba864da359 for php
commit cba864da3594849b2211be94b7299a7cbcbe32a3
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date: Sat Sep 26 14:26:57 2026 +0200
Fix incorrect DCE due to unsound escape analysis
Closes GH-23924.
diff --git a/NEWS b/NEWS
index c747dbcdcf5..d36d4b56bfc 100644
--- a/NEWS
+++ b/NEWS
@@ -75,6 +75,7 @@ PHP NEWS
. Fixed bug GH-23637 (PHP-FPM worker SIGSEGV: run_time_cache map_ptr offset
beyond CG(map_ptr_last) when a class is reached through the CE cache).
(David Carlier)
+ . Fix incorrect DCE due to unsound escape analysis. (ndossche)
- PCNTL:
. Fixed pcntl_signal_dispatch() dropping the queued signals when it runs while
diff --git a/Zend/Optimizer/escape_analysis.c b/Zend/Optimizer/escape_analysis.c
index 840a18341a0..352d647e925 100644
--- a/Zend/Optimizer/escape_analysis.c
+++ b/Zend/Optimizer/escape_analysis.c
@@ -300,8 +300,10 @@ static bool is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int v
case ZEND_ASSIGN_STATIC_PROP_OP:
case ZEND_ASSIGN_DIM:
case ZEND_ASSIGN_OBJ:
- case ZEND_ASSIGN_OBJ_REF:
break;
+ case ZEND_ASSIGN_OBJ_REF:
+ /* The property may now alias a variable outside of the object. */
+ return true;
case ZEND_PRE_INC_OBJ:
case ZEND_PRE_DEC_OBJ:
case ZEND_POST_INC_OBJ:
diff --git a/ext/opcache/tests/opt/dce_015.phpt b/ext/opcache/tests/opt/dce_015.phpt
new file mode 100644
index 00000000000..a09284cab36
--- /dev/null
+++ b/ext/opcache/tests/opt/dce_015.phpt
@@ -0,0 +1,45 @@
+--TEST--
+DCE must not remove assignments to properties of an object holding a reference
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.file_update_protection=0
+--EXTENSIONS--
+opcache
+--FILE--
+<?php
+
+class Holder {
+ public $untyped = 0;
+ public int $typed = 0;
+}
+
+class Target {
+ public $untyped = 0;
+ public int $typed = 0;
+}
+
+function untyped() {
+ $h = new Holder;
+ $t = new Target;
+ $h->untyped = &$t->untyped;
+ $h->untyped = 5;
+ var_dump($t->untyped);
+}
+
+function typed() {
+ $h = new Holder;
+ $t = new Target;
+ $h->typed = &$t->typed;
+ $h->typed = 5;
+ var_dump($t->typed);
+}
+
+untyped();
+typed();
+
+?>
+--EXPECT--
+int(5)
+int(5)