]> granicus.if.org Git - vim/commitdiff
patch 8.2.4206: condition with many "(" causes a crash v8.2.4206
authorBram Moolenaar <Bram@vim.org>
Mon, 24 Jan 2022 18:16:12 +0000 (18:16 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 24 Jan 2022 18:16:12 +0000 (18:16 +0000)
Problem:    Condition with many "(" causes a crash.
Solution:   Limit recursion to 1000.

src/errors.h
src/eval.c
src/testdir/test_eval_stuff.vim
src/version.c

index e632d5b240fc6a0041407f236a06c069e6525d21..d89c27c22bdc1141f1577e2ad7e87ac0c552d172 100644 (file)
@@ -2718,6 +2718,8 @@ EXTERN char e_invalid_command_after_export[]
        INIT(= N_("E1043: Invalid command after :export"));
 EXTERN char e_export_with_invalid_argument[]
        INIT(= N_("E1044: Export with invalid argument"));
+// E1045 not used
+// E1046 not used
 EXTERN char e_syntax_error_in_import_str[]
        INIT(= N_("E1047: Syntax error in import: %s"));
 EXTERN char e_item_not_found_in_script_str[]
@@ -2786,6 +2788,7 @@ EXTERN char e_missing_argument_type_for_str[]
 // E1080 unused
 EXTERN char e_cannot_unlet_str[]
        INIT(= N_("E1081: Cannot unlet %s"));
+// E1082 unused
 EXTERN char e_missing_backtick[]
        INIT(= N_("E1083: Missing backtick"));
 EXTERN char e_cannot_delete_vim9_script_function_str[]
@@ -2906,6 +2909,7 @@ EXTERN char e_for_argument_must_be_sequence_of_lists[]
        INIT(= N_("E1140: :for argument must be a sequence of lists"));
 EXTERN char e_indexable_type_required[]
        INIT(= N_("E1141: Indexable type required"));
+// E1142 unused
 EXTERN char e_empty_expression_str[]
        INIT(= N_("E1143: Empty expression: \"%s\""));
 EXTERN char e_command_str_not_followed_by_white_space_str[]
@@ -2966,7 +2970,8 @@ EXTERN char e_argument_name_shadows_existing_variable_str[]
        INIT(= N_("E1167: Argument name shadows existing variable: %s"));
 EXTERN char e_argument_already_declared_in_script_str[]
        INIT(= N_("E1168: Argument already declared in the script: %s"));
-// E1169 unused
+EXTERN char e_expression_too_recursive_str[]
+       INIT(= N_("E1169: Expression too recursive: %s"));
 EXTERN char e_cannot_use_hash_curly_to_start_comment[]
        INIT(= N_("E1170: Cannot use #{ to start a comment"));
 EXTERN char e_missing_end_block[]
index 2ca3377492e6817204d9df487e45b73ca6fcae2c..d42e1f8266ac0aa0b845bd39cbae9587c3cbe007 100644 (file)
@@ -3526,6 +3526,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
@@ -3552,6 +3553,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)
     {
     /*
@@ -3781,6 +3791,8 @@ eval7(
      */
     if (ret == OK && evaluate && end_leader > start_leader)
        ret = eval7_leader(rettv, FALSE, start_leader, &end_leader);
+
+    --recurse;
     return ret;
 }
 
index ff6d695f62241921b83dd78c8aa1b559e8c20f29..6043ed9a135b433828ea4df16372bdbf506f9fc7 100644 (file)
@@ -590,4 +590,9 @@ func Test_curly_assignment()
   unlet g:gvar
 endfunc
 
+func Test_deep_recursion()
+  " this was running out of stack
+  call assert_fails("exe 'if ' .. repeat('(', 1002)", 'E1169: Expression too recursive: ((')
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 4cb980ea4abd9780b519130680e0de67527a8a2a..16a99ef92e4607781539459925b99f7f54232cbd 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4206,
 /**/
     4205,
 /**/