Revision: 318
http://www.exim.org/viewvc/pcre2?view=rev&revision=318
Author: zherczeg
Date: 2015-07-20 08:38:06 +0100 (Mon, 20 Jul 2015)
Log Message:
-----------
Fix infinite recursion in the JIT compiler when certain patterns when certain patterns are analysed.
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/src/pcre2_jit_compile.c
code/trunk/testdata/testinput16
code/trunk/testdata/testoutput16
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2015-07-17 16:25:21 UTC (rev 317)
+++ code/trunk/ChangeLog 2015-07-20 07:38:06 UTC (rev 318)
@@ -50,7 +50,10 @@
provoke a buffer overflow. This bug was discovered by Karl Skomski with the
LLVM fuzzer.
+14. Fix infinite recursion in the JIT compiler when certain patterns such as
+/(?:|a|){100}x/ are analysed.
+
Version 10.20 30-June-2015
--------------------------
Modified: code/trunk/src/pcre2_jit_compile.c
===================================================================
--- code/trunk/src/pcre2_jit_compile.c 2015-07-17 16:25:21 UTC (rev 317)
+++ code/trunk/src/pcre2_jit_compile.c 2015-07-20 07:38:06 UTC (rev 318)
@@ -3340,7 +3340,7 @@
bytes[0] = len;
}
-static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, sljit_ui *chars, sljit_ub *bytes, int max_chars)
+static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, sljit_ui *chars, sljit_ub *bytes, int max_chars, uint32_t *rec_count)
{
/* Recursive function, which scans prefix literals. */
BOOL last, any, caseless;
@@ -3358,9 +3358,14 @@
repeat = 1;
while (TRUE)
{
+ if (*rec_count == 0)
+ return 0;
+ rec_count--;
+
last = TRUE;
any = FALSE;
caseless = FALSE;
+
switch (*cc)
{
case OP_CHARI:
@@ -3422,7 +3427,7 @@
#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
#endif
- max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars);
+ max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars, rec_count);
if (max_chars == 0)
return consumed;
last = FALSE;
@@ -3445,7 +3450,7 @@
alternative = cc + GET(cc, 1);
while (*alternative == OP_ALT)
{
- max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars);
+ max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars, rec_count);
if (max_chars == 0)
return consumed;
alternative += GET(alternative, 1);
@@ -3690,6 +3695,7 @@
int range_right = -1, range_len = 3 - 1;
sljit_ub *update_table = NULL;
BOOL in_range;
+uint32_t rec_count;
for (i = 0; i < MAX_N_CHARS; i++)
{
@@ -3698,7 +3704,8 @@
bytes[i * MAX_N_BYTES] = 0;
}
-max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS);
+rec_count = 10000;
+max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS, &rec_count);
if (max <= 1)
return FALSE;
Modified: code/trunk/testdata/testinput16
===================================================================
--- code/trunk/testdata/testinput16 2015-07-17 16:25:21 UTC (rev 317)
+++ code/trunk/testdata/testinput16 2015-07-20 07:38:06 UTC (rev 318)
@@ -202,4 +202,6 @@
/(a(?:a|b|c|d|e)b){8,16}/jit=1
+/(?:|a|){100}x/jit=1
+
# End of testinput16
Modified: code/trunk/testdata/testoutput16
===================================================================
--- code/trunk/testdata/testoutput16 2015-07-17 16:25:21 UTC (rev 317)
+++ code/trunk/testdata/testoutput16 2015-07-20 07:38:06 UTC (rev 318)
@@ -381,4 +381,6 @@
/(a(?:a|b|c|d|e)b){8,16}/jit=1
+/(?:|a|){100}x/jit=1
+
# End of testinput16