# HG changeset patch # User Bram Moolenaar # Date 1643454004 -3600 # Node ID d0096a7f8d965a4203c8d6c6c3d852b2ad3638b3 # Parent 37dca3b3f63be00c1daa2a4430e398549347c0c5 patch 8.2.4247: stack corruption when looking for spell suggestions Commit: https://github.com/vim/vim/commit/06f15416bb8d5636200a10776f1752c4d6e49f31 Author: Bram Moolenaar 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. diff --git a/src/spellsuggest.c b/src/spellsuggest.c --- 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 } } } diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim --- 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= diff --git a/src/version.c b/src/version.c --- 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,