summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2020-01-31 10:34:04 +0300
committerDmitry Stogov <dmitry@zend.com>2020-01-31 10:34:04 +0300
commitdb7193f31ea9d176214fc36cde0503864a75ab0d (patch)
tree532ec17827a090bdd514808e3b394c08febd253d
parentf0f5c415a6e0abc40514f97113deb52a343174ee (diff)
downloadphp-git-db7193f31ea9d176214fc36cde0503864a75ab0d.tar.gz
Fixed bug #79094 (Crashing when running recursion function)
-rw-r--r--Zend/zend_execute.c33
-rw-r--r--Zend/zend_vm_def.h6
-rw-r--r--Zend/zend_vm_execute.h6
3 files changed, 39 insertions, 6 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index ab0d3656ee..de00080b5a 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 61242d6130..1499b4b5ef 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 da4efc5ffb..1e5f6455e3 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);