@@ -1382,6 +1382,16 @@ static void inherit_property_hook(
13821382 if (child
13831383 && (child -> common .fn_flags & ZEND_ACC_OVERRIDE )
13841384 && property_has_operation (parent_info , kind )) {
1385+ /* Duplicate child function if it comes from opcache-protected memory */
1386+ if (child -> common .scope != ce ) {
1387+ child = zend_duplicate_function (child , ce );
1388+ if (!child_info -> hooks ) {
1389+ ce -> num_hooked_props ++ ;
1390+ child_info -> hooks = zend_arena_alloc (& CG (arena ), ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1391+ memset (child_info -> hooks , 0 , ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1392+ }
1393+ child_info -> hooks [kind ] = child ;
1394+ }
13851395 child -> common .fn_flags &= ~ZEND_ACC_OVERRIDE ;
13861396 }
13871397
@@ -1406,6 +1416,17 @@ static void inherit_property_hook(
14061416 return ;
14071417 }
14081418
1419+ /* Duplicate child function if it comes from opcache-protected memory */
1420+ if (child -> common .scope != ce ) {
1421+ child = zend_duplicate_function (child , ce );
1422+ if (!child_info -> hooks ) {
1423+ ce -> num_hooked_props ++ ;
1424+ child_info -> hooks = zend_arena_alloc (& CG (arena ), ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1425+ memset (child_info -> hooks , 0 , ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1426+ }
1427+ child_info -> hooks [kind ] = child ;
1428+ }
1429+
14091430 child -> common .prototype = parent -> common .prototype ? parent -> common .prototype : parent ;
14101431
14111432 uint32_t parent_flags = parent -> common .fn_flags ;
@@ -1543,6 +1564,25 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
15431564 child_info -> flags &= ~ZEND_ACC_VIRTUAL ;
15441565 }
15451566
1567+ /* Create a copy if this property comes from opcache-protected memory */
1568+ if (child_info -> ce != ce ) {
1569+ zend_property_info * new_prop_info = zend_arena_alloc (& CG (arena ), sizeof (zend_property_info ));
1570+ memcpy (new_prop_info , child_info , sizeof (zend_property_info ));
1571+ new_prop_info -> ce = ce ;
1572+ /* Deep copy the type information */
1573+ zend_type_copy_ctor (& new_prop_info -> type , /* use_arena */ true, /* persistent */ false);
1574+ if (new_prop_info -> hooks ) {
1575+ new_prop_info -> hooks = zend_arena_alloc (& CG (arena ), ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1576+ memcpy (new_prop_info -> hooks , child_info -> hooks , ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1577+ }
1578+ /* Re-fetch and update the child entry in the hash table */
1579+ child = zend_hash_find_known_hash (& ce -> properties_info , key );
1580+ if (EXPECTED (child )) {
1581+ Z_PTR_P (child ) = new_prop_info ;
1582+ child_info = new_prop_info ;
1583+ }
1584+ }
1585+
15461586 if (parent_info -> hooks || child_info -> hooks ) {
15471587 for (uint32_t i = 0 ; i < ZEND_PROPERTY_HOOK_COUNT ; i ++ ) {
15481588 inherit_property_hook (ce , parent_info , child_info , i );
0 commit comments