@@ -5250,7 +5250,12 @@ static zend_never_inline zend_result ZEND_FASTCALL zend_quick_check_constant(
52505250
52515251static zend_always_inline uint32_t zend_get_arg_offset_by_name (
52525252 zend_function * fbc , zend_string * arg_name , void * * cache_slot ) {
5253- if (EXPECTED (* cache_slot == fbc )) {
5253+ /* Due to closures, the `fbc` address isn't unique if the memory address is reused.
5254+ * The argument info will be however and uniquely positions the arguments.
5255+ * We do support NULL arg_info, so we have to distinguish that from an uninitialized cache slot. */
5256+ void * unique_id = (void * ) ((uintptr_t ) fbc -> common .arg_info | 1 );
5257+
5258+ if (EXPECTED (* cache_slot == unique_id )) {
52545259 return * (uintptr_t * )(cache_slot + 1 );
52555260 }
52565261
@@ -5261,8 +5266,10 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name(
52615266 for (uint32_t i = 0 ; i < num_args ; i ++ ) {
52625267 zend_arg_info * arg_info = & fbc -> op_array .arg_info [i ];
52635268 if (zend_string_equals (arg_name , arg_info -> name )) {
5264- * cache_slot = fbc ;
5265- * (uintptr_t * )(cache_slot + 1 ) = i ;
5269+ if (!fbc -> op_array .refcount || !(fbc -> op_array .fn_flags & ZEND_ACC_CLOSURE )) {
5270+ * cache_slot = unique_id ;
5271+ * (uintptr_t * )(cache_slot + 1 ) = i ;
5272+ }
52665273 return i ;
52675274 }
52685275 }
@@ -5271,16 +5278,18 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name(
52715278 zend_internal_arg_info * arg_info = & fbc -> internal_function .arg_info [i ];
52725279 size_t len = strlen (arg_info -> name );
52735280 if (zend_string_equals_cstr (arg_name , arg_info -> name , len )) {
5274- * cache_slot = fbc ;
5281+ * cache_slot = unique_id ;
52755282 * (uintptr_t * )(cache_slot + 1 ) = i ;
52765283 return i ;
52775284 }
52785285 }
52795286 }
52805287
52815288 if (fbc -> common .fn_flags & ZEND_ACC_VARIADIC ) {
5282- * cache_slot = fbc ;
5283- * (uintptr_t * )(cache_slot + 1 ) = fbc -> common .num_args ;
5289+ if (fbc -> type == ZEND_INTERNAL_FUNCTION || !fbc -> op_array .refcount || !(fbc -> op_array .fn_flags & ZEND_ACC_CLOSURE )) {
5290+ * cache_slot = unique_id ;
5291+ * (uintptr_t * )(cache_slot + 1 ) = fbc -> common .num_args ;
5292+ }
52845293 return fbc -> common .num_args ;
52855294 }
52865295
0 commit comments