]> granicus.if.org Git - php/commitdiff
Forbid "fake" closure rebinding
authorDmitry Stogov <dmitry@zend.com>
Fri, 9 Oct 2015 16:41:15 +0000 (18:41 +0200)
committerNikita Popov <nikic@php.net>
Mon, 12 Oct 2015 18:34:08 +0000 (20:34 +0200)
Zend/tests/bug70630.phpt
Zend/zend_closures.c
Zend/zend_closures.h
ext/reflection/php_reflection.c

index fc79949ce2f9a2657d0584c7cca6b46ebbae6351..d78ee62c6adedb978ddc46d7ad48529bcea6d562 100644 (file)
@@ -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
index b1e21ed1e43f1c5eda3a827df69ada34dde99d7d..76b10e43d3bde2987ac17eab01b430bcd0edb683 100644 (file)
@@ -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
index 8d0963ec1799632ff802d5a703c9a443867369f7..8d4edfd37a4bdadbc272639762d2afe161e1f5f3 100644 (file)
@@ -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);
index 00731c70c39ecef268ff95e630cee94d2056bd80..a095120e184fcd84a1e992a39141c19df5051464 100644 (file)
@@ -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);
                }
        }
 }