Skip to content
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
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ PHP NEWS
. Fix too wide type inference for ASSIGN_DIM_OP. (ndossche)
. Fix OSS-Fuzz #568005340 (FETCH_DIM_FUNC_ARG partial conversion). (ndossche)
. Fix exception checks due to NAN warnings and object empty()'s. (ndossche)
. Fixed bug GH-24270 (JIT loses the called scope of self:: and parent:: calls
in closures). (RV7PR)

- PDO:
. Fixed a duplicate warning when ATTR_STATEMENT_CLASS is rejected on a
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -9344,7 +9344,7 @@ static int zend_jit_init_static_method_call(zend_jit_ctx *jit,
ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_EX(This.value.ref)), offsetof(zend_object, ce))));
ir_IF_FALSE(if_object);
ir_END_PHI_list(values, ir_LOAD_A(jit_EX(This.value.ref)));
ir_PHI_list(values);
scope_ref = ir_PHI_list(values);
} else {
scope_ref = ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_EX(This.value.ref)), offsetof(zend_object, ce)));
}
Expand Down
74 changes: 74 additions & 0 deletions ext/opcache/tests/jit/gh24270.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
class Base {
public static function staticSelf(): Closure {
return fn() => self::make();
}
public function boundSelf(): Closure {
return fn() => self::make();
}
private static function make() {
return new static();
}
}
class Mid extends Base {
protected static function name() {
return static::class;
}
}
class Child extends Mid {
public function boundParent(): Closure {
return fn() => parent::name();
}
}
class GrandChild extends Child {}

class ParentA {
public static function name() {
return static::class;
}
}
class ParentB {
public static function name() {
return static::class;
}
}
trait T {
public static function traitSelf(): Closure {
return fn() => self::make();
}
public function traitParent(): Closure {
return fn() => parent::name();
}
public static function make() {
return new static();
}
}
class A extends ParentA {
use T;
}
class ChildA extends A {}
class B extends ParentB {
use T;
}
class ChildB extends B {}

$closures = [
'self from static method' => Child::staticSelf(),
'bound self' => (new Child)->boundSelf(),
'bound parent' => (new GrandChild)->boundParent(),
'trait self A' => ChildA::traitSelf(),
'trait self B' => ChildB::traitSelf(),
'trait parent A' => (new ChildA)->traitParent(),
'trait parent B' => (new ChildB)->traitParent(),
];

$results = [];
for ($i = 0; $i < 100; $i++) {
foreach ($closures as $name => $closure) {
$result = $closure();
$results[$name][is_object($result) ? $result::class : $result] = true;
}
}
foreach ($results as $name => $classes) {
echo $name, ': ', implode(', ', array_keys($classes)), "\n";
}
22 changes: 22 additions & 0 deletions ext/opcache/tests/jit/gh24270_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
GH-24270 001: Function JIT loses the called scope of self:: and parent:: calls in closures
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.file_update_protection=0
opcache.jit=function
opcache.jit_buffer_size=64M
--EXTENSIONS--
opcache
--FILE--
<?php
require __DIR__ . '/gh24270.inc';
?>
--EXPECT--
self from static method: Child
bound self: Child
bound parent: GrandChild
trait self A: ChildA
trait self B: ChildB
trait parent A: ChildA
trait parent B: ChildB
24 changes: 24 additions & 0 deletions ext/opcache/tests/jit/gh24270_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
GH-24270 002: Tracing JIT loses the called scope of self:: and parent:: calls in closures
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.file_update_protection=0
opcache.jit=tracing
opcache.jit_buffer_size=64M
opcache.jit_hot_func=1
opcache.jit_hot_loop=1
--EXTENSIONS--
opcache
--FILE--
<?php
require __DIR__ . '/gh24270.inc';
?>
--EXPECT--
self from static method: Child
bound self: Child
bound parent: GrandChild
trait self A: ChildA
trait self B: ChildB
trait parent A: ChildA
trait parent B: ChildB
Loading