diff options
author | Dmitry Stogov <dmitry@zend.com> | 2021-01-26 18:41:26 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2021-01-26 18:41:26 +0300 |
commit | 094e1a8b2def767b41d2defaf7cb86681126f9da (patch) | |
tree | 8d338f56b224307884f68d3bd79e8b0efa87c664 | |
parent | a2dcd44272dccaab22a13d587a13c4c60972063b (diff) | |
download | php-git-094e1a8b2def767b41d2defaf7cb86681126f9da.tar.gz |
Skip dummy frames allocated on CPU stack of zend_call_function().
(Usage of "current_observed_frame" varible looks unsafe to me).
-rw-r--r-- | Zend/zend_observer.c | 8 | ||||
-rw-r--r-- | ext/zend_test/tests/observer_error_05.phpt | 35 |
2 files changed, 41 insertions, 2 deletions
diff --git a/Zend/zend_observer.c b/Zend/zend_observer.c index a8ce1eb5c0..a60428ee04 100644 --- a/Zend/zend_observer.c +++ b/Zend/zend_observer.c @@ -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 index 0000000000..d3e5f67a4e --- /dev/null +++ b/ext/zend_test/tests/observer_error_05.phpt @@ -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'> |