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; |