summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/closure_call.phpt10
-rw-r--r--Zend/zend_closures.c16
2 files changed, 21 insertions, 5 deletions
diff --git a/Zend/tests/closure_call.phpt b/Zend/tests/closure_call.phpt
index d53b6077ee..e8bed36aec 100644
--- a/Zend/tests/closure_call.phpt
+++ b/Zend/tests/closure_call.phpt
@@ -42,7 +42,7 @@ $beta = function ($z) {
};
// Ensure argument passing works
-var_dump($beta->call($elePHPant, 3));
+var_dump($beta->call($foobar, 7));
// Ensure ->call calls with scope of passed object
class FooBar {
@@ -56,10 +56,12 @@ $foo = function () {
$foo->call(new FooBar);
?>
---EXPECT--
+--EXPECTF--
int(0)
int(0)
int(3)
-int(7)
+
+Warning: Cannot bind closure to object of internal class stdClass in %s line %d
+NULL
int(21)
-int(3) \ No newline at end of file
+int(3)
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index ec63f48884..e656f8d6ca 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -80,6 +80,7 @@ ZEND_METHOD(Closure, call)
zval *my_params;
int my_param_count = 0;
zend_function my_function;
+ zend_object *newobj;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o*", &newthis, &my_params, &my_param_count) == FAILURE) {
return;
@@ -102,6 +103,14 @@ ZEND_METHOD(Closure, call)
}
}
+ newobj = Z_OBJ_P(newthis);
+
+ if (newobj->ce != closure->func.common.scope && newobj->ce->type == ZEND_INTERNAL_CLASS) {
+ /* rebinding to internal class is not allowed */
+ zend_error(E_WARNING, "Cannot bind closure to object of internal class %s", newobj->ce->name->val);
+ return;
+ }
+
/* This should never happen as closures will always be callable */
if (zend_fcall_info_init(zclosure, 0, &fci, &fci_cache, NULL, NULL) != SUCCESS) {
ZEND_ASSERT(0);
@@ -110,7 +119,7 @@ ZEND_METHOD(Closure, call)
fci.retval = &closure_result;
fci.params = my_params;
fci.param_count = my_param_count;
- fci.object = fci_cache.object = Z_OBJ_P(newthis);
+ fci.object = fci_cache.object = newobj;
fci_cache.initialized = 1;
my_function = *fci_cache.function_handler;
@@ -158,6 +167,11 @@ ZEND_METHOD(Closure, bind)
}
zend_string_release(class_name);
}
+ if(ce && ce != closure->func.common.scope && ce->type == ZEND_INTERNAL_CLASS) {
+ /* rebinding to internal class is not allowed */
+ zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s", ce->name->val);
+ return;
+ }
} else { /* scope argument not given; do not change the scope by default */
ce = closure->func.common.scope;
}