Skip to content

Commit fbb97aa

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix unstable get_iterator pointer for hooked classes in shm on Windows
2 parents f11d9b5 + 792f63d commit fbb97aa

File tree

4 files changed

+50
-1
lines changed

4 files changed

+50
-1
lines changed

Zend/zend_compile.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8598,10 +8598,13 @@ static void zend_compile_property_hooks(
85988598

85998599
ce->num_hooked_props++;
86008600

8601+
/* See zend_link_hooked_object_iter(). */
8602+
#ifndef ZEND_OPCACHE_SHM_REATTACHMENT
86018603
if (!ce->get_iterator) {
86028604
/* Will be removed again, in case of Iterator or IteratorAggregate. */
86038605
ce->get_iterator = zend_hooked_object_get_iterator;
86048606
}
8607+
#endif
86058608

86068609
if (!prop_info->ce->parent_name) {
86078610
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)
91279130

91289131
/* We currently don't early-bind classes that implement interfaces or use traits */
91299132
if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks
9133+
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
9134+
/* See zend_link_hooked_object_iter(). */
9135+
&& !ce->num_hooked_props
9136+
#endif
91309137
&& !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) {
91319138
if (toplevel) {
91329139
if (extends_ast) {

Zend/zend_inheritance.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,27 @@ ZEND_API inheritance_status zend_verify_property_hook_variance(const zend_proper
17461746
return zend_perform_covariant_type_check(ce, prop_info->type, ce, value_arg_info->type);
17471747
}
17481748

1749+
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
1750+
/* Hooked properties set get_iterator, which causes issues on for shm
1751+
* reattachment. Avoid early-binding on Windows and set get_iterator during
1752+
* inheritance. The linked class may not use inheritance cache. */
1753+
static void zend_link_hooked_object_iter(zend_class_entry *ce) {
1754+
if (!ce->get_iterator && ce->num_hooked_props) {
1755+
ce->get_iterator = zend_hooked_object_get_iterator;
1756+
ce->ce_flags &= ~ZEND_ACC_CACHEABLE;
1757+
if (CG(current_linking_class) == ce) {
1758+
# if ZEND_DEBUG
1759+
/* This check is executed before inheriting any elements that can
1760+
* track dependencies. */
1761+
HashTable *ht = (HashTable*)ce->inheritance_cache;
1762+
ZEND_ASSERT(!ht);
1763+
# endif
1764+
CG(current_linking_class) = NULL;
1765+
}
1766+
}
1767+
}
1768+
#endif
1769+
17491770
ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *parent_ce, bool checked) /* {{{ */
17501771
{
17511772
zend_property_info *property_info;
@@ -3422,7 +3443,7 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
34223443
return ce;
34233444
}
34243445

3425-
#ifndef ZEND_WIN32
3446+
#ifndef ZEND_OPCACHE_SHM_REATTACHMENT
34263447
# define UPDATE_IS_CACHEABLE(ce) do { \
34273448
if ((ce)->type == ZEND_USER_CLASS) { \
34283449
is_cacheable &= (ce)->ce_flags; \
@@ -3567,6 +3588,10 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
35673588
zend_enum_register_funcs(ce);
35683589
}
35693590

3591+
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
3592+
zend_link_hooked_object_iter(ce);
3593+
#endif
3594+
35703595
if (parent) {
35713596
if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
35723597
add_dependency_obligation(ce, parent);
@@ -3855,6 +3880,10 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
38553880
zend_begin_record_errors();
38563881
}
38573882

3883+
#ifdef ZEND_OPCACHE_SHM_REATTACHMENT
3884+
zend_link_hooked_object_iter(ce);
3885+
#endif
3886+
38583887
zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS);
38593888
if (parent_ce && parent_ce->num_interfaces) {
38603889
zend_do_inherit_interfaces(ce, parent_ce);

Zend/zend_portability.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,4 +865,11 @@ static zend_always_inline uint64_t ZEND_BYTES_SWAP64(uint64_t u)
865865
}
866866
#endif
867867

868+
#ifdef ZEND_WIN32
869+
/* Whether it's allowed to reattach to a shm segment from different processes on
870+
* this platform. This prevents pointing to internal structures from shm due to
871+
* ASLR. Currently only possible on Windows. */
872+
# define ZEND_OPCACHE_SHM_REATTACHMENT 1
873+
#endif
874+
868875
#endif /* ZEND_PORTABILITY_H */

ext/opcache/tests/dump_property_hooks.phpt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ opcache.enable_cli=1
66
opcache.opt_debug_level=0x20000
77
--EXTENSIONS--
88
opcache
9+
--SKIPIF--
10+
<?php
11+
if (PHP_OS_FAMILY === 'Windows') {
12+
die('skip Windows emits additional DECLARE_CLASS_DELAYED opcode');
13+
}
14+
?>
915
--FILE--
1016
<?php
1117

0 commit comments

Comments
 (0)