From: Bram Moolenaar Date: Mon, 24 Jan 2022 18:16:12 +0000 Subject: [PATCH] patch 8.2.4206: condition with many "(" causes a crash Problem: Condition with many "(" causes a crash. Solution: Limit recursion to 1000. --- src/eval.c | 12 ++++++++++++ src/globals.h | 2 ++ src/testdir/test_eval_stuff.vim | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/src/eval.c b/src/eval.c index 3b563f7..95dda90 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2495,6 +2495,7 @@ eval7( char_u *start_leader, *end_leader; int ret = OK; char_u *alias; + static int recurse = 0; /* * Initialise variable so that clear_tv() can't mistake this for a @@ -2521,6 +2522,15 @@ eval7( return FAIL; } + // Limit recursion to 1000 levels. At least at 10000 we run out of stack + // and crash. + if (recurse == 1000) + { + semsg(_(e_expression_too_recursive_str), *arg); + return FAIL; + } + ++recurse; + switch (**arg) { /* @@ -2761,6 +2771,8 @@ eval7( */ if (ret == OK && evaluate && end_leader > start_leader) ret = eval7_leader(rettv, start_leader, &end_leader); + + --recurse; return ret; } diff --git a/src/globals.h b/src/globals.h index 75092b7..659bad6 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1464,6 +1464,8 @@ EXTERN char e_endwhile[] INIT(= N_("E170: Missing :endwhile")); EXTERN char e_endfor[] INIT(= N_("E170: Missing :endfor")); EXTERN char e_while[] INIT(= N_("E588: :endwhile without :while")); EXTERN char e_for[] INIT(= N_("E588: :endfor without :for")); +EXTERN char e_expression_too_recursive_str[] + INIT(= N_("E1169: Expression too recursive: %s")); #endif EXTERN char e_exists[] INIT(= N_("E13: File exists (add ! to override)")); EXTERN char e_failed[] INIT(= N_("E472: Command failed")); diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim index ec566da..32a5411 100644 --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -216,3 +216,8 @@ func Test_scriptversion_fail() call assert_fails('source Xversionscript', 'E999:') call delete('Xversionscript') endfunc + +func Test_deep_recursion() + " this was running out of stack + call assert_fails("exe 'if ' .. repeat('(', 1002)", 'E1169: Expression too recursive: ((') +endfunc -- 1.8.3.1