[php-src] PHP-8.6: Fix JIT reading packed-turned-hash array as packed after string key write

From: Date: Sat, 24 Oct 2026 20:58:36 +0000
Subject: [php-src] PHP-8.6: Fix JIT reading packed-turned-hash array as packed after string key write
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-142699@lists.php.net to get a copy of this message
Author: Jorg Sowa (jorgsowa) Date: 2026-10-24T22:48:04+02:00 Commit: https://github.com/php/php-src/commit/51808ac54782284428e80ffb2543fdff2d663bef Raw diff: https://github.com/php/php-src/commit/51808ac54782284428e80ffb2543fdff2d663bef.diff Fix JIT reading packed-turned-hash array as packed after string key write Writing a string key into a packed array converts it to a hash with integer keys, but type inference didn't add MAY_BE_ARRAY_NUMERIC_HASH. Closes GH-24526. Changed paths: A ext/opcache/tests/jit/assign_dim_packed_string_key_001.phpt A ext/opcache/tests/jit/assign_dim_packed_string_key_002.phpt A ext/opcache/tests/jit/assign_dim_packed_string_key_003.phpt M NEWS M Zend/Optimizer/zend_inference.c Diff: diff --git a/NEWS b/NEWS index 952acfa5d8e9..568638e23574 100644 --- a/NEWS +++ b/NEWS @@ -117,6 +117,8 @@ PHP NEWS empty array element. (jorgsowa) . Fixed bug GH-24396 (Assertion failure in zend_jit_def_reg() "reg forwarding" with chained Pi nodes). (ndossche) + . Fixed JIT treating an array as packed after a string key write turned it + into a hash. (jorgsowa) - PDO: . Fixed invalid ATTR_ORACLE_NULLS values being accepted and truncated. diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index a2e1d03404d8..dff89b16f9d4 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2224,6 +2224,9 @@ static uint32_t assign_dim_array_result_type( if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) { tmp |= MAY_BE_ARRAY_KEY_STRING; } + if ((tmp & MAY_BE_ARRAY_KEY_STRING) && MAY_BE_PACKED(arr_type)) { + tmp |= MAY_BE_ARRAY_NUMERIC_HASH; + } } } /* Only add value type if we have a key type. It might be that the key type is illegal @@ -3619,6 +3622,9 @@ static zend_always_inline zend_result _zend_update_type_info( if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) { key_type |= MAY_BE_ARRAY_KEY_STRING; } + if ((key_type & MAY_BE_ARRAY_KEY_STRING) && MAY_BE_PACKED(t1)) { + key_type |= MAY_BE_ARRAY_NUMERIC_HASH; + } } } else if (opline->opcode == ZEND_FETCH_DIM_UNSET) { if (t1 & MAY_BE_ARRAY) { diff --git a/ext/opcache/tests/jit/assign_dim_packed_string_key_001.phpt b/ext/opcache/tests/jit/assign_dim_packed_string_key_001.phpt new file mode 100644 index 000000000000..9147f22354dc --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_packed_string_key_001.phpt @@ -0,0 +1,31 @@ +--TEST-- +JIT: string key write turns a packed array into a hash with integer keys (function JIT) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=function +--EXTENSIONS-- +opcache +--FILE-- +<?php +function f() { + $arr = [10, 11]; + for ($i = 2; $i >= 0; $i--) { + $arr['b'] = true; + echo $i, ":\n"; + var_dump($arr[$i]); + } +} +f(); +?> +--EXPECTF-- +2: + +Warning: Undefined array key 2 in %s on line %d +NULL +1: +int(11) +0: +int(10) diff --git a/ext/opcache/tests/jit/assign_dim_packed_string_key_002.phpt b/ext/opcache/tests/jit/assign_dim_packed_string_key_002.phpt new file mode 100644 index 000000000000..bbe512d1f475 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_packed_string_key_002.phpt @@ -0,0 +1,22 @@ +--TEST-- +JIT: compound string key assignment turns a packed array into a hash with integer keys +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=function +--EXTENSIONS-- +opcache +--FILE-- +<?php +function f() { + $arr = [1, 2, 3]; + $arr["a"] += 1; + var_dump($arr[1]); +} +f(); +?> +--EXPECTF-- +Warning: Undefined array key "a" in %s on line %d +int(2) diff --git a/ext/opcache/tests/jit/assign_dim_packed_string_key_003.phpt b/ext/opcache/tests/jit/assign_dim_packed_string_key_003.phpt new file mode 100644 index 000000000000..e28dbb4c8e39 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_packed_string_key_003.phpt @@ -0,0 +1,29 @@ +--TEST-- +JIT: nested string key write turns a packed array into a hash with integer keys (tracing JIT) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=tracing +--EXTENSIONS-- +opcache +--FILE-- +<?php +function f($c) { + $arr = [0 => 'x', 5 => 'y']; + $arr['a'][32] = 1; + $r = 0; + for ($i = 0; $i < 100; $i++) { + $r += isset($arr[0][$c]); + } + var_dump($r); +} +for ($k = 0; $k < 3; $k++) { + f(0); +} +?> +--EXPECT-- +int(100) +int(100) +int(100)

« previous php.cvs (#142699) next »