From db7193f31ea9d176214fc36cde0503864a75ab0d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 31 Jan 2020 10:34:04 +0300 Subject: [PATCH] Fixed bug #79094 (Crashing when running recursion function) --- Zend/zend_execute.c | 33 +++++++++++++++++++++++++++++++++ Zend/zend_vm_def.h | 6 +++--- Zend/zend_vm_execute.h | 6 +++--- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index ab0d3656ee5..de00080b5a9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4452,6 +4452,39 @@ static zend_never_inline int ZEND_FASTCALL zend_quick_check_constant( return _zend_quick_get_constant(key, 0, 1 OPLINE_CC EXECUTE_DATA_CC); } /* }}} */ +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) +/* Special versions of functions that sets EX(opline) before calling zend_vm_stack_extend() */ +static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) /* {{{ */ +{ + zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top); + + ZEND_ASSERT_VM_STACK_GLOBAL; + + if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) { + EX(opline) = opline; /* this is the only difference */ + call = (zend_execute_data*)zend_vm_stack_extend(used_stack); + ZEND_ASSERT_VM_STACK_GLOBAL; + zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope); + return call; + } else { + EG(vm_stack_top) = (zval*)((char*)call + used_stack); + zend_vm_init_call_frame(call, call_info, func, num_args, object_or_called_scope); + return call; + } +} /* }}} */ + +static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) /* {{{ */ +{ + uint32_t used_stack = zend_vm_calc_used_stack(num_args, func); + + return _zend_vm_stack_push_call_frame_ex(used_stack, call_info, + func, num_args, object_or_called_scope); +} /* }}} */ +#else +# define _zend_vm_stack_push_call_frame_ex zend_vm_stack_push_call_frame_ex +# define _zend_vm_stack_push_call_frame zend_vm_stack_push_call_frame +#endif + #ifdef ZEND_VM_TRACE_HANDLERS # include "zend_vm_trace_handlers.h" #elif defined(ZEND_VM_TRACE_MAP) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 61242d6130c..1499b4b5ef4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3783,7 +3783,7 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT) } CACHE_PTR(opline->result.num, fbc); } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3946,7 +3946,7 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT) CACHE_PTR(opline->result.num, fbc); } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3976,7 +3976,7 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT) CACHE_PTR(opline->result.num, fbc); } - call = zend_vm_stack_push_call_frame_ex( + call = _zend_vm_stack_push_call_frame_ex( opline->op1.num, ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index da4efc5ffba..1e5f6455e3a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2897,7 +2897,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME } CACHE_PTR(opline->result.num, fbc); } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2984,7 +2984,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N CACHE_PTR(opline->result.num, fbc); } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3014,7 +3014,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CO CACHE_PTR(opline->result.num, fbc); } - call = zend_vm_stack_push_call_frame_ex( + call = _zend_vm_stack_push_call_frame_ex( opline->op1.num, ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call);