@@ -1934,10 +1934,22 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
19341934
19351935 uint32_t num_args = orig -> op_array .num_args ;
19361936 if (orig -> op_array .fn_flags & ZEND_ACC_VARIADIC ) num_args ++ ;
1937- size_t arg_info_block = sizeof (zend_arg_info ) * (num_args + 1 );
1937+ uint32_t total = num_args + 1 ;
1938+ size_t arg_info_block = sizeof (zend_arg_info ) * total ;
19381939
19391940 zend_arg_info * new_arg_info = zend_arena_alloc (& CG (arena ), arg_info_block );
19401941 memcpy (new_arg_info , orig -> op_array .arg_info - 1 , arg_info_block );
1942+
1943+ for (uint32_t i = 0 ; i < total ; i ++ ) {
1944+ if (new_arg_info [i ].name ) {
1945+ zend_string_addref (new_arg_info [i ].name );
1946+ }
1947+
1948+ if (new_arg_info [i ].doc_comment ) {
1949+ zend_string_addref (new_arg_info [i ].doc_comment );
1950+ }
1951+ }
1952+
19411953 uint32_t slot = (hi == ZEND_PROPERTY_HOOK_GET ) ? 0 : 1 ;
19421954 new_arg_info [slot ].type = sub ;
19431955 zend_type_copy_ctor (& new_arg_info [slot ].type , true, false);
@@ -2797,6 +2809,17 @@ static void zend_substitute_trait_method_arg_info(
27972809 zend_arg_info * new_block = zend_arena_alloc (& CG (arena ), sizeof (zend_arg_info ) * total );
27982810 memcpy (new_block , orig_block , sizeof (zend_arg_info ) * total );
27992811
2812+ /* The clone shares name/doc_comment string pointers with the parent's arg_info; bump refcount
2813+ * so opcache's interning pass on the parent doesn't release strings the clone still references. */
2814+ for (uint32_t i = 0 ; i < total ; i ++ ) {
2815+ if (new_block [i ].name ) {
2816+ zend_string_addref (new_block [i ].name );
2817+ }
2818+ if (new_block [i ].doc_comment ) {
2819+ zend_string_addref (new_block [i ].doc_comment );
2820+ }
2821+ }
2822+
28002823 uint32_t return_slot_offset = has_return ? 1 : 0 ;
28012824
28022825 if (has_return && orig_op -> generic_types -> return_type ) {
0 commit comments