From 50f3e1e552563a9569675953b2cbda2c40d67fbd Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sun, 11 Jun 2023 14:29:19 +0200 Subject: [PATCH 1/2] Add stack limit check in zend_eval_const_expr() --- Zend/tests/stack_limit/stack_limit_013.phpt | 120 ++++++++++++++++++++ Zend/zend_compile.c | 8 ++ 2 files changed, 128 insertions(+) create mode 100644 Zend/tests/stack_limit/stack_limit_013.phpt diff --git a/Zend/tests/stack_limit/stack_limit_013.phpt b/Zend/tests/stack_limit/stack_limit_013.phpt new file mode 100644 index 000000000000..c323fe4c31d1 --- /dev/null +++ b/Zend/tests/stack_limit/stack_limit_013.phpt @@ -0,0 +1,120 @@ +--TEST-- +Stack limit 013 - Internal stack limit check in zend_eval_const_expr() +--SKIPIF-- + +--EXTENSIONS-- +zend_test +--INI-- +zend.max_allowed_stack_size=64K +--FILE-- +kind) { case ZEND_AST_BINARY_OP: zend_eval_const_expr(&ast->child[0]); From 2f3a3ffd0e21f964055151eaae4c5053f53fec8b Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 27 Jun 2023 14:09:26 +0200 Subject: [PATCH 2/2] Fatal error --- Zend/zend_compile.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2dc3e7b25a02..9001302c5368 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -99,6 +99,26 @@ static void zend_compile_expr(znode *result, zend_ast *ast); static void zend_compile_stmt(zend_ast *ast); static void zend_compile_assign(znode *result, zend_ast *ast); +#ifdef ZEND_CHECK_STACK_LIMIT +zend_never_inline static void zend_stack_limit_error(void) +{ + zend_error_noreturn(E_COMPILE_ERROR, + "Maximum call stack size of %zu bytes reached during compilation. Try splitting expression", + (size_t) ((uintptr_t) EG(stack_base) - (uintptr_t) EG(stack_limit))); +} + +static void zend_check_stack_limit(void) +{ + if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) { + zend_stack_limit_error(); + } +} +#else /* ZEND_CHECK_STACK_LIMIT */ +static void zend_check_stack_limit(void) +{ +} +#endif /* ZEND_CHECK_STACK_LIMIT */ + static void init_op(zend_op *op) { MAKE_NOP(op); @@ -10512,13 +10532,7 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */ static void zend_compile_expr(znode *result, zend_ast *ast) { -#ifdef ZEND_CHECK_STACK_LIMIT - if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) { - zend_error_noreturn(E_COMPILE_ERROR, - "Maximum call stack size of %zu bytes reached during compilation. Try splitting expression", - (size_t) ((uintptr_t) EG(stack_base) - (uintptr_t) EG(stack_limit))); - } -#endif /* ZEND_CHECK_STACK_LIMIT */ + zend_check_stack_limit(); uint32_t checkpoint = zend_short_circuiting_checkpoint(); zend_compile_expr_inner(result, ast); @@ -10604,13 +10618,7 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ return; } -#ifdef ZEND_CHECK_STACK_LIMIT - if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) { - /* Abort evaluation due to stack usage. Note that compiling this - * expression is likely to also fail. */ - return; - } -#endif /* ZEND_CHECK_STACK_LIMIT */ + zend_check_stack_limit(); switch (ast->kind) { case ZEND_AST_BINARY_OP: