Merge branch 'PHP-8.4'

* PHP-8.4:
  Fix unstable get_iterator pointer for hooked classes in shm on Windows
This commit is contained in:
Ilija Tovilo 2024-12-09 17:14:46 +01:00
commit fbb97aa6fc
No known key found for this signature in database
GPG key ID: 5050C66BFCD1015A
4 changed files with 50 additions and 1 deletions

View file

@ -8598,10 +8598,13 @@ static void zend_compile_property_hooks(
ce->num_hooked_props++; ce->num_hooked_props++;
/* See zend_link_hooked_object_iter(). */
#ifndef ZEND_OPCACHE_SHM_REATTACHMENT
if (!ce->get_iterator) { if (!ce->get_iterator) {
/* Will be removed again, in case of Iterator or IteratorAggregate. */ /* Will be removed again, in case of Iterator or IteratorAggregate. */
ce->get_iterator = zend_hooked_object_get_iterator; ce->get_iterator = zend_hooked_object_get_iterator;
} }
#endif
if (!prop_info->ce->parent_name) { if (!prop_info->ce->parent_name) {
zend_verify_hooked_property(ce, prop_info, prop_name); zend_verify_hooked_property(ce, prop_info, prop_name);
@ -9127,6 +9130,10 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
/* We currently don't early-bind classes that implement interfaces or use traits */ /* We currently don't early-bind classes that implement interfaces or use traits */
if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
/* See zend_link_hooked_object_iter(). */
&& !ce->num_hooked_props
#endif
&& !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) { && !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) {
if (toplevel) { if (toplevel) {
if (extends_ast) { if (extends_ast) {

View file

@ -1746,6 +1746,27 @@ ZEND_API inheritance_status zend_verify_property_hook_variance(const zend_proper
return zend_perform_covariant_type_check(ce, prop_info->type, ce, value_arg_info->type); return zend_perform_covariant_type_check(ce, prop_info->type, ce, value_arg_info->type);
} }
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
/* Hooked properties set get_iterator, which causes issues on for shm
* reattachment. Avoid early-binding on Windows and set get_iterator during
* inheritance. The linked class may not use inheritance cache. */
static void zend_link_hooked_object_iter(zend_class_entry *ce) {
if (!ce->get_iterator && ce->num_hooked_props) {
ce->get_iterator = zend_hooked_object_get_iterator;
ce->ce_flags &= ~ZEND_ACC_CACHEABLE;
if (CG(current_linking_class) == ce) {
# if ZEND_DEBUG
/* This check is executed before inheriting any elements that can
* track dependencies. */
HashTable *ht = (HashTable*)ce->inheritance_cache;
ZEND_ASSERT(!ht);
# endif
CG(current_linking_class) = NULL;
}
}
}
#endif
ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *parent_ce, bool checked) /* {{{ */ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *parent_ce, bool checked) /* {{{ */
{ {
zend_property_info *property_info; zend_property_info *property_info;
@ -3422,7 +3443,7 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
return ce; return ce;
} }
#ifndef ZEND_WIN32 #ifndef ZEND_OPCACHE_SHM_REATTACHMENT
# define UPDATE_IS_CACHEABLE(ce) do { \ # define UPDATE_IS_CACHEABLE(ce) do { \
if ((ce)->type == ZEND_USER_CLASS) { \ if ((ce)->type == ZEND_USER_CLASS) { \
is_cacheable &= (ce)->ce_flags; \ is_cacheable &= (ce)->ce_flags; \
@ -3567,6 +3588,10 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
zend_enum_register_funcs(ce); zend_enum_register_funcs(ce);
} }
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
zend_link_hooked_object_iter(ce);
#endif
if (parent) { if (parent) {
if (!(parent->ce_flags & ZEND_ACC_LINKED)) { if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
add_dependency_obligation(ce, parent); add_dependency_obligation(ce, parent);
@ -3855,6 +3880,10 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
zend_begin_record_errors(); zend_begin_record_errors();
} }
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
zend_link_hooked_object_iter(ce);
#endif
zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS); zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS);
if (parent_ce && parent_ce->num_interfaces) { if (parent_ce && parent_ce->num_interfaces) {
zend_do_inherit_interfaces(ce, parent_ce); zend_do_inherit_interfaces(ce, parent_ce);

View file

@ -865,4 +865,11 @@ static zend_always_inline uint64_t ZEND_BYTES_SWAP64(uint64_t u)
} }
#endif #endif
#ifdef ZEND_WIN32
/* Whether it's allowed to reattach to a shm segment from different processes on
* this platform. This prevents pointing to internal structures from shm due to
* ASLR. Currently only possible on Windows. */
# define ZEND_OPCACHE_SHM_REATTACHMENT 1
#endif
#endif /* ZEND_PORTABILITY_H */ #endif /* ZEND_PORTABILITY_H */

View file

@ -6,6 +6,12 @@ opcache.enable_cli=1
opcache.opt_debug_level=0x20000 opcache.opt_debug_level=0x20000
--EXTENSIONS-- --EXTENSIONS--
opcache opcache
--SKIPIF--
<?php
if (PHP_OS_FAMILY === 'Windows') {
die('skip Windows emits additional DECLARE_CLASS_DELAYED opcode');
}
?>
--FILE-- --FILE--
<?php <?php