com php-src: Fixed bug #74164 (PHP hangs when an invalid value is dynamically passed to typehinted by-ref arg): NEWS Zend/tests/bug74164.phpt
Zend/zend_execute_API.c
| From: | Xinchen Hui | Date: | Sat, 25 Feb 2017 04:00:42 +0000 |
| Subject: | com php-src: Fixed bug #74164 (PHP hangs when an invalid value is dynamically passed to typehinted by-ref arg): NEWS Zend/tests/bug74164.phpt Zend/zend_execute_API.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-97176@lists.php.net to get a copy of this message | ||
Commit: 36fcc4cb5d92dabc8c8f6f0587c81093bcac878c
Author: Xinchen Hui <laruence@gmail.com> Sat, 25 Feb 2017 12:00:42 +0800
Parents: d1f36d6d8ebd76b2d1014a1fcccdf75baa70cdb0
Branches: PHP-7.1 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=36fcc4cb5d92dabc8c8f6f0587c81093bcac878c
Log:
Fixed bug #74164 (PHP hangs when an invalid value is dynamically passed to typehinted by-ref arg)
Bugs:
https://bugs.php.net/74164
Changed paths:
M NEWS
A Zend/tests/bug74164.phpt
M Zend/zend_execute_API.c
Diff:
diff --git a/NEWS b/NEWS
index a2129d9..e5b94aa 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PHP NEWS
?? ??? 2017, PHP 7.1.3
- Core:
+ . Fixed bug #74164 (PHP hangs when an invalid value is dynamically passed to
+ typehinted by-ref arg). (Laruence)
. Fixed bug #74093 (Maximum execution time of n+2 seconds exceed not written
in error_log). (Laruence)
. Fixed bug #73989 (PHP 7.1 Segfaults within Symfony test suite).
diff --git a/Zend/tests/bug74164.phpt b/Zend/tests/bug74164.phpt
new file mode 100644
index 0000000..354b2f5
--- /dev/null
+++ b/Zend/tests/bug74164.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #74164 (PHP hangs when an invalid value is dynamically passed to typehinted by-ref arg)
+--FILE--
+<?php
+
+namespace Foo;
+
+set_error_handler(function ($type, $msg) {
+ throw new \Exception($msg);
+});
+
+call_user_func(function (array &$ref) {var_dump("xxx");},
'not_an_array_variable');
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception: Parameter 1 to Foo\{closure}() expected to be a reference, value
given in %sbug74164.php:%d
+Stack trace:
+#0 [internal function]: Foo\{closure}(%s)
+#1 %sbug74164.php(%d): call_user_func(%s)
+#2 {main}
+ thrown in %sbug74164.php on line %d
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index e021985..9080ae5 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -761,6 +761,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
if (fci->object &&
(!EG(objects_store).object_buckets ||
!IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) {
+ zend_vm_stack_free_call_frame(call);
if (EG(current_execute_data) == &dummy_execute_data) {
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
}
@@ -770,6 +771,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_error(NULL, "Cannot call abstract method %s::%s()",
ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
+ zend_vm_stack_free_call_frame(call);
if (EG(current_execute_data) == &dummy_execute_data) {
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
}
@@ -780,6 +782,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
/
func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
func->common.scope ? "::" : "",
ZSTR_VAL(func->common.function_name));
+ if (UNEXPECTED(EG(exception))) {
+ zend_vm_stack_free_call_frame(call);
+ if (EG(current_execute_data) == &dummy_execute_data) {
+ EG(current_execute_data) = dummy_execute_data.prev_execute_data;
+ }
+ return FAILURE;
+ }
}
}
@@ -800,6 +809,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
/
func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
func->common.scope ? "::" : "",
ZSTR_VAL(func->common.function_name));
+ if (UNEXPECTED(EG(exception))) {
+ ZEND_CALL_NUM_ARGS(call) = i;
+ zend_vm_stack_free_args(call);
+ zend_vm_stack_free_call_frame(call);
+ if (EG(current_execute_data) == &dummy_execute_data) {
+ EG(current_execute_data) = dummy_execute_data.prev_execute_data;
+ }
+ return FAILURE;
+ }
}
}
} else {