diff --git a/Zend/tests/stack_limit/gh16041_001.phpt b/Zend/tests/stack_limit/gh16041_001.phpt new file mode 100644 index 0000000000000..4d3e41a54dcdb --- /dev/null +++ b/Zend/tests/stack_limit/gh16041_001.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-16041 001: Stack overflow in phpdbg +--SKIPIF-- + +--INI-- +zend.max_allowed_stack_size=512K +--PHPDBG-- +set pagination off +run +continue +quit +--FILE-- + +--EXPECTF-- +[Successful compilation of %sgh16041_001.php] +prompt> prompt> [Uncaught Error in %s on line %d: Maximum call stack size of %d bytes%s +>00005: new Canary(); + 00006: } + 00007: } +prompt> [Uncaught Error in %s on line %d] +Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? in %s:%d +Stack trace: +#0 %s(%d): Canary->__destruct() +%a +prompt> diff --git a/Zend/tests/stack_limit/gh16041_002.phpt b/Zend/tests/stack_limit/gh16041_002.phpt new file mode 100644 index 0000000000000..6d389d208af4a --- /dev/null +++ b/Zend/tests/stack_limit/gh16041_002.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-16041 002: Stack overflow in phpdbg +--SKIPIF-- + +--INI-- +zend.max_allowed_stack_size=512K +--PHPDBG-- +set pagination off +run +quit +--FILE-- +getMessage()); +} + +?> +--EXPECTF-- +[Successful compilation of %sgh16041_002.php] +prompt> prompt> Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? +[Script ended normally] +prompt> diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index a0eacb14dcf4c..dbc60cae347f1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2500,7 +2500,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_s } #ifdef ZEND_CHECK_STACK_LIMIT -static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_call_stack_size_error(void) +zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_call_stack_size_error(void) { size_t max_stack_size = 0; if ((uintptr_t) EG(stack_base) > (uintptr_t) EG(stack_limit)) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 3f59e2b371a13..2057807278711 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -66,6 +66,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void); ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim); +zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_call_stack_size_error(void); ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 2314068044fb8..50dcfebd41885 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -1652,6 +1652,15 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */ PHPDBG_G(in_execution) = 1; +#ifdef ZEND_CHECK_STACK_LIMIT + if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) { + zend_call_stack_size_error(); + /* No opline was executed before exception */ + EG(opline_before_exception) = NULL; + /* Fall through to handle exception below. */ + } +#endif /* ZEND_CHECK_STACK_LIMIT */ + while (1) { zend_object *exception = EG(exception);