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