com php-src: Revert "Fixed bug #70630 (Closure::call/bind() crash with ReflectionFunction->getClosure())": NEWS Zend/tests/bug70630.phpt
Zend/tests/closure_061.phpt Zend/zend_closures. c Zend/zend_compile.c Zend/zend_compile.h

From: Date: Tue, 06 Oct 2015 20:59:36 +0000
Subject: com php-src: Revert "Fixed bug #70630 (Closure::call/bind() crash with ReflectionFunction->getClosure())": NEWS Zend/tests/bug70630.phpt
Zend/tests/closure_061.phpt Zend/zend_closures. c Zend/zend_compile.c Zend/zend_compile.h
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-89314@lists.php.net to get a copy of this message
Commit: e0b3b3c7524603d57dce62ae1cb1eae3b1bc3e42 Author: Dmitry Stogov <dmitry@zend.com> Tue, 6 Oct 2015 23:59:36 +0300 Parents: e193d35c1ed1307b06cc25c2b720d0141703798c Branches: PHP-7.0 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=e0b3b3c7524603d57dce62ae1cb1eae3b1bc3e42 Log: Revert "Fixed bug #70630 (Closure::call/bind() crash with ReflectionFunction->getClosure())" This reverts commit 517b5536259ecf7697f353f4bfbafde857fc1f81. Bugs: https://bugs.php.net/70630 Changed paths: M NEWS D Zend/tests/bug70630.phpt D Zend/tests/closure_061.phpt M Zend/zend_closures.c M Zend/zend_compile.c M Zend/zend_compile.h

diff --git a/NEWS b/NEWS index 9051f4d..d641ddd 100644 --- a/NEWS +++ b/NEWS @@ -2,10 +2,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 15 Oct 2015, PHP 7.0.0 RC 5 -- Core - . Fixed bug #70630 (Closure::call/bind() crash with - ReflectionFunction->getClosure()). (Bob) - - Mcrypt: . Fixed bug #70625 (mcrypt_encrypt() won't return data when no IV was specified under RC4). (Nikita) diff --git a/Zend/tests/bug70630.phpt b/Zend/tests/bug70630.phpt deleted file mode 100644 index 3dabca6..0000000 --- a/Zend/tests/bug70630.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Bug #70630 (Closure::call/bind() crash with ReflectionFunction->getClosure()) ---FILE-- -<?php - -class a {} -function foo() {} - -foreach (["substr", "foo"] as $fn) { - $x = (new ReflectionFunction($fn))->getClosure(); - $x->call(new a); - Closure::bind($x, new a, "a"); -} - -?> ---EXPECTF-- - -Warning: Cannot bind function substr to an object in %s on line %d - -Warning: Cannot bind function substr to an object in %s on line %d - -Warning: Cannot bind function foo to an object in %s on line %d - -Warning: Cannot bind function foo to an object in %s on line %d diff --git a/Zend/tests/closure_061.phpt b/Zend/tests/closure_061.phpt deleted file mode 100644 index a195956..0000000 --- a/Zend/tests/closure_061.phpt +++ /dev/null @@ -1,64 +0,0 @@ ---TEST-- -Closure::call() or Closure::bind() to independent class must fail ---FILE-- -<?php - -class foo { - public $var; - - function initClass() { - $this->var = __CLASS__; - } -} - -class bar { - public $var; - - function initClass() { - $this->var = __CLASS__; - } - - function getVar() { - assert($this->var !== null); // ensure initClass was called - return $this->var; - } -} - -class baz extends bar { - public $var; - - function initClass() { - $this->var = __CLASS__; - } -} - -function callMethodOn($class, $method, $object) { - $closure = (new ReflectionMethod($class, $method))->getClosure((new ReflectionClass($class))->newInstanceWithoutConstructor()); - $closure = $closure->bindTo($object, $class); - return $closure(); -} - -$baz = new baz; - -callMethodOn("baz", "initClass", $baz); -var_dump($baz->getVar()); - -callMethodOn("bar", "initClass", $baz); -var_dump($baz->getVar()); - -callMethodOn("foo", "initClass", $baz); -var_dump($baz->getVar()); - -?> ---EXPECTF-- -string(3) "baz" -string(3) "bar" - -Warning: Cannot bind function foo::initClass to object of class baz in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d -Stack trace: -#0 %s(%d): initClass() -#1 %s(%d): callMethodOn('foo', 'initClass', Object(baz)) -#2 {main} - thrown in %s on line %d diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 8de7b6e..50aa7d4 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -94,12 +94,10 @@ ZEND_METHOD(Closure, call) return; } - if (closure->func.type != ZEND_USER_FUNCTION || (closure->func.common.fn_flags & ZEND_ACC_REAL_CLOSURE) == 0) { - /* verify that we aren't binding methods to a wrong object */ - if (closure->func.common.scope == NULL) { - zend_error(E_WARNING, "Cannot bind function %s to an object", ZSTR_VAL(closure->func.common.function_name)); - return; - } else if (!instanceof_function(Z_OBJCE_P(newthis), closure->func.common.scope)) { + if (closure->func.type == ZEND_INTERNAL_FUNCTION) { + /* verify that we aren't binding internal function to a wrong object */ + if ((closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0 && + !instanceof_function(Z_OBJCE_P(newthis), closure->func.common.scope)) { zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", ZSTR_VAL(closure->func.common.scope->name), ZSTR_VAL(closure->func.common.function_name), ZSTR_VAL(Z_OBJCE_P(newthis)->name)); return; } @@ -167,7 +165,7 @@ ZEND_METHOD(Closure, bind) RETURN_NULL(); } - closure = (zend_closure *) Z_OBJ_P(zclosure); + closure = (zend_closure *)Z_OBJ_P(zclosure); if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); @@ -189,7 +187,7 @@ ZEND_METHOD(Closure, bind) } zend_string_release(class_name); } - if (ce && ce != closure->func.common.scope && ce->type == ZEND_INTERNAL_CLASS) { + 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", ZSTR_VAL(ce->name)); return; @@ -204,22 +202,6 @@ ZEND_METHOD(Closure, bind) called_scope = ce; } - /* verify that we aren't binding methods to a wrong object */ - if (closure->func.type != ZEND_USER_FUNCTION || (closure->func.common.fn_flags & ZEND_ACC_REAL_CLOSURE) == 0) { - if (!closure->func.common.scope) { - if (ce) { - zend_error(E_WARNING, "Cannot bind function %s to an object", ZSTR_VAL(closure->func.common.function_name)); - return; - } - } else if (!ce) { - zend_error(E_WARNING, "Cannot bind function %s::%s to no class", ZSTR_VAL(closure->func.common.scope->name), ZSTR_VAL(closure->func.common.function_name)); - return; - } else if (!instanceof_function(ce, closure->func.common.scope)) { - zend_error(E_WARNING, "Cannot bind function %s::%s to class %s", ZSTR_VAL(closure->func.common.scope->name), ZSTR_VAL(closure->func.common.function_name), ZSTR_VAL(ce->name)); - return; - } - } - zend_create_closure(return_value, &closure->func, ce, called_scope, newthis); new_closure = (zend_closure *) Z_OBJ_P(return_value); @@ -260,9 +242,11 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* { * and we won't check arguments on internal function. We also set * ZEND_ACC_USER_ARG_INFO flag to prevent invalid usage by Reflection */ invoke->type = ZEND_INTERNAL_FUNCTION; - invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & keep_flags); + invoke->internal_function.fn_flags = + ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & keep_flags); if (closure->func.type != ZEND_INTERNAL_FUNCTION || (closure->func.common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { - invoke->internal_function.fn_flags |= ZEND_ACC_USER_ARG_INFO; + invoke->internal_function.fn_flags |= + ZEND_ACC_USER_ARG_INFO; } invoke->internal_function.handler = ZEND_MN(Closure___invoke); invoke->internal_function.module = 0; @@ -539,10 +523,10 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent object_init_ex(res, zend_ce_closure); - closure = (zend_closure *) Z_OBJ_P(res); + closure = (zend_closure *)Z_OBJ_P(res); memcpy(&closure->func, func, func->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function)); - closure->func.common.prototype = (zend_function *) closure; + closure->func.common.prototype = (zend_function*)closure; closure->func.common.fn_flags |= ZEND_ACC_CLOSURE; if ((scope == NULL) && this_ptr && (Z_TYPE_P(this_ptr) != IS_UNDEF)) { @@ -566,8 +550,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent if (closure->func.op_array.refcount) { (*closure->func.op_array.refcount)++; } - } - if (closure->func.type != ZEND_USER_FUNCTION || (func->common.fn_flags & ZEND_ACC_REAL_CLOSURE) == 0) { + } else { /* verify that we aren't binding internal function to a wrong scope */ if(func->common.scope != NULL) { if(scope && !instanceof_function(scope, func->common.scope)) { @@ -578,6 +561,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent !instanceof_function(Z_OBJCE_P(this_ptr), closure->func.common.scope)) { zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name), ZSTR_VAL(Z_OBJCE_P(this_ptr)->name)); scope = NULL; + this_ptr = NULL; } } else { /* if it's a free function, we won't set scope & this since they're meaningless */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d30db31..98af0a7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4854,7 +4854,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */ op_array->doc_comment = zend_string_copy(decl->doc_comment); } if (decl->kind == ZEND_AST_CLOSURE) { - op_array->fn_flags |= ZEND_ACC_CLOSURE | ZEND_ACC_REAL_CLOSURE; + op_array->fn_flags |= ZEND_ACC_CLOSURE; } if (is_method) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8653407..68cc39a 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -238,7 +238,7 @@ typedef struct _zend_try_catch_element { /* user class has methods with static variables */ #define ZEND_HAS_STATIC_IN_METHODS 0x800000 -#define ZEND_ACC_REAL_CLOSURE 0x40 + #define ZEND_ACC_CLOSURE 0x100000 #define ZEND_ACC_GENERATOR 0x800000
« previous php.cvs (#89314) next »