From ef218fbba60bfe5b0a8ac9ea4445eac5fb0847e5 Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Sat, 7 Sep 2024 00:16:03 +0900 Subject: [PATCH] Guard against out-of-bounds memory access when parsing LIMIT_HEAP et al (#463) Patterns passed to pcre2_compile are not guaranteed to be null-terminated. Also, it can happen that there is an invalid pattern like this: (*LIMIT_HEAP=123 If the next byte of memory after the end of the pattern happens to be a digit, it will be parsed as part of the limit value. Or, if the next byte is a right parenthesis character, it will be taken as the end of the (*LIMIT_HEAP=nnn) construct. This will result in `skipatstart` being larger than `patlen`, which will result in underflow and an erroneous call to malloc requesting a huge number of bytes. --- src/pcre2_compile.c | 7 ++++--- testdata/testoutput15 | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c index e6843bb13..410f220b3 100644 --- a/src/pcre2_compile.c +++ b/src/pcre2_compile.c @@ -10552,12 +10552,12 @@ if ((options & PCRE2_LITERAL) == 0) ptr += pp; goto HAD_EARLY_ERROR; } - while (IS_DIGIT(ptr[pp])) + while (pp < patlen && IS_DIGIT(ptr[pp])) { if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */ c = c*10 + (ptr[pp++] - CHAR_0); } - if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS) + if (pp >= patlen || ptr[pp] != CHAR_RIGHT_PARENTHESIS) { errorcode = ERR60; ptr += pp; @@ -10566,7 +10566,7 @@ if ((options & PCRE2_LITERAL) == 0) if (p->type == PSO_LIMH) limit_heap = c; else if (p->type == PSO_LIMM) limit_match = c; else limit_depth = c; - skipatstart += pp - skipatstart; + skipatstart = ++pp; break; } break; /* Out of the table scan loop */ @@ -10574,6 +10574,7 @@ if ((options & PCRE2_LITERAL) == 0) } if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */ } + PCRE2_ASSERT(skipatstart <= patlen); } /* End of pattern-start options; advance to start of real regex. */ diff --git a/testdata/testoutput15 b/testdata/testoutput15 index aa9c5c930..f36faeeaf 100644 --- a/testdata/testoutput15 +++ b/testdata/testoutput15 @@ -111,10 +111,10 @@ Minimum depth limit = 10 3: ee /(*LIMIT_MATCH=12bc)abc/ -Failed: error 160 at offset 17: (*VERB) not recognized or malformed +Failed: error 160 at offset 16: (*VERB) not recognized or malformed /(*LIMIT_MATCH=4294967290)abc/ -Failed: error 160 at offset 24: (*VERB) not recognized or malformed +Failed: error 160 at offset 23: (*VERB) not recognized or malformed /(*LIMIT_DEPTH=4294967280)abc/I Capture group count = 0