Mercurial > vim
comparison src/regexp_nfa.c @ 29191:0af5fe160e4e v8.2.5115
patch 8.2.5115: search timeout is overrun with some patterns
Commit: https://github.com/vim/vim/commit/616592e0816d2d9f893fcd95e3e1e0fbc5893168
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Jun 17 15:17:10 2022 +0100
patch 8.2.5115: search timeout is overrun with some patterns
Problem: Search timeout is overrun with some patterns.
Solution: Check for timeout in more places. Make the flag volatile and
atomic. Use assert_inrange() to see what happened.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 17 Jun 2022 16:30:06 +0200 |
parents | b90bca860b5a |
children | c7aa0c46acd5 |
comparison
equal
deleted
inserted
replaced
29190:a4f0e5e61728 | 29191:0af5fe160e4e |
---|---|
4235 } | 4235 } |
4236 | 4236 |
4237 return TRUE; | 4237 return TRUE; |
4238 } | 4238 } |
4239 | 4239 |
4240 #ifdef FEAT_RELTIME | |
4241 /* | |
4242 * Check if we are past the time limit, if there is one. | |
4243 */ | |
4244 static int | |
4245 nfa_did_time_out(void) | |
4246 { | |
4247 if (*timeout_flag) | |
4248 { | |
4249 if (nfa_timed_out != NULL) | |
4250 { | |
4251 if (!*nfa_timed_out) | |
4252 ch_log(NULL, "NFA regexp timed out"); | |
4253 *nfa_timed_out = TRUE; | |
4254 } | |
4255 return TRUE; | |
4256 } | |
4257 return FALSE; | |
4258 } | |
4259 #endif | |
4260 | |
4240 #ifdef ENABLE_LOG | 4261 #ifdef ENABLE_LOG |
4241 static void | 4262 static void |
4242 open_debug_log(int result) | 4263 open_debug_log(int result) |
4243 { | 4264 { |
4244 log_fd = fopen(NFA_REGEXP_RUN_LOG, "a"); | 4265 log_fd = fopen(NFA_REGEXP_RUN_LOG, "a"); |
4449 #define ADDSTATE_HERE_OFFSET 10 | 4470 #define ADDSTATE_HERE_OFFSET 10 |
4450 | 4471 |
4451 /* | 4472 /* |
4452 * Add "state" and possibly what follows to state list ".". | 4473 * Add "state" and possibly what follows to state list ".". |
4453 * Returns "subs_arg", possibly copied into temp_subs. | 4474 * Returns "subs_arg", possibly copied into temp_subs. |
4454 * Returns NULL when recursiveness is too deep. | 4475 * Returns NULL when recursiveness is too deep or timed out. |
4455 */ | 4476 */ |
4456 static regsubs_T * | 4477 static regsubs_T * |
4457 addstate( | 4478 addstate( |
4458 nfa_list_T *l, // runtime state list | 4479 nfa_list_T *l, // runtime state list |
4459 nfa_state_T *state, // state to update | 4480 nfa_state_T *state, // state to update |
4477 static regsubs_T temp_subs; | 4498 static regsubs_T temp_subs; |
4478 #ifdef ENABLE_LOG | 4499 #ifdef ENABLE_LOG |
4479 int did_print = FALSE; | 4500 int did_print = FALSE; |
4480 #endif | 4501 #endif |
4481 static int depth = 0; | 4502 static int depth = 0; |
4503 | |
4504 #ifdef FEAT_RELTIME | |
4505 if (nfa_did_time_out()) | |
4506 return NULL; | |
4507 #endif | |
4482 | 4508 |
4483 // This function is called recursively. When the depth is too much we run | 4509 // This function is called recursively. When the depth is too much we run |
4484 // out of stack and crash, limit recursiveness here. | 4510 // out of stack and crash, limit recursiveness here. |
4485 if (++depth >= 5000 || subs == NULL) | 4511 if (++depth >= 5000 || subs == NULL) |
4486 { | 4512 { |
5641 break; | 5667 break; |
5642 } | 5668 } |
5643 return 0L; | 5669 return 0L; |
5644 } | 5670 } |
5645 | 5671 |
5646 #ifdef FEAT_RELTIME | |
5647 /* | |
5648 * Check if we are past the time limit, if there is one. | |
5649 * To reduce overhead, only check one in "count" times. | |
5650 */ | |
5651 static int | |
5652 nfa_did_time_out(void) | |
5653 { | |
5654 if (*timeout_flag) | |
5655 { | |
5656 if (nfa_timed_out != NULL) | |
5657 *nfa_timed_out = TRUE; | |
5658 return TRUE; | |
5659 } | |
5660 return FALSE; | |
5661 } | |
5662 #endif | |
5663 | |
5664 /* | 5672 /* |
5665 * Main matching routine. | 5673 * Main matching routine. |
5666 * | 5674 * |
5667 * Run NFA to determine whether it matches rex.input. | 5675 * Run NFA to determine whether it matches rex.input. |
5668 * | 5676 * |
5706 // recursive_regmatch(). Allow interrupting them with CTRL-C. | 5714 // recursive_regmatch(). Allow interrupting them with CTRL-C. |
5707 fast_breakcheck(); | 5715 fast_breakcheck(); |
5708 if (got_int) | 5716 if (got_int) |
5709 return FALSE; | 5717 return FALSE; |
5710 #ifdef FEAT_RELTIME | 5718 #ifdef FEAT_RELTIME |
5711 // Check relatively often here, since this is the toplevel matching. | |
5712 if (nfa_did_time_out()) | 5719 if (nfa_did_time_out()) |
5713 return FALSE; | 5720 return FALSE; |
5714 #endif | 5721 #endif |
5715 | 5722 |
5716 #ifdef NFA_REGEXP_DEBUG_LOG | 5723 #ifdef NFA_REGEXP_DEBUG_LOG |
7107 // Allow interrupting with CTRL-C. | 7114 // Allow interrupting with CTRL-C. |
7108 line_breakcheck(); | 7115 line_breakcheck(); |
7109 if (got_int) | 7116 if (got_int) |
7110 break; | 7117 break; |
7111 #ifdef FEAT_RELTIME | 7118 #ifdef FEAT_RELTIME |
7112 // Check for timeout once in a twenty times to avoid overhead. | |
7113 if (nfa_did_time_out()) | 7119 if (nfa_did_time_out()) |
7114 break; | 7120 break; |
7115 #endif | 7121 #endif |
7116 } | 7122 } |
7117 | 7123 |