summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-10-25 11:24:32 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-10-25 11:24:32 +0200
commitf07565b0ebdfc5b8210bbf58d994ebd319014e67 (patch)
treef1e4dc0a53f22105b7e50a0d7b4e7eeb12fb22f0
parenta8b4e40fa225f4f2524cc29c37119d00005ccca1 (diff)
downloadphp-git-f07565b0ebdfc5b8210bbf58d994ebd319014e67.tar.gz
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.
-rw-r--r--ext/opcache/Optimizer/dfa_pass.c13
-rw-r--r--ext/opcache/tests/verify_return_instanceof.phpt19
2 files changed, 31 insertions, 1 deletions
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c
index 5401c9df6a..4c2162a021 100644
--- a/ext/opcache/Optimizer/dfa_pass.c
+++ b/ext/opcache/Optimizer/dfa_pass.c
@@ -306,6 +306,17 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
free_alloca(shiftlist, use_heap);
}
+static zend_bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
+ if (ce1 == ce2) {
+ return 1;
+ }
+ if (!(ce1->ce_flags & ZEND_ACC_LINKED)) {
+ /* This case could be generalized, similarly to unlinked_instanceof */
+ return 0;
+ }
+ return instanceof_function(ce1, ce2);
+}
+
static inline zend_bool can_elide_return_type_check(
zend_op_array *op_array, zend_ssa *ssa, zend_ssa_op *ssa_op) {
zend_arg_info *info = &op_array->arg_info[-1];
@@ -327,7 +338,7 @@ static inline zend_bool can_elide_return_type_check(
}
if (ZEND_TYPE_IS_CLASS(info->type)) {
- if (!use_info->ce || !def_info->ce || !instanceof_function(use_info->ce, def_info->ce)) {
+ if (!use_info->ce || !def_info->ce || !safe_instanceof(use_info->ce, def_info->ce)) {
return 0;
}
}
diff --git a/ext/opcache/tests/verify_return_instanceof.phpt b/ext/opcache/tests/verify_return_instanceof.phpt
new file mode 100644
index 0000000000..14323d533b
--- /dev/null
+++ b/ext/opcache/tests/verify_return_instanceof.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Instanceof checks in VERIFY_RETURN_TYPE optimization may deal with unlinked classes
+--FILE--
+<?php
+interface foo { }
+
+interface biz {}
+
+class qux implements foo {
+ public function bar(): biz {
+ $x = $this;
+ return $x;
+ }
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===