diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-04-04 07:28:03 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2022-04-04 09:37:40 +0800 |
commit | 945caeeda2f0a9c660cf05f655dad5d7a88cd4f5 (patch) | |
tree | c7a8231325c3a1eac65147fcdfdca2584073ed35 | |
parent | 1f038bc592282ca60982b288b4c4bc48fcb37839 (diff) | |
download | rneovim-945caeeda2f0a9c660cf05f655dad5d7a88cd4f5.tar.gz rneovim-945caeeda2f0a9c660cf05f655dad5d7a88cd4f5.tar.bz2 rneovim-945caeeda2f0a9c660cf05f655dad5d7a88cd4f5.zip |
vim-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.
https://github.com/vim/vim/commit/06f15416bb8d5636200a10776f1752c4d6e49f31
Cherry-pick parentheses from patch 8.2.4402.
-rw-r--r-- | src/nvim/spell.c | 11 | ||||
-rw-r--r-- | src/nvim/testdir/test_spell.vim | 8 |
2 files changed, 17 insertions, 2 deletions
diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 97f39c925a..c4504a36ee 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -3690,7 +3690,7 @@ static void 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. // @@ -3794,6 +3794,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } } + // The loop may take an indefinite amount of time. Break out after five + // sectonds. TODO(vim): add an option for the time limit. + proftime_T time_limit = profile_setlimit(5000); + // Loop to find all suggestions. At each round we either: // - For the current state try one operation, advance "ts_curi", // increase "depth". @@ -3824,7 +3828,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // At end of a prefix or at start of prefixtree: check for // following word. - if (byts[arridx] == 0 || n == STATE_NOPREFIX) { + if (depth < MAXWLEN && (byts[arridx] == 0 || n == STATE_NOPREFIX)) { // Set su->su_badflags to the caps type at this position. // Use the caps type until here for the prefix itself. n = nofold_len(fword, sp->ts_fidx, su->su_badptr); @@ -4927,6 +4931,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (--breakcheckcount == 0) { os_breakcheck(); breakcheckcount = 1000; + if (profile_passed_limit(time_limit)) { + got_int = true; + } } } } diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim index d3a11aebd8..56ed97cdd9 100644 --- a/src/nvim/testdir/test_spell.vim +++ b/src/nvim/testdir/test_spell.vim @@ -681,6 +681,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) throw 'skipped: Nvim does not support enc=latin1' set enc=latin1 |