summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-01-14 15:06:26 +0300
committerDmitry Stogov <dmitry@zend.com>2015-01-14 15:06:26 +0300
commit232575862427e5e4a42665596773cac709e9275b (patch)
treeb6181dc167f75dc6caee536e9189e88d13273ce9
parent588e803e8522434d769315fecf309ad12c9bfd69 (diff)
downloadphp-git-232575862427e5e4a42665596773cac709e9275b.tar.gz
Improve "instanceof". Interfaces of the left operand should be checked only if the right operand is interafce itself.
-rw-r--r--Zend/zend_operators.c56
-rw-r--r--Zend/zend_vm_def.h4
-rw-r--r--Zend/zend_vm_execute.h10
3 files changed, 54 insertions, 16 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 7ce8664232..e726f57b05 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -2004,31 +2004,69 @@ ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) /*
}
/* }}} */
-ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only) /* {{{ */
+static zend_bool instanceof_inerface_only(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
{
uint32_t i;
- for (i=0; i<instance_ce->num_interfaces; i++) {
- if (instanceof_function(instance_ce->interfaces[i], ce)) {
+ for (i = 0; i < instance_ce->num_interfaces; i++) {
+ if (instanceof_inerface_only(instance_ce->interfaces[i], ce)) {
return 1;
}
}
- if (!interfaces_only) {
- while (instance_ce) {
- if (instance_ce == ce) {
+ return 0;
+}
+/* }}} */
+
+static zend_always_inline zend_bool instanceof_class(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
+{
+ while (instance_ce) {
+ if (instance_ce == ce) {
+ return 1;
+ }
+ instance_ce = instance_ce->parent;
+ }
+ return 0;
+}
+/* }}} */
+
+static zend_bool instanceof_interface(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
+{
+ uint32_t i;
+
+ for (i = 0; i < instance_ce->num_interfaces; i++) {
+ if (instanceof_interface(instance_ce->interfaces[i], ce)) {
+ return 1;
+ }
+ }
+ return instanceof_class(instance_ce, ce);
+}
+/* }}} */
+
+ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only) /* {{{ */
+{
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ if (!interfaces_only) {
+ if (instanceof_inerface_only(instance_ce, ce)) {
return 1;
}
- instance_ce = instance_ce->parent;
+ } else {
+ return instanceof_interface(instance_ce, ce);
}
}
-
+ if (!interfaces_only) {
+ return instanceof_class(instance_ce, ce);
+ }
return 0;
}
/* }}} */
ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
{
- return instanceof_function_ex(instance_ce, ce, 0);
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ return instanceof_interface(instance_ce, ce);
+ } else {
+ return instanceof_class(instance_ce, ce);
+ }
}
/* }}} */
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index fb49a49faf..6642eee7bb 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3119,7 +3119,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
#endif /* HAVE_DTRACE */
if (ce != catch_ce) {
- if (!instanceof_function(ce, catch_ce)) {
+ if (!catch_ce || !instanceof_function(ce, catch_ce)) {
if (opline->result.num) {
zend_throw_exception_internal(NULL);
HANDLE_EXCEPTION();
@@ -5597,7 +5597,7 @@ ZEND_VM_C_LABEL(try_instanceof):
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- result = instanceof_function(Z_OBJCE_P(expr), ce);
+ result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
} else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
expr = Z_REFVAL_P(expr);
ZEND_VM_C_GOTO(try_instanceof);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 8936f79e90..6f9d7456dc 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -7248,7 +7248,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
#endif /* HAVE_DTRACE */
if (ce != catch_ce) {
- if (!instanceof_function(ce, catch_ce)) {
+ if (!catch_ce || !instanceof_function(ce, catch_ce)) {
if (opline->result.num) {
zend_throw_exception_internal(NULL);
HANDLE_EXCEPTION();
@@ -26681,7 +26681,7 @@ try_instanceof:
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- result = instanceof_function(Z_OBJCE_P(expr), ce);
+ result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
expr = Z_REFVAL_P(expr);
goto try_instanceof;
@@ -27599,7 +27599,7 @@ try_instanceof:
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- result = instanceof_function(Z_OBJCE_P(expr), ce);
+ result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
expr = Z_REFVAL_P(expr);
goto try_instanceof;
@@ -34243,7 +34243,7 @@ try_instanceof:
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- result = instanceof_function(Z_OBJCE_P(expr), ce);
+ result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
expr = Z_REFVAL_P(expr);
goto try_instanceof;
@@ -34649,7 +34649,7 @@ try_instanceof:
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- result = instanceof_function(Z_OBJCE_P(expr), ce);
+ result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
expr = Z_REFVAL_P(expr);
goto try_instanceof;