Commit fedc7cbbd85 for php
commit fedc7cbbd854407316779ddf0d2c5b9f473ea383
Author: Tim Düsterhus <tim@tideways-gmbh.com>
Date: Fri Sep 25 10:17:36 2026 +0200
zend_compile: Disable `array_map()` optimization for `strict_types=1` (#23889)
Fixes php/php-src#23882.
diff --git a/NEWS b/NEWS
index 525f1c98a58..bc56592c0c6 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP NEWS
(ndossche)
. Fixed bug GH-23628 (Tracing JIT reads undefined property slots of lazy
proxy objects instead of forwarding to the real instance). (lisachenko)
+ . Fixed bug GH-23882 (array_map() optimization is incorrect for
+ strict_types=1). (timwolla)
24 Sep 2026, PHP 8.6.0RC2
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 0ced5528386..bad60a5f107 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5324,6 +5324,12 @@ static zend_result zend_compile_func_clone(znode *result, const zend_ast_list *a
static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *args, zend_string *lcname, uint32_t lineno) /* {{{ */
{
+ /* array_map() as an internal function calls the callback as if strict_types=0,
+ * this optimization is therefore not legal if strict_types=1. */
+ if (CG(active_op_array)->fn_flags & ZEND_ACC_STRICT_TYPES) {
+ return FAILURE;
+ }
+
/* Bail out if we do not have exactly two parameters. */
if (args->children != 2) {
return FAILURE;
diff --git a/ext/opcache/tests/array_map_foreach_optimization_009.phpt b/ext/opcache/tests/array_map_foreach_optimization_009.phpt
new file mode 100644
index 00000000000..a1552c44f79
--- /dev/null
+++ b/ext/opcache/tests/array_map_foreach_optimization_009.phpt
@@ -0,0 +1,35 @@
+--TEST--
+array_map(): foreach optimization requires strict_types=0 (GH-23882)
+--EXTENSIONS--
+opcache
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.opt_debug_level=0x20000
+--FILE--
+<?php
+
+declare(strict_types=1);
+
+var_dump(array_map(trim(...), [1]));
+
+?>
+--EXPECTF--
+$_main:
+ ; (lines=%d, args=0, vars=%d, tmps=%d)
+ ; (after optimizer)
+ ; %s
+0000 INIT_FCALL 1 %d string("var_dump")
+0001 INIT_FCALL 2 %d string("array_map")
+0002 INIT_FCALL 0 %d string("trim")
+0003 T0 = CALLABLE_CONVERT %d
+0004 SEND_VAL T0 1
+0005 SEND_VAL array(...) 2
+0006 T0 = DO_ICALL
+0007 SEND_VAL T0 1
+0008 DO_ICALL
+0009 RETURN int(1)
+array(1) {
+ [0]=>
+ string(1) "1"
+}