From: Dmitry Stogov Date: Mon, 25 Apr 2016 11:11:46 +0000 (+0300) Subject: Fixed bug #72101 (crash on complex code) X-Git-Tag: php-7.0.7RC1~75 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=92233dd736a883c34d5769081a9c0ff6d9f264f7;p=php Fixed bug #72101 (crash on complex code) --- diff --git a/NEWS b/NEWS index cda406f845..9330bce211 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ PHP NEWS ?? ??? 2016 PHP 7.0.7 - Core: + . Fixed bug #72101 (crash on complex code). (Dmitry) . Fixed bug #72057 (PHP Hangs when using custom error handler and typehint). (Nikita Nefedov) . Fixed bug #72038 (Function calls with values to a by-ref parameter don't diff --git a/Zend/tests/bug72101.phpt b/Zend/tests/bug72101.phpt new file mode 100644 index 0000000000..ed70b962d7 --- /dev/null +++ b/Zend/tests/bug72101.phpt @@ -0,0 +1,85 @@ +--TEST-- +Bug #72101 (crash on complex code) +--FILE-- +callback = $callback; + } + public function invoke($invocation) { + return call_user_func_array($this->callback, $invocation->parameters); + } +} + +class PHPUnit_Framework_MockObject_InvocationMocker { + protected $matchers = []; + public function addMatcher( $matcher) { + $this->matchers[] = $matcher; + } + public function invoke( $invocation) { + foreach ($this->matchers as $match) { + $match->invoked($invocation); + } + } +} + +class PHPUnit_Framework_MockObject_Matcher { + public $stub = null; + public function invoked($invocation) { + return $this->stub->invoke($invocation); + } +} + +class MethodCallbackByReference { + public function bar(&$a, &$b, $c) { + Legacy::bar($a, $b, $c); + } + public function callback(&$a, &$b, $c) { + $b = 1; + } +} +class PHPUnit_Framework_MockObject_Invocation_Static { + public $parameters; + public function __construct(array $parameters) { + $this->parameters = $parameters; + } +} + +class Mock_MethodCallbackByReference_7b180d26 extends MethodCallbackByReference { + public $inv_mocker; + public function bar(&$a, &$b, $c) { + $arguments = array($a, $b, $c); + $result = $this->inv_mocker->invoke( + new PHPUnit_Framework_MockObject_Invocation_Static( + $arguments + ) + ); + return $result; + } +} + +set_error_handler(function() { +// var_dump(func_get_args()); + DoesNotExists::$nope = true; +}, E_ALL | E_STRICT); + +$foo = new Mock_MethodCallbackByReference_7b180d26(); +$InvMocker = new PHPUnit_Framework_MockObject_InvocationMocker(); +$foo->inv_mocker = $InvMocker; +$OuterMatcher = new PHPUnit_Framework_MockObject_Matcher(); +$InvMocker->addMatcher($OuterMatcher); +$OuterMatcher->methodNameMatcher = null; +$OuterMatcher->stub = new PHPUnit_Framework_MockObject_Stub_ReturnCallback([$foo, 'callback']); +$a = $b = $c = 0; +$foo->bar($a, $b, $c); +--EXPECTF-- +Fatal error: Uncaught Error: Class 'DoesNotExists' not found in %sbug72101.php:61 +Stack trace: +#0 %sbug72101.php(8): {closure}(2, 'Parameter 1 to ...', '%s', 8, Array) +#1 %s/bug72101.php(27): PHPUnit_Framework_MockObject_Stub_ReturnCallback->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) +#2 %sbug72101.php(19): PHPUnit_Framework_MockObject_Matcher->invoked(Object(PHPUnit_Framework_MockObject_Invocation_Static)) +#3 %sbug72101.php(51): PHPUnit_Framework_MockObject_InvocationMocker->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) +#4 %sbug72101.php(72): Mock_MethodCallbackByReference_7b180d26->bar(0, 0, 0) +#5 {main} + thrown in %sbug72101.php on line 61 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 687493f37b..5471356f5c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4591,6 +4591,7 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY) EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; Z_OBJ(EX(call)->This) = NULL; + ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); } else { uint32_t arg_num; HashTable *ht; @@ -4622,7 +4623,7 @@ ZEND_VM_C_LABEL(send_array): EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; Z_OBJ(EX(call)->This) = NULL; - + ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); break; } } @@ -4673,6 +4674,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY) EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; Z_OBJ(EX(call)->This) = NULL; + ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2746c4000c..ba50ccd844 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1123,6 +1123,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; Z_OBJ(EX(call)->This) = NULL; + ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); } else { uint32_t arg_num; HashTable *ht; @@ -1154,7 +1155,7 @@ send_array: EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; Z_OBJ(EX(call)->This) = NULL; - + ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); break; } } @@ -15349,6 +15350,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; Z_OBJ(EX(call)->This) = NULL; + ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); zval_ptr_dtor_nogc(free_op1); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -28956,6 +28958,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND EX(call)->func = (zend_function*)&zend_pass_function; EX(call)->called_scope = NULL; Z_OBJ(EX(call)->This) = NULL; + ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); }