Skip to content

Commit f07565b

Browse files
committed
Check class linking in VERIFY_RETURN_TYPE optimization
instanceof_function() requires linked classes. I'm not reusing unlinked_instanceof() here, because it performs class loading, which wouldn't be right here, I think.
1 parent a8b4e40 commit f07565b

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,17 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
306306
free_alloca(shiftlist, use_heap);
307307
}
308308

309+
static zend_bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
310+
if (ce1 == ce2) {
311+
return 1;
312+
}
313+
if (!(ce1->ce_flags & ZEND_ACC_LINKED)) {
314+
/* This case could be generalized, similarly to unlinked_instanceof */
315+
return 0;
316+
}
317+
return instanceof_function(ce1, ce2);
318+
}
319+
309320
static inline zend_bool can_elide_return_type_check(
310321
zend_op_array *op_array, zend_ssa *ssa, zend_ssa_op *ssa_op) {
311322
zend_arg_info *info = &op_array->arg_info[-1];
@@ -327,7 +338,7 @@ static inline zend_bool can_elide_return_type_check(
327338
}
328339

329340
if (ZEND_TYPE_IS_CLASS(info->type)) {
330-
if (!use_info->ce || !def_info->ce || !instanceof_function(use_info->ce, def_info->ce)) {
341+
if (!use_info->ce || !def_info->ce || !safe_instanceof(use_info->ce, def_info->ce)) {
331342
return 0;
332343
}
333344
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Instanceof checks in VERIFY_RETURN_TYPE optimization may deal with unlinked classes
3+
--FILE--
4+
<?php
5+
interface foo { }
6+
7+
interface biz {}
8+
9+
class qux implements foo {
10+
public function bar(): biz {
11+
$x = $this;
12+
return $x;
13+
}
14+
}
15+
16+
?>
17+
===DONE===
18+
--EXPECT--
19+
===DONE===

0 commit comments

Comments
 (0)