| 66 |
rather than bytes. |
rather than bytes. |
| 67 |
|
|
| 68 |
Arguments: |
Arguments: |
| 69 |
code pointer to start of group (the bracket) |
code pointer to start of group (the bracket) |
| 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 |
| 73 |
|
|
| 74 |
Returns: the minimum length |
Returns: the minimum length |
| 75 |
-1 if \C was encountered |
-1 if \C was encountered |
| 78 |
*/ |
*/ |
| 79 |
|
|
| 80 |
static int |
static int |
| 81 |
find_minlength(const uschar *code, const uschar *startcode, int options) |
find_minlength(const uschar *code, const uschar *startcode, int options, |
| 82 |
|
BOOL *had_accept_ptr) |
| 83 |
{ |
{ |
| 84 |
int length = -1; |
int length = -1; |
| 85 |
BOOL utf8 = (options & PCRE_UTF8) != 0; |
BOOL utf8 = (options & PCRE_UTF8) != 0; |
| 127 |
case OP_BRAPOS: |
case OP_BRAPOS: |
| 128 |
case OP_SBRAPOS: |
case OP_SBRAPOS: |
| 129 |
case OP_ONCE: |
case OP_ONCE: |
| 130 |
d = find_minlength(cc, startcode, options); |
d = find_minlength(cc, startcode, options, had_accept_ptr); |
| 131 |
if (d < 0) return d; |
if (d < 0) return d; |
| 132 |
branchlength += d; |
branchlength += d; |
| 133 |
|
if (*had_accept_ptr) return branchlength; |
| 134 |
do cc += GET(cc, 1); while (*cc == OP_ALT); |
do cc += GET(cc, 1); while (*cc == OP_ALT); |
| 135 |
cc += 1 + LINK_SIZE; |
cc += 1 + LINK_SIZE; |
| 136 |
break; |
break; |
| 137 |
|
|
| 138 |
/* Reached end of a branch; if it's a ket it is the end of a nested |
/* Reached end of a branch; if it's a ket it is the end of a nested |
| 139 |
call. If it's ALT it is an alternation in a nested call. If it is |
call. If it's ALT it is an alternation in a nested call. If it is END it's |
| 140 |
END it's the end of the outer call. All can be handled by the same code. */ |
the end of the outer call. All can be handled by the same code. If it is |
| 141 |
|
ACCEPT, it is essentially the same as END, but we set a flag so that |
| 142 |
|
counting stops. */ |
| 143 |
|
|
| 144 |
|
case OP_ACCEPT: |
| 145 |
|
*had_accept_ptr = TRUE; |
| 146 |
|
/* Fall through */ |
| 147 |
case OP_ALT: |
case OP_ALT: |
| 148 |
case OP_KET: |
case OP_KET: |
| 149 |
case OP_KETRMAX: |
case OP_KETRMAX: |
| 152 |
case OP_END: |
case OP_END: |
| 153 |
if (length < 0 || (!had_recurse && branchlength < length)) |
if (length < 0 || (!had_recurse && branchlength < length)) |
| 154 |
length = branchlength; |
length = branchlength; |
| 155 |
if (*cc != OP_ALT) return length; |
if (op != OP_ALT) return length; |
| 156 |
cc += 1 + LINK_SIZE; |
cc += 1 + LINK_SIZE; |
| 157 |
branchlength = 0; |
branchlength = 0; |
| 158 |
had_recurse = FALSE; |
had_recurse = FALSE; |
| 375 |
d = 0; |
d = 0; |
| 376 |
had_recurse = TRUE; |
had_recurse = TRUE; |
| 377 |
} |
} |
| 378 |
else d = find_minlength(cs, startcode, options); |
else |
| 379 |
|
{ |
| 380 |
|
d = find_minlength(cs, startcode, options, had_accept_ptr); |
| 381 |
|
*had_accept_ptr = FALSE; |
| 382 |
|
} |
| 383 |
} |
} |
| 384 |
else d = 0; |
else d = 0; |
| 385 |
cc += 3; |
cc += 3; |
| 423 |
if (cc > cs && cc < ce) |
if (cc > cs && cc < ce) |
| 424 |
had_recurse = TRUE; |
had_recurse = TRUE; |
| 425 |
else |
else |
| 426 |
branchlength += find_minlength(cs, startcode, options); |
{ |
| 427 |
|
branchlength += find_minlength(cs, startcode, options, had_accept_ptr); |
| 428 |
|
*had_accept_ptr = FALSE; |
| 429 |
|
} |
| 430 |
cc += 1 + LINK_SIZE; |
cc += 1 + LINK_SIZE; |
| 431 |
break; |
break; |
| 432 |
|
|
| 494 |
case OP_THEN_ARG: |
case OP_THEN_ARG: |
| 495 |
cc += _pcre_OP_lengths[op] + cc[1+LINK_SIZE]; |
cc += _pcre_OP_lengths[op] + cc[1+LINK_SIZE]; |
| 496 |
break; |
break; |
| 497 |
|
|
| 498 |
/* The remaining opcodes are just skipped over. */ |
/* The remaining opcodes are just skipped over. */ |
| 499 |
|
|
|
case OP_ACCEPT: |
|
| 500 |
case OP_CLOSE: |
case OP_CLOSE: |
| 501 |
case OP_COMMIT: |
case OP_COMMIT: |
| 502 |
case OP_FAIL: |
case OP_FAIL: |
| 702 |
while (try_next) /* Loop for items in this branch */ |
while (try_next) /* Loop for items in this branch */ |
| 703 |
{ |
{ |
| 704 |
int rc; |
int rc; |
| 705 |
|
|
| 706 |
switch(*tcode) |
switch(*tcode) |
| 707 |
{ |
{ |
| 708 |
/* If we reach something we don't understand, it means a new opcode has |
/* If we reach something we don't understand, it means a new opcode has |
| 1215 |
{ |
{ |
| 1216 |
int min; |
int min; |
| 1217 |
BOOL bits_set = FALSE; |
BOOL bits_set = FALSE; |
| 1218 |
|
BOOL had_accept = FALSE; |
| 1219 |
uschar start_bits[32]; |
uschar start_bits[32]; |
| 1220 |
pcre_extra *extra; |
pcre_extra *extra; |
| 1221 |
pcre_study_data *study; |
pcre_study_data *study; |
| 1273 |
|
|
| 1274 |
/* Find the minimum length of subject string. */ |
/* Find the minimum length of subject string. */ |
| 1275 |
|
|
| 1276 |
switch(min = find_minlength(code, code, re->options)) |
switch(min = find_minlength(code, code, re->options, &had_accept)) |
| 1277 |
{ |
{ |
| 1278 |
case -2: *errorptr = "internal error: missing capturing bracket"; break; |
case -2: *errorptr = "internal error: missing capturing bracket"; break; |
| 1279 |
case -3: *errorptr = "internal error: opcode not recognized"; break; |
case -3: *errorptr = "internal error: opcode not recognized"; break; |