Skip to content

Commit 8242953

Browse files
committed
Avoid early-binding on unresolved types
Fixes bug #76451, and more importantly lays necessary groundwork for covariant/contravariant types. Bug #76451 is just an edge case, but once covariance is introduced this will become a common problem instead.
1 parent 64918c7 commit 8242953

File tree

7 files changed

+166
-45
lines changed

7 files changed

+166
-45
lines changed

Zend/tests/bug76451.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
class Foo {}
4+
class_alias('Foo', 'Bar');

Zend/tests/bug76451.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Bug #76451: Aliases during inheritance type checks affected by opcache
3+
--FILE--
4+
<?php
5+
require __DIR__ . "/bug76451.inc";
6+
7+
class A {
8+
public function test(Foo $foo) {}
9+
}
10+
class B extends A {
11+
public function test(Bar $foo) {}
12+
}
13+
?>
14+
===DONE===
15+
--EXPECT--
16+
===DONE===

Zend/tests/bug76451_2.inc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
class A {
3+
public function test(Foo $foo) {}
4+
}
5+
class B extends A {
6+
public function test(Bar $foo) {}
7+
}
8+
?>

Zend/tests/bug76451_2.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Bug #76451: Aliases during inheritance type checks affected by opcache (variation)
3+
--FILE--
4+
<?php
5+
class Foo {}
6+
class_alias('Foo', 'Bar');
7+
8+
require __DIR__ . '/bug76451_2.inc';
9+
?>
10+
===DONE===
11+
--EXPECT--
12+
===DONE===

Zend/zend_compile.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,14 +1131,16 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint3
11311131
if (first_early_binding_opline != (uint32_t)-1) {
11321132
zend_bool orig_in_compilation = CG(in_compilation);
11331133
uint32_t opline_num = first_early_binding_opline;
1134-
zend_class_entry *ce;
11351134

11361135
CG(in_compilation) = 1;
11371136
while (opline_num != (uint32_t)-1) {
11381137
const zend_op *opline = &op_array->opcodes[opline_num];
1138+
zval *lcname = RT_CONSTANT(opline, opline->op1);
11391139
zval *parent_name = RT_CONSTANT(opline, opline->op2);
1140-
if ((ce = zend_lookup_class_ex(Z_STR_P(parent_name), Z_STR_P(parent_name + 1), 0)) != NULL) {
1141-
do_bind_class(RT_CONSTANT(&op_array->opcodes[opline_num], op_array->opcodes[opline_num].op1), ce);
1140+
zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname + 1));
1141+
zend_class_entry *parent_ce = zend_lookup_class_ex(Z_STR_P(parent_name), Z_STR_P(parent_name + 1), 0);
1142+
if (ce && parent_ce && zend_can_early_bind(ce, parent_ce)) {
1143+
do_bind_class(lcname, parent_ce);
11421144
}
11431145
opline_num = op_array->opcodes[opline_num].result.opline_num;
11441146
}
@@ -6392,6 +6394,7 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
63926394
&& !(CG(compiler_options) & ZEND_COMPILE_PRELOAD) /* delay inheritance till preloading */
63936395
&& ((parent_ce->type != ZEND_INTERNAL_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES))
63946396
&& ((parent_ce->type != ZEND_USER_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) || (parent_ce->info.user.filename == ce->info.user.filename))
6397+
&& zend_can_early_bind(ce, parent_ce)
63956398
) {
63966399
if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
63976400
CG(zend_lineno) = decl->end_lineno;

0 commit comments

Comments
 (0)