@@ -5440,7 +5440,12 @@ static zend_never_inline zend_result ZEND_FASTCALL zend_quick_check_constant(
54405440
54415441static zend_always_inline uint32_t zend_get_arg_offset_by_name (
54425442 zend_function * fbc , zend_string * arg_name , void * * cache_slot ) {
5443- if (EXPECTED (* cache_slot == fbc )) {
5443+ /* Due to closures, the `fbc` address isn't unique if the memory address is reused.
5444+ * The argument info will be however and uniquely positions the arguments.
5445+ * We do support NULL arg_info, so we have to distinguish that from an uninitialized cache slot. */
5446+ void * unique_id = (void * ) ((uintptr_t ) fbc -> common .arg_info | 1 );
5447+
5448+ if (EXPECTED (* cache_slot == unique_id )) {
54445449 return * (uintptr_t * )(cache_slot + 1 );
54455450 }
54465451
@@ -5451,8 +5456,10 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name(
54515456 for (uint32_t i = 0 ; i < num_args ; i ++ ) {
54525457 zend_arg_info * arg_info = & fbc -> op_array .arg_info [i ];
54535458 if (zend_string_equals (arg_name , arg_info -> name )) {
5454- * cache_slot = fbc ;
5455- * (uintptr_t * )(cache_slot + 1 ) = i ;
5459+ if (!fbc -> op_array .refcount || !(fbc -> op_array .fn_flags & ZEND_ACC_CLOSURE )) {
5460+ * cache_slot = unique_id ;
5461+ * (uintptr_t * )(cache_slot + 1 ) = i ;
5462+ }
54565463 return i ;
54575464 }
54585465 }
@@ -5462,16 +5469,18 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name(
54625469 zend_internal_arg_info * arg_info = & fbc -> internal_function .arg_info [i ];
54635470 size_t len = strlen (arg_info -> name );
54645471 if (zend_string_equals_cstr (arg_name , arg_info -> name , len )) {
5465- * cache_slot = fbc ;
5472+ * cache_slot = unique_id ;
54665473 * (uintptr_t * )(cache_slot + 1 ) = i ;
54675474 return i ;
54685475 }
54695476 }
54705477 }
54715478
54725479 if (fbc -> common .fn_flags & ZEND_ACC_VARIADIC ) {
5473- * cache_slot = fbc ;
5474- * (uintptr_t * )(cache_slot + 1 ) = fbc -> common .num_args ;
5480+ if (fbc -> type == ZEND_INTERNAL_FUNCTION || !fbc -> op_array .refcount || !(fbc -> op_array .fn_flags & ZEND_ACC_CLOSURE )) {
5481+ * cache_slot = unique_id ;
5482+ * (uintptr_t * )(cache_slot + 1 ) = fbc -> common .num_args ;
5483+ }
54755484 return fbc -> common .num_args ;
54765485 }
54775486
0 commit comments