Skip to content

Commit 5388143

Browse files
committed
Fixed bug #77652
1 parent 08089b5 commit 5388143

File tree

4 files changed

+49
-1
lines changed

4 files changed

+49
-1
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? 2019, PHP 7.2.17
44

5+
- Core:
6+
. Fixed bug #77652 (Anonymous classes can lose their interface information).
7+
(Nikita)
8+
59
- MySQLi:
610
. Fixed bug #77597 (mysqli_fetch_field hangs scripts). (Nikita)
711

Zend/tests/bug77652.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
return [
3+
'I' => function() {
4+
return new class implements I {};
5+
},
6+
];

Zend/tests/bug77652.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Bug #77652: Anonymous classes can lose their interface information
3+
--FILE--
4+
<?php
5+
6+
interface I {}
7+
require __DIR__ . '/bug77652.inc';
8+
$data = require __DIR__ . '/bug77652.inc';
9+
print_r(class_implements($data['I']()));
10+
11+
?>
12+
--EXPECT--
13+
Array
14+
(
15+
[I] => I
16+
)

Zend/zend_compile.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6365,10 +6365,32 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
63656365
if (!zend_hash_exists(CG(class_table), lcname)) {
63666366
zend_hash_add_ptr(CG(class_table), lcname, ce);
63676367
} else {
6368-
/* this anonymous class has been included */
6368+
/* This anonymous class has been included, reuse the existing definition.
6369+
* NB: This behavior is buggy, and this should always result in a separate
6370+
* class declaration. However, until the problem of RTD key collisions is
6371+
* solved, this gives a behavior close to what is expected. */
63696372
zval zv;
63706373
ZVAL_PTR(&zv, ce);
63716374
destroy_zend_class(&zv);
6375+
ce = zend_hash_find_ptr(CG(class_table), lcname);
6376+
6377+
/* Manually replicate emission of necessary inheritance opcodes here. We cannot
6378+
* reuse the general code, as we only want to emit the opcodes, without modifying
6379+
* the reused class definition. */
6380+
if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) {
6381+
zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL);
6382+
}
6383+
if (implements_ast) {
6384+
zend_ast_list *iface_list = zend_ast_get_list(implements_ast);
6385+
uint32_t i;
6386+
for (i = 0; i < iface_list->children; i++) {
6387+
opline = zend_emit_op(NULL, ZEND_ADD_INTERFACE, &declare_node, NULL);
6388+
opline->op2_type = IS_CONST;
6389+
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
6390+
zend_resolve_class_name_ast(iface_list->child[i]));
6391+
}
6392+
zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL);
6393+
}
63726394
return;
63736395
}
63746396
} else {

0 commit comments

Comments
 (0)