]> granicus.if.org Git - php/commitdiff
Fixed bug #72101 (crash on complex code)
authorDmitry Stogov <dmitry@zend.com>
Mon, 25 Apr 2016 11:11:46 +0000 (14:11 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 25 Apr 2016 11:11:46 +0000 (14:11 +0300)
NEWS
Zend/tests/bug72101.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index cda406f8450867b775f3ee60534aebca034c6125..9330bce21170c690cbce5f467e8f40f89dfafb0b 100644 (file)
--- 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 (file)
index 0000000..ed70b96
--- /dev/null
@@ -0,0 +1,85 @@
+--TEST--
+Bug #72101 (crash on complex code)
+--FILE--
+<?php
+class PHPUnit_Framework_MockObject_Stub_ReturnCallback {
+    protected $callback;
+    public function __construct($callback) {
+        $this->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
index 687493f37b8bca2b769106f0d96a8e9bd700081e..5471356f5c0dec873356304b50fb05e49f827887 100644 (file)
@@ -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();
index 2746c4000cee08c939cb4fc4d42a91a1f7fea230..ba50ccd844e4440e57330f142d9275aaf096e538 100644 (file)
@@ -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();
                        }