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.
This commit is contained in:
Bram Moolenaar
2022-06-17 15:17:10 +01:00
parent 5ea38d1e7f
commit 616592e081
7 changed files with 80 additions and 37 deletions

View File

@ -4237,6 +4237,27 @@ sub_equal(regsub_T *sub1, regsub_T *sub2)
return TRUE;
}
#ifdef FEAT_RELTIME
/*
* Check if we are past the time limit, if there is one.
*/
static int
nfa_did_time_out(void)
{
if (*timeout_flag)
{
if (nfa_timed_out != NULL)
{
if (!*nfa_timed_out)
ch_log(NULL, "NFA regexp timed out");
*nfa_timed_out = TRUE;
}
return TRUE;
}
return FALSE;
}
#endif
#ifdef ENABLE_LOG
static void
open_debug_log(int result)
@ -4451,7 +4472,7 @@ state_in_list(
/*
* Add "state" and possibly what follows to state list ".".
* Returns "subs_arg", possibly copied into temp_subs.
* Returns NULL when recursiveness is too deep.
* Returns NULL when recursiveness is too deep or timed out.
*/
static regsubs_T *
addstate(
@ -4480,6 +4501,11 @@ addstate(
#endif
static int depth = 0;
#ifdef FEAT_RELTIME
if (nfa_did_time_out())
return NULL;
#endif
// This function is called recursively. When the depth is too much we run
// out of stack and crash, limit recursiveness here.
if (++depth >= 5000 || subs == NULL)
@ -5643,24 +5669,6 @@ find_match_text(colnr_T startcol, int regstart, char_u *match_text)
return 0L;
}
#ifdef FEAT_RELTIME
/*
* Check if we are past the time limit, if there is one.
* To reduce overhead, only check one in "count" times.
*/
static int
nfa_did_time_out(void)
{
if (*timeout_flag)
{
if (nfa_timed_out != NULL)
*nfa_timed_out = TRUE;
return TRUE;
}
return FALSE;
}
#endif
/*
* Main matching routine.
*
@ -5708,7 +5716,6 @@ nfa_regmatch(
if (got_int)
return FALSE;
#ifdef FEAT_RELTIME
// Check relatively often here, since this is the toplevel matching.
if (nfa_did_time_out())
return FALSE;
#endif
@ -7109,7 +7116,6 @@ nextchar:
if (got_int)
break;
#ifdef FEAT_RELTIME
// Check for timeout once in a twenty times to avoid overhead.
if (nfa_did_time_out())
break;
#endif