@@ -1776,7 +1776,7 @@ ZEND_FUNCTION(debug_print_backtrace)
1776
1776
1777
1777
ZEND_API void zend_fetch_debug_backtrace (zval * return_value , int skip_last , int options , int limit ) /* {{{ */
1778
1778
{
1779
- zend_execute_data * call ;
1779
+ zend_execute_data * call , * last_call = NULL ;
1780
1780
zend_object * object ;
1781
1781
bool fake_frame = 0 ;
1782
1782
int lineno , frameno = 0 ;
@@ -1821,6 +1821,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
1821
1821
1822
1822
if (skip_last ) {
1823
1823
/* skip debug_backtrace() */
1824
+ last_call = call ;
1824
1825
call = call -> prev_execute_data ;
1825
1826
}
1826
1827
@@ -1857,9 +1858,14 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
1857
1858
zval * arg = zend_get_zval_ptr (op_data , op_data -> op1_type , & op_data -> op1 , call );
1858
1859
if (Z_TYPE_P (arg ) == IS_UNDEF ) goto not_frameless_call ;
1859
1860
}
1861
+ zend_function * func = ZEND_FLF_FUNC (opline );
1862
+ /* Assume frameless functions are not recursive with themselves.
1863
+ * This condition may be true when observers are enabled. */
1864
+ if (last_call && last_call -> func == func ) {
1865
+ goto not_frameless_call ;
1866
+ }
1860
1867
stack_frame = zend_new_array (8 );
1861
1868
zend_hash_real_init_mixed (stack_frame );
1862
- zend_function * func = ZEND_FLF_FUNC (opline );
1863
1869
zend_string * name = func -> common .function_name ;
1864
1870
ZVAL_STRINGL (& tmp , ZSTR_VAL (name ), ZSTR_LEN (name ));
1865
1871
_zend_hash_append_ex (stack_frame , ZSTR_KNOWN (ZEND_STR_FUNCTION ), & tmp , 1 );
@@ -2068,6 +2074,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
2068
2074
} else {
2069
2075
fake_frame = 0 ;
2070
2076
include_filename = filename ;
2077
+ last_call = call ;
2071
2078
call = prev ;
2072
2079
}
2073
2080
}
0 commit comments