changeset 27438:d0096a7f8d96 v8.2.4247

patch 8.2.4247: stack corruption when looking for spell suggestions Commit: https://github.com/vim/vim/commit/06f15416bb8d5636200a10776f1752c4d6e49f31 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 29 10:51:59 2022 +0000 patch 8.2.4247: stack corruption when looking for spell suggestions Problem: Stack corruption when looking for spell suggestions. Solution: Prevent the depth increased too much. Add a five second time limit to finding suggestions.
author Bram Moolenaar <Bram@vim.org>
date Sat, 29 Jan 2022 12:00:04 +0100
parents 37dca3b3f63b
children 996b7602c7fa
files src/spellsuggest.c src/testdir/test_spell.vim src/version.c
diffstat 3 files changed, 25 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/spellsuggest.c
+++ b/src/spellsuggest.c
@@ -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
 	    }
 	}
     }
--- a/src/testdir/test_spell.vim
+++ b/src/testdir/test_spell.vim
@@ -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 s000G00ý000000000000
+  sil norm ..vzG................vvzG0     v z=
+  bwipe!
+endfunc
+
 func LoadAffAndDic(aff_contents, dic_contents)
   set enc=latin1
   set spellfile=
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4247,
+/**/
     4246,
 /**/
     4245,