diff options
author | Zev Weiss <zev@bewilderbeest.net> | 2016-12-25 02:57:09 -0600 |
---|---|---|
committer | Jim Meyering <meyering@fb.com> | 2016-12-25 10:41:38 +0100 |
commit | 31a5e0f4f7c365bbad1436f97e684254886f42a3 (patch) | |
tree | b79756c59562f8b7d3bbd5ae445e5ac464af8901 /src/pcresearch.c | |
parent | 96848ac6c02f596aa542fca769c7b7aeea446ab4 (diff) | |
download | grep-31a5e0f4f7c365bbad1436f97e684254886f42a3.tar.gz |
pcresearch: thread safety
* src/pcresearch.c (pcre_comp): New struct to hold previously-global
state.
(jit_exec): Operate on a pcre_comp parameter instead of global state.
(Pcompile): Allocate and return a pcre_comp instead of setting global
variables.
(Pexecute): Operate on a pcre_comp parameter instead of global state.
Diffstat (limited to 'src/pcresearch.c')
-rw-r--r-- | src/pcresearch.c | 88 |
1 files changed, 47 insertions, 41 deletions
diff --git a/src/pcresearch.c b/src/pcresearch.c index 54d9430a..5bc9328d 100644 --- a/src/pcresearch.c +++ b/src/pcresearch.c @@ -29,48 +29,57 @@ in pcre_exec. */ enum { NSUB = 300 }; -/* Compiled internal form of a Perl regular expression. */ -static pcre *cre; - -/* Additional information about the pattern. */ -static pcre_extra *extra; - # ifndef PCRE_STUDY_JIT_COMPILE # define PCRE_STUDY_JIT_COMPILE 0 # endif +struct pcre_comp +{ + /* Compiled internal form of a Perl regular expression. */ + pcre *cre; + + /* Additional information about the pattern. */ + pcre_extra *extra; + # if PCRE_STUDY_JIT_COMPILE -/* Maximum size of the JIT stack. */ -static int jit_stack_size; + /* Maximum size of the JIT stack. */ + int jit_stack_size; # endif + /* Table, indexed by ! (flag & PCRE_NOTBOL), of whether the empty + string matches when that flag is used. */ + int empty_match[2]; + + pcre_jit_stack *jit_stack; +}; + + /* Match the already-compiled PCRE pattern against the data in SUBJECT, of size SEARCH_BYTES and starting with offset SEARCH_OFFSET, with options OPTIONS, and storing resulting matches into SUB. Return the (nonnegative) match location or a (negative) error number. */ static int -jit_exec (char const *subject, int search_bytes, int search_offset, - int options, int *sub) +jit_exec (struct pcre_comp *pc, char const *subject, int search_bytes, + int search_offset, int options, int *sub) { while (true) { - int e = pcre_exec (cre, extra, subject, search_bytes, search_offset, - options, sub, NSUB); + int e = pcre_exec (pc->cre, pc->extra, subject, search_bytes, + search_offset, options, sub, NSUB); # if PCRE_STUDY_JIT_COMPILE if (e == PCRE_ERROR_JIT_STACKLIMIT - && 0 < jit_stack_size && jit_stack_size <= INT_MAX / 2) + && 0 < pc->jit_stack_size && pc->jit_stack_size <= INT_MAX / 2) { - int old_size = jit_stack_size; - int new_size = jit_stack_size = old_size * 2; - static pcre_jit_stack *jit_stack; - if (jit_stack) - pcre_jit_stack_free (jit_stack); - jit_stack = pcre_jit_stack_alloc (old_size, new_size); - if (!jit_stack) + int old_size = pc->jit_stack_size; + int new_size = pc->jit_stack_size = old_size * 2; + if (pc->jit_stack) + pcre_jit_stack_free (pc->jit_stack); + pc->jit_stack = pcre_jit_stack_alloc (old_size, new_size); + if (!pc->jit_stack) die (EXIT_TROUBLE, 0, _("failed to allocate memory for the PCRE JIT stack")); - pcre_assign_jit_stack (extra, NULL, jit_stack); + pcre_assign_jit_stack (pc->extra, NULL, pc->jit_stack); continue; } # endif @@ -81,12 +90,6 @@ jit_exec (char const *subject, int search_bytes, int search_offset, #endif -#if HAVE_LIBPCRE -/* Table, indexed by ! (flag & PCRE_NOTBOL), of whether the empty - string matches when that flag is used. */ -static int empty_match[2]; -#endif - void * Pcompile (char const *pattern, size_t size, reg_syntax_t ignored) { @@ -109,6 +112,7 @@ Pcompile (char const *pattern, size_t size, reg_syntax_t ignored) char *n = re; char const *p; char const *pnul; + struct pcre_comp *pc = xcalloc (1, sizeof (*pc)); if (localeinfo.multibyte) { @@ -151,32 +155,33 @@ Pcompile (char const *pattern, size_t size, reg_syntax_t ignored) if (match_lines) strcpy (n, xsuffix); - cre = pcre_compile (re, flags, &ep, &e, pcre_maketables ()); - if (!cre) + pc->cre = pcre_compile (re, flags, &ep, &e, pcre_maketables ()); + if (!pc->cre) die (EXIT_TROUBLE, 0, "%s", ep); - extra = pcre_study (cre, PCRE_STUDY_JIT_COMPILE, &ep); + pc->extra = pcre_study (pc->cre, PCRE_STUDY_JIT_COMPILE, &ep); if (ep) die (EXIT_TROUBLE, 0, "%s", ep); # if PCRE_STUDY_JIT_COMPILE - if (pcre_fullinfo (cre, extra, PCRE_INFO_JIT, &e)) + if (pcre_fullinfo (pc->cre, pc->extra, PCRE_INFO_JIT, &e)) die (EXIT_TROUBLE, 0, _("internal error (should never happen)")); /* The PCRE documentation says that a 32 KiB stack is the default. */ if (e) - jit_stack_size = 32 << 10; + pc->jit_stack_size = 32 << 10; # endif free (re); int sub[NSUB]; - empty_match[false] = pcre_exec (cre, extra, "", 0, 0, - PCRE_NOTBOL, sub, NSUB); - empty_match[true] = pcre_exec (cre, extra, "", 0, 0, 0, sub, NSUB); -#endif /* HAVE_LIBPCRE */ + pc->empty_match[false] = pcre_exec (pc->cre, pc->extra, "", 0, 0, + PCRE_NOTBOL, sub, NSUB); + pc->empty_match[true] = pcre_exec (pc->cre, pc->extra, "", 0, 0, 0, sub, + NSUB); - return NULL; + return pc; +#endif /* HAVE_LIBPCRE */ } size_t @@ -193,6 +198,7 @@ Pexecute (void *vcp, char const *buf, size_t size, size_t *match_size, char const *line_start = buf; int e = PCRE_ERROR_NOMATCH; char const *line_end; + struct pcre_comp *pc = vcp; /* The search address to pass to pcre_exec. This is the start of the buffer, or just past the most-recently discovered encoding @@ -228,7 +234,7 @@ Pexecute (void *vcp, char const *buf, size_t size, size_t *match_size, if (p == line_end) { sub[0] = sub[1] = search_offset; - e = empty_match[bol]; + e = pc->empty_match[bol]; break; } @@ -236,7 +242,7 @@ Pexecute (void *vcp, char const *buf, size_t size, size_t *match_size, if (!bol) options |= PCRE_NOTBOL; - e = jit_exec (subject, line_end - subject, search_offset, + e = jit_exec (pc, subject, line_end - subject, search_offset, options, sub); if (e != PCRE_ERROR_BADUTF8) break; @@ -251,10 +257,10 @@ Pexecute (void *vcp, char const *buf, size_t size, size_t *match_size, This optimization is valid if VALID_BYTES is zero, which means SEARCH_OFFSET is also zero. */ sub[1] = 0; - e = empty_match[bol]; + e = pc->empty_match[bol]; } else - e = jit_exec (subject, valid_bytes, search_offset, + e = jit_exec (pc, subject, valid_bytes, search_offset, options | PCRE_NO_UTF8_CHECK | PCRE_NOTEOL, sub); if (e != PCRE_ERROR_NOMATCH) |