Fix incorrect loop counter reset when setting lookbehind lengths (ClusterFuzz

38653).
This commit is contained in:
Philip Hazel 2021-09-14 16:10:20 +01:00
parent dc5f966635
commit 507e4dcf6f
2 changed files with 13 additions and 6 deletions

View File

@ -54,6 +54,12 @@ An option has also been added to pcre2grep to enable this.
7. Re-enable an optimization which was unintentionally disabled in 10.35. 7. Re-enable an optimization which was unintentionally disabled in 10.35.
8. There is a loop counter to catch excessively crazy patterns when checking
the lengths of lookbehinds at compile time. This was incorrectly getting reset
whenever a lookahead was processed, leading to some fuzzer-generated patterns
taking a very long time to compile when (?|) was present in the pattern,
because (?|) disables caching of group lengths.
Version 10.37 26-May-2021 Version 10.37 26-May-2021
------------------------- -------------------------

View File

@ -137,7 +137,7 @@ static BOOL
static int static int
check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *, check_lookbehinds(uint32_t *, uint32_t **, parsed_recurse_check *,
compile_block *); compile_block *, int *);
/************************************************* /*************************************************
@ -9161,7 +9161,7 @@ for (;; pptr++)
case META_LOOKAHEAD: case META_LOOKAHEAD:
case META_LOOKAHEADNOT: case META_LOOKAHEADNOT:
case META_LOOKAHEAD_NA: case META_LOOKAHEAD_NA:
*errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb); *errcodeptr = check_lookbehinds(pptr + 1, &pptr, recurses, cb, lcptr);
if (*errcodeptr != 0) return -1; if (*errcodeptr != 0) return -1;
/* Ignore any qualifiers that follow a lookahead assertion. */ /* Ignore any qualifiers that follow a lookahead assertion. */
@ -9501,16 +9501,16 @@ Arguments
retptr if not NULL, return the ket pointer here retptr if not NULL, return the ket pointer here
recurses chain of recurse_check to catch mutual recursion recurses chain of recurse_check to catch mutual recursion
cb points to the compile block cb points to the compile block
lcptr points to loop counter
Returns: 0 on success, or an errorcode (cb->erroroffset will be set) Returns: 0 on success, or an errorcode (cb->erroroffset will be set)
*/ */
static int static int
check_lookbehinds(uint32_t *pptr, uint32_t **retptr, check_lookbehinds(uint32_t *pptr, uint32_t **retptr,
parsed_recurse_check *recurses, compile_block *cb) parsed_recurse_check *recurses, compile_block *cb, int *lcptr)
{ {
int errorcode = 0; int errorcode = 0;
int loopcount = 0;
int nestlevel = 0; int nestlevel = 0;
cb->erroroffset = PCRE2_UNSET; cb->erroroffset = PCRE2_UNSET;
@ -9636,7 +9636,7 @@ for (; *pptr != META_END; pptr++)
case META_LOOKBEHIND: case META_LOOKBEHIND:
case META_LOOKBEHINDNOT: case META_LOOKBEHINDNOT:
case META_LOOKBEHIND_NA: case META_LOOKBEHIND_NA:
if (!set_lookbehind_lengths(&pptr, &errorcode, &loopcount, recurses, cb)) if (!set_lookbehind_lengths(&pptr, &errorcode, lcptr, recurses, cb))
return errorcode; return errorcode;
break; break;
} }
@ -10091,7 +10091,8 @@ lengths. */
if (has_lookbehind) if (has_lookbehind)
{ {
errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb); int loopcount = 0;
errorcode = check_lookbehinds(cb.parsed_pattern, NULL, NULL, &cb, &loopcount);
if (errorcode != 0) goto HAD_CB_ERROR; if (errorcode != 0) goto HAD_CB_ERROR;
} }