summaryrefslogtreecommitdiff
path: root/src/pcresearch.c
diff options
context:
space:
mode:
authorZev Weiss <zev@bewilderbeest.net>2016-12-25 02:57:09 -0600
committerJim Meyering <meyering@fb.com>2016-12-25 10:41:38 +0100
commit31a5e0f4f7c365bbad1436f97e684254886f42a3 (patch)
treeb79756c59562f8b7d3bbd5ae445e5ac464af8901 /src/pcresearch.c
parent96848ac6c02f596aa542fca769c7b7aeea446ab4 (diff)
downloadgrep-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.c88
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)