]> granicus.if.org Git - vim/commitdiff
patch 8.2.4247: stack corruption when looking for spell suggestions v8.2.4247
authorBram Moolenaar <Bram@vim.org>
Sat, 29 Jan 2022 10:51:59 +0000 (10:51 +0000)
committerBram Moolenaar <Bram@vim.org>
Sat, 29 Jan 2022 10:51:59 +0000 (10:51 +0000)
Problem:    Stack corruption when looking for spell suggestions.
Solution:   Prevent the depth increased too much.  Add a five second time
            limit to finding suggestions.

src/spellsuggest.c
src/testdir/test_spell.vim
src/version.c

index b2b402919fb44f671a069e71cd096b39e613192d..e54b6fdc8792e7de9f23b76653baa37e41a819ec 100644 (file)
@@ -1205,7 +1205,7 @@ suggest_try_change(suginfo_T *su)
 
 // Check the maximum score, if we go over it we won't try this change.
 #define TRY_DEEPER(su, stack, depth, add) \
-               (stack[depth].ts_score + (add) < su->su_maxscore)
+          (depth < MAXWLEN && stack[depth].ts_score + (add) < su->su_maxscore)
 
 /*
  * Try finding suggestions by adding/removing/swapping letters.
@@ -1277,6 +1277,9 @@ suggest_trie_walk(
     char_u     changename[MAXWLEN][80];
 #endif
     int                breakcheckcount = 1000;
+#ifdef FEAT_RELTIME
+    proftime_T time_limit;
+#endif
     int                compound_ok;
 
     // Go through the whole case-fold tree, try changes at each node.
@@ -1321,6 +1324,11 @@ suggest_trie_walk(
            sp->ts_state = STATE_START;
        }
     }
+#ifdef FEAT_RELTIME
+    // The loop may take an indefinite amount of time. Break out after five
+    // sectonds. TODO: add an option for the time limit.
+    profile_setlimit(5000, &time_limit);
+#endif
 
     // Loop to find all suggestions.  At each round we either:
     // - For the current state try one operation, advance "ts_curi",
@@ -1355,7 +1363,8 @@ suggest_trie_walk(
 
                // At end of a prefix or at start of prefixtree: check for
                // following word.
-               if (byts[arridx] == 0 || n == (int)STATE_NOPREFIX)
+               if (depth < MAXWLEN
+                           && (byts[arridx] == 0 || n == (int)STATE_NOPREFIX))
                {
                    // Set su->su_badflags to the caps type at this position.
                    // Use the caps type until here for the prefix itself.
@@ -2649,6 +2658,10 @@ suggest_trie_walk(
            {
                ui_breakcheck();
                breakcheckcount = 1000;
+#ifdef FEAT_RELTIME
+               if (profile_passed_limit(&time_limit))
+                   got_int = TRUE;
+#endif
            }
        }
     }
index 3c32450c241c9c3ccb18c5147cf6cb3b55bfb7a3..a5c990ab7284ff8bf95de5bf69a2e88e0ad2a04c 100644 (file)
@@ -773,6 +773,14 @@ func Test_spell_long_word()
   set nospell
 endfunc
 
+func Test_spellsuggest_too_deep()
+  " This was incrementing "depth" over MAXWLEN.
+  new
+  norm \16s000G00ý000000000000
+  sil norm ..vzG................vvzG0     v z=
+  bwipe!
+endfunc
+
 func LoadAffAndDic(aff_contents, dic_contents)
   set enc=latin1
   set spellfile=
index b0d48d50a612966d83713cfaddfddab38e7e83ec..005a394ab4dc4627e60d5164797cf3f0955810e8 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4247,
 /**/
     4246,
 /**/