]> granicus.if.org Git - php/commitdiff
Skip dummy frames allocated on CPU stack of zend_call_function().
authorDmitry Stogov <dmitry@zend.com>
Tue, 26 Jan 2021 15:41:26 +0000 (18:41 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 26 Jan 2021 15:41:26 +0000 (18:41 +0300)
(Usage of "current_observed_frame" varible looks unsafe to me).

Zend/zend_observer.c
ext/zend_test/tests/observer_error_05.phpt [new file with mode: 0644]

index a8ce1eb5c057faa86c23e7ee44e48d4f379f1ed6..a60428ee04fa1f7a7c93b8cb11e30007e7366a3e 100644 (file)
@@ -220,7 +220,11 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_end(
                first_observed_frame = NULL;
                current_observed_frame = NULL;
        } else {
-               current_observed_frame = execute_data->prev_execute_data;
+               zend_execute_data *ex = execute_data->prev_execute_data;
+               while (ex && !ex->func) {
+                       ex = ex->prev_execute_data;
+               }
+               current_observed_frame = ex;
        }
 }
 
@@ -228,7 +232,7 @@ ZEND_API void zend_observer_fcall_end_all(void)
 {
        zend_execute_data *ex = current_observed_frame;
        while (ex != NULL) {
-               if (ex->func->type != ZEND_INTERNAL_FUNCTION) {
+               if (ex->func && ex->func->type != ZEND_INTERNAL_FUNCTION) {
                        zend_observer_fcall_end(ex, NULL);
                }
                ex = ex->prev_execute_data;
diff --git a/ext/zend_test/tests/observer_error_05.phpt b/ext/zend_test/tests/observer_error_05.phpt
new file mode 100644 (file)
index 0000000..d3e5f67
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+Observer: End handlers fire after a userland fatal error
+--SKIPIF--
+<?php if (!extension_loaded('zend-test')) die('skip: zend-test extension required'); ?>
+--INI--
+zend_test.observer.enabled=1
+zend_test.observer.observe_all=1
+zend_test.observer.show_return_value=1
+--FILE--
+<?php
+set_error_handler(function ($errno, $errstr, $errfile, $errline) {
+    trigger_error('Foo error', E_USER_ERROR);
+});
+
+function foo()
+{
+       return $x; // warning
+}
+
+foo();
+
+echo 'You should not see this.';
+?>
+--EXPECTF--
+<!-- init '%s%eobserver_error_%d.php' -->
+<file '%s%eobserver_error_%d.php'>
+  <!-- init foo() -->
+  <foo>
+    <!-- init {closure}() -->
+    <{closure}>
+
+Fatal error: Foo error in %s on line %d
+    </{closure}:NULL>
+  </foo:NULL>
+</file '%s%eobserver_error_%d.php'>