@@ -53,6 +53,9 @@ typedef enum {
5353
5454#define CAPTURE_COUNT_MAX 255
5555#define STACK_SIZE_MAX 255
56+ /* must be large enough to have a negligible runtime cost and small
57+ enough to call the interrupt callback often. */
58+ #define INTERRUPT_COUNTER_INIT 10000
5659
5760/* unicode code points */
5861#define CP_LS 0x2028
@@ -1992,6 +1995,7 @@ typedef struct {
19921995 bool multi_line ;
19931996 bool ignore_case ;
19941997 bool is_unicode ;
1998+ int interrupt_counter ;
19951999 void * opaque ; /* used for stack overflow check */
19962000
19972001 size_t state_size ;
@@ -2038,7 +2042,17 @@ static int push_state(REExecContext *s,
20382042 return 0 ;
20392043}
20402044
2041- /* return 1 if match, 0 if not match or -1 if error. */
2045+ static int lre_poll_timeout (REExecContext * s )
2046+ {
2047+ if (unlikely (-- s -> interrupt_counter <= 0 )) {
2048+ s -> interrupt_counter = INTERRUPT_COUNTER_INIT ;
2049+ if (lre_check_timeout (s -> opaque ))
2050+ return LRE_RET_TIMEOUT ;
2051+ }
2052+ return 0 ;
2053+ }
2054+
2055+ /* return 1 if match, 0 if not match or < 0 if error. */
20422056static intptr_t lre_exec_backtrack (REExecContext * s , uint8_t * * capture ,
20432057 StackInt * stack , int stack_len ,
20442058 const uint8_t * pc , const uint8_t * cptr ,
@@ -2069,6 +2083,8 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
20692083 ret = 0 ;
20702084 recurse :
20712085 for (;;) {
2086+ if (lre_poll_timeout (s ))
2087+ return LRE_RET_TIMEOUT ;
20722088 if (s -> state_stack_len == 0 )
20732089 return ret ;
20742090 rs = (REExecState * )(s -> state_stack +
@@ -2162,7 +2178,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
21622178 ret = push_state (s , capture , stack , stack_len ,
21632179 pc1 , cptr , RE_EXEC_STATE_SPLIT , 0 );
21642180 if (ret < 0 )
2165- return -1 ;
2181+ return LRE_RET_MEMORY_ERROR ;
21662182 break ;
21672183 }
21682184 case REOP_lookahead :
@@ -2174,12 +2190,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
21742190 RE_EXEC_STATE_LOOKAHEAD + opcode - REOP_lookahead ,
21752191 0 );
21762192 if (ret < 0 )
2177- return -1 ;
2193+ return LRE_RET_MEMORY_ERROR ;
21782194 break ;
21792195
21802196 case REOP_goto :
21812197 val = get_u32 (pc );
21822198 pc += 4 + (int )val ;
2199+ if (lre_poll_timeout (s ))
2200+ return LRE_RET_TIMEOUT ;
21832201 break ;
21842202 case REOP_line_start :
21852203 if (cptr == s -> cbuf )
@@ -2244,6 +2262,8 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
22442262 pc += 4 ;
22452263 if (-- stack [stack_len - 1 ] != 0 ) {
22462264 pc += (int )val ;
2265+ if (lre_poll_timeout (s ))
2266+ return LRE_RET_TIMEOUT ;
22472267 }
22482268 break ;
22492269 case REOP_push_char_pos :
@@ -2418,9 +2438,12 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
24182438
24192439 q = 0 ;
24202440 for (;;) {
2441+ if (lre_poll_timeout (s ))
2442+ return LRE_RET_TIMEOUT ;
24212443 res = lre_exec_backtrack (s , capture , stack , stack_len ,
24222444 pc1 , cptr , true);
2423- if (res == -1 )
2445+ if (res == LRE_RET_MEMORY_ERROR ||
2446+ res == LRE_RET_TIMEOUT )
24242447 return res ;
24252448 if (!res )
24262449 break ;
@@ -2438,7 +2461,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
24382461 RE_EXEC_STATE_GREEDY_QUANT ,
24392462 q - quant_min );
24402463 if (ret < 0 )
2441- return -1 ;
2464+ return LRE_RET_MEMORY_ERROR ;
24422465 }
24432466 }
24442467 break ;
@@ -2448,7 +2471,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
24482471 }
24492472}
24502473
2451- /* Return 1 if match, 0 if not match or -1 if error. cindex is the
2474+ /* Return 1 if match, 0 if not match or < 0 if error (see LRE_RET_x) . cindex is the
24522475 starting position of the match and must be such as 0 <= cindex <=
24532476 clen. */
24542477int lre_exec (uint8_t * * capture ,
@@ -2470,6 +2493,7 @@ int lre_exec(uint8_t **capture,
24702493 s -> cbuf_type = cbuf_type ;
24712494 if (s -> cbuf_type == 1 && s -> is_unicode )
24722495 s -> cbuf_type = 2 ;
2496+ s -> interrupt_counter = INTERRUPT_COUNTER_INIT ;
24732497 s -> opaque = opaque ;
24742498
24752499 s -> state_size = sizeof (REExecState ) +
0 commit comments