summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-10-09 18:41:15 +0200
committerNikita Popov <nikic@php.net>2015-10-12 20:34:08 +0200
commit23b372d358577c8146e4c35e936413e5a43043d9 (patch)
treee932502c6718d85a991e56b66ce5bf7ddea3f0df
parentdcbbf7c38d45fd06752b7298ed765733ca2f8d41 (diff)
downloadphp-git-23b372d358577c8146e4c35e936413e5a43043d9.tar.gz
Forbid "fake" closure rebinding
-rw-r--r--Zend/tests/bug70630.phpt2
-rw-r--r--Zend/zend_closures.c21
-rw-r--r--Zend/zend_closures.h1
-rw-r--r--ext/reflection/php_reflection.c6
4 files changed, 21 insertions, 9 deletions
diff --git a/Zend/tests/bug70630.phpt b/Zend/tests/bug70630.phpt
index fc79949ce2..d78ee62c6a 100644
--- a/Zend/tests/bug70630.phpt
+++ b/Zend/tests/bug70630.phpt
@@ -7,4 +7,4 @@ $x = (new ReflectionFunction("substr"))->getClosure();
$x->call(new a);
?>
--EXPECTF--
-Warning: a::substr() expects at least 2 parameters, 0 given in %s on line %d
+Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index b1e21ed1e4..76b10e43d3 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -34,6 +34,9 @@
#define ZEND_CLOSURE_PROPERTY_ERROR() \
zend_throw_error(NULL, "Closure object cannot have properties")
+/* reuse bit to mark "fake" closures (it wasn't used for functions before) */
+#define ZEND_ACC_FAKE_CLOSURE ZEND_ACC_INTERFACE
+
typedef struct _zend_closure {
zend_object std;
zend_function func;
@@ -102,11 +105,8 @@ static zend_bool zend_valid_closure_binding(
return 0;
}
- if (func->type == ZEND_INTERNAL_FUNCTION && scope && func->common.scope &&
- !instanceof_function(scope, func->common.scope)) {
- zend_error(E_WARNING, "Cannot bind function %s::%s to scope class %s",
- ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name),
- ZSTR_VAL(scope->name));
+ if ((func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) && scope != func->common.scope) {
+ zend_error(E_WARNING, "Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()");
return 0;
}
@@ -617,6 +617,17 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
}
/* }}} */
+ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr) /* {{{ */
+{
+ zend_closure *closure;
+
+ zend_create_closure(res, func, scope, called_scope, this_ptr);
+
+ closure = (zend_closure *)Z_OBJ_P(res);
+ closure->func.common.fn_flags |= ZEND_ACC_FAKE_CLOSURE;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h
index 8d0963ec17..8d4edfd37a 100644
--- a/Zend/zend_closures.h
+++ b/Zend/zend_closures.h
@@ -29,6 +29,7 @@ void zend_register_closure_ce(void);
extern ZEND_API zend_class_entry *zend_ce_closure;
ZEND_API void zend_create_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr);
+ZEND_API void zend_create_fake_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr);
ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *obj);
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj);
ZEND_API zval* zend_get_closure_this_ptr(zval *obj);
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 00731c70c3..a095120e18 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -1762,7 +1762,7 @@ ZEND_METHOD(reflection_function, getClosure)
}
GET_REFLECTION_OBJECT_PTR(fptr);
- zend_create_closure(return_value, fptr, NULL, NULL, NULL);
+ zend_create_fake_closure(return_value, fptr, NULL, NULL, NULL);
}
/* }}} */
@@ -3144,7 +3144,7 @@ ZEND_METHOD(reflection_method, getClosure)
GET_REFLECTION_OBJECT_PTR(mptr);
if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
- zend_create_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL);
+ zend_create_fake_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL);
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
return;
@@ -3161,7 +3161,7 @@ ZEND_METHOD(reflection_method, getClosure)
{
ZVAL_COPY(return_value, obj);
} else {
- zend_create_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
+ zend_create_fake_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
}
}
}