Mercurial > vim
comparison src/spellsuggest.c @ 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 | c9474ae175f4 |
children | 674240fcf6de |
comparison
equal
deleted
inserted
replaced
27437:37dca3b3f63b | 27438:d0096a7f8d96 |
---|---|
1203 } | 1203 } |
1204 } | 1204 } |
1205 | 1205 |
1206 // Check the maximum score, if we go over it we won't try this change. | 1206 // Check the maximum score, if we go over it we won't try this change. |
1207 #define TRY_DEEPER(su, stack, depth, add) \ | 1207 #define TRY_DEEPER(su, stack, depth, add) \ |
1208 (stack[depth].ts_score + (add) < su->su_maxscore) | 1208 (depth < MAXWLEN && stack[depth].ts_score + (add) < su->su_maxscore) |
1209 | 1209 |
1210 /* | 1210 /* |
1211 * Try finding suggestions by adding/removing/swapping letters. | 1211 * Try finding suggestions by adding/removing/swapping letters. |
1212 * | 1212 * |
1213 * This uses a state machine. At each node in the tree we try various | 1213 * This uses a state machine. At each node in the tree we try various |
1275 #ifdef DEBUG_TRIEWALK | 1275 #ifdef DEBUG_TRIEWALK |
1276 // Stores the name of the change made at each level. | 1276 // Stores the name of the change made at each level. |
1277 char_u changename[MAXWLEN][80]; | 1277 char_u changename[MAXWLEN][80]; |
1278 #endif | 1278 #endif |
1279 int breakcheckcount = 1000; | 1279 int breakcheckcount = 1000; |
1280 #ifdef FEAT_RELTIME | |
1281 proftime_T time_limit; | |
1282 #endif | |
1280 int compound_ok; | 1283 int compound_ok; |
1281 | 1284 |
1282 // Go through the whole case-fold tree, try changes at each node. | 1285 // Go through the whole case-fold tree, try changes at each node. |
1283 // "tword[]" contains the word collected from nodes in the tree. | 1286 // "tword[]" contains the word collected from nodes in the tree. |
1284 // "fword[]" the word we are trying to match with (initially the bad | 1287 // "fword[]" the word we are trying to match with (initially the bad |
1319 idxs = fidxs; | 1322 idxs = fidxs; |
1320 sp->ts_prefixdepth = PFD_NOPREFIX; | 1323 sp->ts_prefixdepth = PFD_NOPREFIX; |
1321 sp->ts_state = STATE_START; | 1324 sp->ts_state = STATE_START; |
1322 } | 1325 } |
1323 } | 1326 } |
1327 #ifdef FEAT_RELTIME | |
1328 // The loop may take an indefinite amount of time. Break out after five | |
1329 // sectonds. TODO: add an option for the time limit. | |
1330 profile_setlimit(5000, &time_limit); | |
1331 #endif | |
1324 | 1332 |
1325 // Loop to find all suggestions. At each round we either: | 1333 // Loop to find all suggestions. At each round we either: |
1326 // - For the current state try one operation, advance "ts_curi", | 1334 // - For the current state try one operation, advance "ts_curi", |
1327 // increase "depth". | 1335 // increase "depth". |
1328 // - When a state is done go to the next, set "ts_state". | 1336 // - When a state is done go to the next, set "ts_state". |
1353 sp->ts_state = STATE_ENDNUL; | 1361 sp->ts_state = STATE_ENDNUL; |
1354 sp->ts_save_badflags = su->su_badflags; | 1362 sp->ts_save_badflags = su->su_badflags; |
1355 | 1363 |
1356 // At end of a prefix or at start of prefixtree: check for | 1364 // At end of a prefix or at start of prefixtree: check for |
1357 // following word. | 1365 // following word. |
1358 if (byts[arridx] == 0 || n == (int)STATE_NOPREFIX) | 1366 if (depth < MAXWLEN |
1367 && (byts[arridx] == 0 || n == (int)STATE_NOPREFIX)) | |
1359 { | 1368 { |
1360 // Set su->su_badflags to the caps type at this position. | 1369 // Set su->su_badflags to the caps type at this position. |
1361 // Use the caps type until here for the prefix itself. | 1370 // Use the caps type until here for the prefix itself. |
1362 if (has_mbyte) | 1371 if (has_mbyte) |
1363 n = nofold_len(fword, sp->ts_fidx, su->su_badptr); | 1372 n = nofold_len(fword, sp->ts_fidx, su->su_badptr); |
2647 // Don't check for CTRL-C too often, it takes time. | 2656 // Don't check for CTRL-C too often, it takes time. |
2648 if (--breakcheckcount == 0) | 2657 if (--breakcheckcount == 0) |
2649 { | 2658 { |
2650 ui_breakcheck(); | 2659 ui_breakcheck(); |
2651 breakcheckcount = 1000; | 2660 breakcheckcount = 1000; |
2661 #ifdef FEAT_RELTIME | |
2662 if (profile_passed_limit(&time_limit)) | |
2663 got_int = TRUE; | |
2664 #endif | |
2652 } | 2665 } |
2653 } | 2666 } |
2654 } | 2667 } |
2655 } | 2668 } |
2656 | 2669 |