| 70 |
startcode pointer to start of the whole pattern |
startcode pointer to start of the whole pattern |
| 71 |
options the compiling options |
options the compiling options |
| 72 |
had_accept pointer to flag for (*ACCEPT) encountered |
had_accept pointer to flag for (*ACCEPT) encountered |
| 73 |
|
int RECURSE depth |
| 74 |
|
|
| 75 |
Returns: the minimum length |
Returns: the minimum length |
| 76 |
-1 if \C was encountered |
-1 if \C was encountered |
| 80 |
|
|
| 81 |
static int |
static int |
| 82 |
find_minlength(const uschar *code, const uschar *startcode, int options, |
find_minlength(const uschar *code, const uschar *startcode, int options, |
| 83 |
BOOL *had_accept_ptr) |
BOOL *had_accept_ptr, int recurse_depth) |
| 84 |
{ |
{ |
| 85 |
int length = -1; |
int length = -1; |
| 86 |
BOOL utf8 = (options & PCRE_UTF8) != 0; |
BOOL utf8 = (options & PCRE_UTF8) != 0; |
| 128 |
case OP_BRAPOS: |
case OP_BRAPOS: |
| 129 |
case OP_SBRAPOS: |
case OP_SBRAPOS: |
| 130 |
case OP_ONCE: |
case OP_ONCE: |
| 131 |
d = find_minlength(cc, startcode, options, had_accept_ptr); |
d = find_minlength(cc, startcode, options, had_accept_ptr, recurse_depth); |
| 132 |
if (d < 0) return d; |
if (d < 0) return d; |
| 133 |
branchlength += d; |
branchlength += d; |
| 134 |
if (*had_accept_ptr) return branchlength; |
if (*had_accept_ptr) return branchlength; |
| 379 |
} |
} |
| 380 |
else |
else |
| 381 |
{ |
{ |
| 382 |
d = find_minlength(cs, startcode, options, had_accept_ptr); |
d = find_minlength(cs, startcode, options, had_accept_ptr, |
| 383 |
|
recurse_depth); |
| 384 |
*had_accept_ptr = FALSE; |
*had_accept_ptr = FALSE; |
| 385 |
} |
} |
| 386 |
} |
} |
| 418 |
|
|
| 419 |
branchlength += min * d; |
branchlength += min * d; |
| 420 |
break; |
break; |
| 421 |
|
|
| 422 |
|
/* We can easily detect direct recursion, but not mutual recursion. This is |
| 423 |
|
caught by a recursion depth count. */ |
| 424 |
|
|
| 425 |
case OP_RECURSE: |
case OP_RECURSE: |
| 426 |
cs = ce = (uschar *)startcode + GET(cc, 1); |
cs = ce = (uschar *)startcode + GET(cc, 1); |
| 427 |
if (cs == NULL) return -2; |
if (cs == NULL) return -2; |
| 428 |
do ce += GET(ce, 1); while (*ce == OP_ALT); |
do ce += GET(ce, 1); while (*ce == OP_ALT); |
| 429 |
if (cc > cs && cc < ce) |
if ((cc > cs && cc < ce) || recurse_depth > 10) |
| 430 |
had_recurse = TRUE; |
had_recurse = TRUE; |
| 431 |
else |
else |
| 432 |
{ |
{ |
| 433 |
branchlength += find_minlength(cs, startcode, options, had_accept_ptr); |
branchlength += find_minlength(cs, startcode, options, had_accept_ptr, |
| 434 |
|
recurse_depth + 1); |
| 435 |
*had_accept_ptr = FALSE; |
*had_accept_ptr = FALSE; |
| 436 |
} |
} |
| 437 |
cc += 1 + LINK_SIZE; |
cc += 1 + LINK_SIZE; |
| 1281 |
|
|
| 1282 |
/* Find the minimum length of subject string. */ |
/* Find the minimum length of subject string. */ |
| 1283 |
|
|
| 1284 |
switch(min = find_minlength(code, code, re->options, &had_accept)) |
switch(min = find_minlength(code, code, re->options, &had_accept, 0)) |
| 1285 |
{ |
{ |
| 1286 |
case -2: *errorptr = "internal error: missing capturing bracket"; break; |
case -2: *errorptr = "internal error: missing capturing bracket"; break; |
| 1287 |
case -3: *errorptr = "internal error: opcode not recognized"; break; |
case -3: *errorptr = "internal error: opcode not recognized"; break; |