Fix diagnosis of negative relative references to non-existent groups.

This commit is contained in:
Philip.Hazel 2015-03-31 15:01:25 +00:00
parent 2327a5860b
commit 6a2cb0d774
4 changed files with 24 additions and 10 deletions

View File

@ -55,6 +55,10 @@ a fixed maximum following a group that contains a subroutine reference was
incorrectly compiled and could trigger buffer overflow. This bug was discovered incorrectly compiled and could trigger buffer overflow. This bug was discovered
by the LLVM fuzzer. by the LLVM fuzzer.
14. Negative relative recursive references such as (?-7) to non-existent
subpatterns were not being diagnosed and could lead to unpredictable behaviour.
This bug was discovered by the LLVM fuzzer.
Version 10.10 06-March-2015 Version 10.10 06-March-2015
--------------------------- ---------------------------

View File

@ -3179,15 +3179,15 @@ for (;; ptr++)
BOOL xclass_has_prop; BOOL xclass_has_prop;
#endif #endif
int newoptions; int newoptions;
uint32_t recno; int recno; /* Must be signed */
int refsign; int refsign; /* Must be signed */
int skipbytes; int skipbytes;
uint32_t subreqcu, subfirstcu;
int32_t subreqcuflags, subfirstcuflags;
int terminator; int terminator;
unsigned int mclength; unsigned int mclength;
unsigned int tempbracount; unsigned int tempbracount;
uint32_t ec; uint32_t ec;
uint32_t subreqcu, subfirstcu;
int32_t subreqcuflags, subfirstcuflags; /* Must be signed */
PCRE2_UCHAR mcbuffer[8]; PCRE2_UCHAR mcbuffer[8];
/* Get next character in the pattern */ /* Get next character in the pattern */
@ -5443,13 +5443,13 @@ for (;; ptr++)
} }
if (refsign != 0) recno = (refsign == CHAR_MINUS)? if (refsign != 0) recno = (refsign == CHAR_MINUS)?
cb->bracount - recno + 1 : recno + cb->bracount; cb->bracount - recno + 1 : recno + cb->bracount;
if (recno <= 0 || recno > cb->final_bracount) if (recno <= 0 || (uint32_t)recno > cb->final_bracount)
{ {
*errorcodeptr = ERR15; *errorcodeptr = ERR15;
goto FAILED; goto FAILED;
} }
PUT2(code, 2+LINK_SIZE, recno); PUT2(code, 2+LINK_SIZE, recno);
if (recno > cb->top_backref) cb->top_backref = recno; if ((uint32_t)recno > cb->top_backref) cb->top_backref = recno;
break; break;
} }
@ -5475,7 +5475,7 @@ for (;; ptr++)
for (;;) for (;;)
{ {
recno = GET2(slot, 0); /* Number for last found */ recno = GET2(slot, 0); /* Number for last found */
if (recno > cb->top_backref) cb->top_backref = recno; if ((uint32_t)recno > cb->top_backref) cb->top_backref = recno;
count++; count++;
if (++i >= cb->names_found) break; if (++i >= cb->names_found) break;
slot += cb->name_entry_size; slot += cb->name_entry_size;
@ -6000,7 +6000,7 @@ for (;; ptr++)
open_capitem *oc; open_capitem *oc;
recno = GET2(slot, 0); recno = GET2(slot, 0);
cb->backref_map |= (recno < 32)? (1 << recno) : 1; cb->backref_map |= (recno < 32)? (1 << recno) : 1;
if (recno > cb->top_backref) cb->top_backref = recno; if ((uint32_t)recno > cb->top_backref) cb->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it /* Check to see if this back reference is recursive, that it, it
is inside the group that it references. A flag is set so that the is inside the group that it references. A flag is set so that the
@ -6121,7 +6121,7 @@ for (;; ptr++)
if (called == NULL) if (called == NULL)
{ {
if (recno > cb->final_bracount) if ((uint32_t)recno > cb->final_bracount)
{ {
*errorcodeptr = ERR15; *errorcodeptr = ERR15;
goto FAILED; goto FAILED;
@ -6626,7 +6626,7 @@ for (;; ptr++)
*code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF; *code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF;
PUT2INC(code, 0, recno); PUT2INC(code, 0, recno);
cb->backref_map |= (recno < 32)? (1 << recno) : 1; cb->backref_map |= (recno < 32)? (1 << recno) : 1;
if (recno > cb->top_backref) cb->top_backref = recno; if ((uint32_t)recno > cb->top_backref) cb->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it /* Check to see if this back reference is recursive, that it, it
is inside the group that it references. A flag is set so that the is inside the group that it references. A flag is set so that the

4
testdata/testinput2 vendored
View File

@ -4249,4 +4249,8 @@ a random value. /Ix
"X((?2)()*+){2}"B "X((?2)()*+){2}"B
/(?<=\bABQ(3(?-7)))/
/(?<=\bABQ(3(?+7)))/
# End of testinput2 # End of testinput2

View File

@ -14251,4 +14251,10 @@ Failed: error 128 at offset 3: assertion expected after (?( or (?(?C)
End End
------------------------------------------------------------------ ------------------------------------------------------------------
/(?<=\bABQ(3(?-7)))/
Failed: error 115 at offset 15: reference to non-existent subpattern
/(?<=\bABQ(3(?+7)))/
Failed: error 115 at offset 15: reference to non-existent subpattern
# End of testinput2 # End of testinput2