diff --git a/ChangeLog b/ChangeLog index 1fa674b..a6fa98a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 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 --------------------------- diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c index 2b04f08..4fee058 100644 --- a/src/pcre2_compile.c +++ b/src/pcre2_compile.c @@ -3179,15 +3179,15 @@ for (;; ptr++) BOOL xclass_has_prop; #endif int newoptions; - uint32_t recno; - int refsign; + int recno; /* Must be signed */ + int refsign; /* Must be signed */ int skipbytes; - uint32_t subreqcu, subfirstcu; - int32_t subreqcuflags, subfirstcuflags; int terminator; unsigned int mclength; unsigned int tempbracount; uint32_t ec; + uint32_t subreqcu, subfirstcu; + int32_t subreqcuflags, subfirstcuflags; /* Must be signed */ PCRE2_UCHAR mcbuffer[8]; /* Get next character in the pattern */ @@ -5443,13 +5443,13 @@ for (;; ptr++) } if (refsign != 0) recno = (refsign == CHAR_MINUS)? 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; goto FAILED; } 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; } @@ -5475,7 +5475,7 @@ for (;; ptr++) for (;;) { 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++; if (++i >= cb->names_found) break; slot += cb->name_entry_size; @@ -6000,7 +6000,7 @@ for (;; ptr++) open_capitem *oc; recno = GET2(slot, 0); 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 is inside the group that it references. A flag is set so that the @@ -6121,7 +6121,7 @@ for (;; ptr++) if (called == NULL) { - if (recno > cb->final_bracount) + if ((uint32_t)recno > cb->final_bracount) { *errorcodeptr = ERR15; goto FAILED; @@ -6626,7 +6626,7 @@ for (;; ptr++) *code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, recno); 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 is inside the group that it references. A flag is set so that the diff --git a/testdata/testinput2 b/testdata/testinput2 index ead245a..eaa445c 100644 --- a/testdata/testinput2 +++ b/testdata/testinput2 @@ -4249,4 +4249,8 @@ a random value. /Ix "X((?2)()*+){2}"B +/(?<=\bABQ(3(?-7)))/ + +/(?<=\bABQ(3(?+7)))/ + # End of testinput2 diff --git a/testdata/testoutput2 b/testdata/testoutput2 index fda5412..80bdadf 100644 --- a/testdata/testoutput2 +++ b/testdata/testoutput2 @@ -14251,4 +14251,10 @@ Failed: error 128 at offset 3: assertion expected after (?( or (?(?C) 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