Revision: 677
http://vcs.pcre.org/viewvc?view=rev&revision=677
Author: ph10
Date: 2011-08-28 11:50:07 +0100 (Sun, 28 Aug 2011)
Log Message:
-----------
Adjust JIT limit code; make JIT test return 1 if not successful.
Modified Paths:
--------------
code/trunk/pcre_exec.c
code/trunk/pcre_internal.h
code/trunk/pcre_jit_compile.c
code/trunk/pcre_jit_test.c
Modified: code/trunk/pcre_exec.c
===================================================================
--- code/trunk/pcre_exec.c 2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_exec.c 2011-08-28 10:50:07 UTC (rev 677)
@@ -5844,8 +5844,9 @@
&& extra_data->executable_jit != NULL
&& (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL |
PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART)) == 0)
- return _pcre_jit_exec(re, extra_data->executable_jit, subject, length,
- start_offset, options, offsets, offsetcount);
+ return _pcre_jit_exec(re, extra_data->executable_jit, subject, length,
+ start_offset, options, ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0)
+ ? MATCH_LIMIT : extra_data->match_limit, offsets, offsetcount);
#endif
/* Carry on with non-JIT matching. This information is for finding all the
Modified: code/trunk/pcre_internal.h
===================================================================
--- code/trunk/pcre_internal.h 2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_internal.h 2011-08-28 10:50:07 UTC (rev 677)
@@ -1944,7 +1944,7 @@
#ifdef SUPPORT_JIT
extern void _pcre_jit_compile(const real_pcre *, pcre_extra *);
extern int _pcre_jit_exec(const real_pcre *, void *, PCRE_SPTR,
- int, int, int, int *, int);
+ int, int, int, int, int *, int);
extern void _pcre_jit_free(void *);
#endif
Modified: code/trunk/pcre_jit_compile.c
===================================================================
--- code/trunk/pcre_jit_compile.c 2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_jit_compile.c 2011-08-28 10:50:07 UTC (rev 677)
@@ -152,6 +152,7 @@
uschar *ptr;
/* Everything else after. */
int offsetcount;
+ int calllimit;
uschar notbol;
uschar noteol;
uschar notempty;
@@ -280,6 +281,7 @@
recurse_entry *entries;
recurse_entry *currententry;
jump_list *accept;
+ jump_list *calllimit;
jump_list *stackalloc;
jump_list *revertframes;
jump_list *wordboundary;
@@ -355,15 +357,19 @@
#define LOCALS_HEAD (4 * sizeof(sljit_w))
/* Head of the last recursion. */
#define RECURSIVE_HEAD (5 * sizeof(sljit_w))
+/* Number of recursions. */
+#define CALL_COUNT (6 * sizeof(sljit_w))
+/* Max limit of recursions. */
+#define CALL_LIMIT (7 * sizeof(sljit_w))
/* Last known position of the requested byte. */
-#define REQ_BYTE_PTR (6 * sizeof(sljit_w))
+#define REQ_BYTE_PTR (8 * sizeof(sljit_w))
/* End pointer of the first line. */
-#define FIRSTLINE_END (7 * sizeof(sljit_w))
+#define FIRSTLINE_END (9 * sizeof(sljit_w))
/* The output vector is stored on the stack, and contains pointers
to characters. The vector data is divided into two groups: the first
group contains the start / end character pointers, and the second is
the start pointers when the end of the capturing group has not yet reached. */
-#define OVECTOR_START (8 * sizeof(sljit_w))
+#define OVECTOR_START (10 * sizeof(sljit_w))
#define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
#define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
#define PRIV(cc) (common->localptrs[(cc) - common->start])
@@ -1175,6 +1181,14 @@
common->stubs = NULL;
}
+static SLJIT_INLINE void decrease_call_count(compiler_common *common)
+{
+DEFINE_COMPILER;
+
+OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_COUNT, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_COUNT, SLJIT_IMM, 1);
+add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
+}
+
static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
{
/* May destroy all locals and registers except TMP2. */
@@ -3455,6 +3469,8 @@
JUMPHERE(zerolength);
FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
+
+ decrease_call_count(common);
return cc;
}
@@ -3492,6 +3508,8 @@
if (jump != NULL)
JUMPHERE(jump);
JUMPHERE(zerolength);
+
+decrease_call_count(common);
return cc;
}
@@ -4212,6 +4230,9 @@
/* Continue to the normal fallback. */
}
+if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
+ decrease_call_count(common);
+
/* Skip the other alternatives. */
while (*cc == OP_ALT)
cc += GET(cc, 1);
@@ -4436,6 +4457,7 @@
/* None of them matched. */
set_jumps(emptymatch, LABEL());
+decrease_call_count(common);
return cc + 1 + LINK_SIZE;
}
@@ -4696,6 +4718,7 @@
break;
}
+decrease_call_count(common);
return end;
}
@@ -4939,6 +4962,8 @@
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
}
FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();
+ if (cc[1] > OP_ASSERTBACK_NOT)
+ decrease_call_count(common);
break;
case OP_ONCE:
@@ -5969,6 +5994,7 @@
common->entries = NULL;
common->currententry = NULL;
common->accept = NULL;
+common->calllimit = NULL;
common->stackalloc = NULL;
common->revertframes = NULL;
common->wordboundary = NULL;
@@ -6025,8 +6051,10 @@
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
+OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0);
/* Main part of the matching */
if ((re->options & PCRE_ANCHORED) == 0)
@@ -6043,8 +6071,11 @@
if ((re->flags & PCRE_REQCHSET) != 0)
reqbyte_notfound = search_requested_char(common, re->req_byte, (re->flags & PCRE_FIRSTSET) != 0);
+OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT);
/* Store the current STR_PTR in OVECTOR(0). */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
+/* Copy the limit of allowed recursions. */
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_COUNT, TMP1, 0);
compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
@@ -6171,6 +6202,11 @@
OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
JUMPTO(SLJIT_JUMP, leave);
+/* Call limit reached. */
+set_jumps(common->calllimit, LABEL());
+OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
+JUMPTO(SLJIT_JUMP, leave);
+
if (common->revertframes != NULL)
{
set_jumps(common->revertframes, LABEL());
@@ -6268,8 +6304,8 @@
int
_pcre_jit_exec(const real_pcre *re, void *executable_func,
- PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
- int offsetcount)
+ PCRE_SPTR subject, int length, int start_offset, int options,
+ int match_limit, int *offsets, int offsetcount)
{
executable_function *function = (executable_function*)executable_func;
union {
@@ -6285,6 +6321,7 @@
arguments.str = subject + start_offset;
arguments.begin = subject;
arguments.end = subject + length;
+arguments.calllimit = match_limit; /* JIT decreases this value less times. */
arguments.notbol = (options & PCRE_NOTBOL) != 0;
arguments.noteol = (options & PCRE_NOTEOL) != 0;
arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
Modified: code/trunk/pcre_jit_test.c
===================================================================
--- code/trunk/pcre_jit_test.c 2011-08-27 15:53:04 UTC (rev 676)
+++ code/trunk/pcre_jit_test.c 2011-08-28 10:50:07 UTC (rev 677)
@@ -60,12 +60,11 @@
*/
static void setstack(pcre_extra *extra);
-static void regression_tests(void);
+static int regression_tests(void);
int main(void)
{
- regression_tests();
- return 0;
+ return regression_tests();
}
static pcre_jit_stack* callback(void *arg)
@@ -567,12 +566,20 @@
/* Deep recursion. */
{ MUA, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " },
- { MUA, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aaa+ " },
+ { MUA, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aa+ " },
+ { MUA, 0, "((a?)+)+b", "aaaaaaaaaaaaa b" },
+
+ /* Deep recursion: Stack limit reached. */
+ { MA, 0, "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaa" },
+ { MA, 0, "(?:a+)+b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },
+ { MA, 0, "(?:a+?)+?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },
+ { MA, 0, "(?:a*)*b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },
+ { MA, 0, "(?:a*?)*?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" },
{ 0, 0, NULL, NULL }
};
-static void regression_tests(void)
+static int regression_tests(void)
{
pcre *re;
struct regression_test_case *current = regression_test_cases;
@@ -659,10 +666,13 @@
succesful++;
}
- if (total == succesful)
+ if (total == succesful) {
printf("\nAll JIT regression tests are successfully passed.\n");
- else
+ return 0;
+ } else {
printf("\nSuccessful test ratio: %d%%\n", succesful * 100 / total);
+ return 1;
+ }
}
/* End of pcre_jit_test.c */