Skip to content

Fix unstable get_iterator pointer in shm on Windows #17034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -8575,10 +8575,13 @@ static void zend_compile_property_hooks(

ce->num_hooked_props++;

/* See zend_link_hooked_object_iter(). */
#ifndef ZEND_OPCACHE_SHM_REATTACHMENT
if (!ce->get_iterator) {
/* Will be removed again, in case of Iterator or IteratorAggregate. */
ce->get_iterator = zend_hooked_object_get_iterator;
}
#endif

if (!prop_info->ce->parent_name) {
zend_verify_hooked_property(ce, prop_info, prop_name);
Expand Down Expand Up @@ -9104,6 +9107,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 */
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)) {
if (toplevel) {
if (extends_ast) {
Expand Down
31 changes: 30 additions & 1 deletion Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

#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_property_info *property_info;
Expand Down Expand Up @@ -3405,7 +3426,7 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
return ce;
}

#ifndef ZEND_WIN32
#ifndef ZEND_OPCACHE_SHM_REATTACHMENT
# define UPDATE_IS_CACHEABLE(ce) do { \
if ((ce)->type == ZEND_USER_CLASS) { \
is_cacheable &= (ce)->ce_flags; \
Expand Down Expand Up @@ -3550,6 +3571,10 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
zend_enum_register_funcs(ce);
}

#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
zend_link_hooked_object_iter(ce);
#endif

if (parent) {
if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
add_dependency_obligation(ce, parent);
Expand Down Expand Up @@ -3838,6 +3863,10 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
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);
if (parent_ce && parent_ce->num_interfaces) {
zend_do_inherit_interfaces(ce, parent_ce);
Expand Down
7 changes: 7 additions & 0 deletions Zend/zend_portability.h
Original file line number Diff line number Diff line change
Expand Up @@ -863,4 +863,11 @@ static zend_always_inline uint64_t ZEND_BYTES_SWAP64(uint64_t u)
}
#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 */
6 changes: 6 additions & 0 deletions ext/opcache/tests/dump_property_hooks.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ opcache.enable_cli=1
opcache.opt_debug_level=0x20000
--EXTENSIONS--
opcache
--SKIPIF--
<?php
if (PHP_OS_FAMILY === 'Windows') {
die('skip Windows emits additional DECLARE_CLASS_DELAYED opcode');
}
?>
--FILE--
<?php

Expand Down
Loading