0
0
mirror of https://github.com/vim/vim.git synced 2025-10-14 07:04:10 -04:00

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.
This commit is contained in:
Bram Moolenaar
2022-01-29 10:51:59 +00:00
parent e96eea7b6a
commit 06f15416bb
3 changed files with 25 additions and 2 deletions

View 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. // Check the maximum score, if we go over it we won't try this change.
#define TRY_DEEPER(su, stack, depth, add) \ #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. * Try finding suggestions by adding/removing/swapping letters.
@@ -1277,6 +1277,9 @@ suggest_trie_walk(
char_u changename[MAXWLEN][80]; char_u changename[MAXWLEN][80];
#endif #endif
int breakcheckcount = 1000; int breakcheckcount = 1000;
#ifdef FEAT_RELTIME
proftime_T time_limit;
#endif
int compound_ok; int compound_ok;
// Go through the whole case-fold tree, try changes at each node. // Go through the whole case-fold tree, try changes at each node.
@@ -1321,6 +1324,11 @@ suggest_trie_walk(
sp->ts_state = STATE_START; 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: // Loop to find all suggestions. At each round we either:
// - For the current state try one operation, advance "ts_curi", // - 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 // At end of a prefix or at start of prefixtree: check for
// following word. // 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. // Set su->su_badflags to the caps type at this position.
// Use the caps type until here for the prefix itself. // Use the caps type until here for the prefix itself.
@@ -2649,6 +2658,10 @@ suggest_trie_walk(
{ {
ui_breakcheck(); ui_breakcheck();
breakcheckcount = 1000; breakcheckcount = 1000;
#ifdef FEAT_RELTIME
if (profile_passed_limit(&time_limit))
got_int = TRUE;
#endif
} }
} }
} }

View File

@@ -773,6 +773,14 @@ func Test_spell_long_word()
set nospell set nospell
endfunc endfunc
func Test_spellsuggest_too_deep()
" This was incrementing "depth" over MAXWLEN.
new
norm s000G00<EFBFBD>000000000000
sil norm ..vzG................vvzG0 v z=
bwipe!
endfunc
func LoadAffAndDic(aff_contents, dic_contents) func LoadAffAndDic(aff_contents, dic_contents)
set enc=latin1 set enc=latin1
set spellfile= set spellfile=

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
4247,
/**/ /**/
4246, 4246,
/**/ /**/