]> granicus.if.org Git - php/commitdiff
Fixed bug #74164 (PHP hangs when an invalid value is dynamically passed to typehinted...
authorXinchen Hui <laruence@gmail.com>
Sat, 25 Feb 2017 04:00:42 +0000 (12:00 +0800)
committerXinchen Hui <laruence@gmail.com>
Sat, 25 Feb 2017 04:00:42 +0000 (12:00 +0800)
NEWS
Zend/tests/bug74164.phpt [new file with mode: 0644]
Zend/zend_execute_API.c

diff --git a/NEWS b/NEWS
index a2129d97246b134b5fa0ad24d23f38a48cd52a30..e5b94aa9b4b48ae5c401ad19bd2e97d2d056ce2e 100644 (file)
--- 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 (file)
index 0000000..354b2f5
--- /dev/null
@@ -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
index e02198526fcf8c412c43238335830fd86ef0b648..9080ae59a03e42a8444053e7f53a68cec3c59516 100644 (file)
@@ -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 {