summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2022-06-10 11:54:17 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2022-06-10 11:57:59 +0100
commitc3d7f28680dda05ca6d8415cffbff8a233c0ae74 (patch)
treed379ccee0ff2115b759796bdffc36c72d84a01d3
parentfa3d5d5f69667c03b990ac90ac5cc90c0b4fcab3 (diff)
downloadexim4-c3d7f28680dda05ca6d8415cffbff8a233c0ae74.tar.gz
Use pool storage for regex operations
-rw-r--r--src/src/exim.c60
-rw-r--r--src/src/expand.c10
-rw-r--r--src/src/filter.c2
-rw-r--r--src/src/globals.c6
-rw-r--r--src/src/globals.h6
-rw-r--r--src/src/malware.c10
-rw-r--r--src/src/regex.c8
-rw-r--r--src/src/transports/appendfile.c8
-rw-r--r--src/src/transports/smtp.c20
-rw-r--r--src/src/transports/tf_maildir.c2
10 files changed, 74 insertions, 58 deletions
diff --git a/src/src/exim.c b/src/src/exim.c
index eac0cb2b9..052c6bf5c 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -59,6 +59,18 @@ if (block) store_free(block);
}
+static void *
+function_store_get(PCRE2_SIZE size, void * tag)
+{
+return store_get((int)size, GET_UNTAINTED); /* loses track of taint */
+}
+
+static void
+function_store_nullfree(void * block, void * tag)
+{
+}
+
+
/*************************************************
@@ -96,19 +108,9 @@ size_t offset;
int options = caseless ? PCRE_COPT|PCRE2_CASELESS : PCRE_COPT;
const pcre2_code * yield;
int err;
-pcre2_general_context * gctx;
-pcre2_compile_context * cctx;
-
-if (use_malloc)
- {
- gctx = pcre2_general_context_create(function_store_malloc, function_store_free, NULL);
- cctx = pcre2_compile_context_create(gctx);
- }
-else
- cctx = pcre_cmp_ctx;
if (!(yield = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, options,
- &err, &offset, cctx)))
+ &err, &offset, use_malloc ? pcre_mlc_cmp_ctx : pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
@@ -116,11 +118,6 @@ if (!(yield = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, options,
"%s at offset %ld while compiling %s", errbuf, (long)offset, pattern);
}
-if (use_malloc)
- {
- pcre2_compile_context_free(cctx);
- pcre2_general_context_free(gctx);
- }
return yield;
}
@@ -128,9 +125,13 @@ return yield;
static void
pcre_init(void)
{
-pcre_gen_ctx = pcre2_general_context_create(function_store_malloc, function_store_free, NULL);
-pcre_cmp_ctx = pcre2_compile_context_create(pcre_gen_ctx);
-pcre_mtc_ctx = pcre2_match_context_create(pcre_gen_ctx);
+pcre_mlc_ctx = pcre2_general_context_create(function_store_malloc, function_store_free, NULL);
+pcre_gen_ctx = pcre2_general_context_create(function_store_get, function_store_nullfree, NULL);
+
+pcre_mlc_cmp_ctx = pcre2_compile_context_create(pcre_mlc_ctx);
+pcre_gen_cmp_ctx = pcre2_compile_context_create(pcre_gen_ctx);
+
+pcre_gen_mtc_ctx = pcre2_match_context_create(pcre_gen_ctx);
}
@@ -160,7 +161,7 @@ regex_match_and_setup(const pcre2_code * re, const uschar * subject, int options
{
pcre2_match_data * md = pcre2_match_data_create_from_pattern(re, pcre_gen_ctx);
int res = pcre2_match(re, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0,
- PCRE_EOPT | options, md, pcre_mtc_ctx);
+ PCRE_EOPT | options, md, pcre_gen_mtc_ctx);
BOOL yield;
if ((yield = (res >= 0)))
@@ -182,7 +183,7 @@ else if (res != PCRE2_ERROR_NOMATCH) DEBUG(D_any)
pcre2_get_error_message(res, errbuf, sizeof(errbuf));
debug_printf_indent("pcre2: %s\n", errbuf);
}
-pcre2_match_data_free(md);
+/* pcre2_match_data_free(md); gen ctx needs no free */
return yield;
}
@@ -204,13 +205,18 @@ regex_match(const pcre2_code * re, const uschar * subject, int slen, uschar ** r
pcre2_match_data * md = pcre2_match_data_create(1, pcre_gen_ctx);
int rc = pcre2_match(re, (PCRE2_SPTR)subject,
slen >= 0 ? slen : PCRE2_ZERO_TERMINATED,
- 0, PCRE_EOPT, md, pcre_mtc_ctx);
+ 0, PCRE_EOPT, md, pcre_gen_mtc_ctx);
PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
-if (rc < 0)
- return FALSE;
-if (rptr)
- *rptr = string_copyn(subject + ovec[0], ovec[1] - ovec[0]);
-return TRUE;
+BOOL ret = FALSE;
+
+if (rc >= 0)
+ {
+ if (rptr)
+ *rptr = string_copyn(subject + ovec[0], ovec[1] - ovec[0]);
+ ret = TRUE;
+ }
+/* pcre2_match_data_free(md); gen ctx needs no free */
+return ret;
}
diff --git a/src/src/expand.c b/src/src/expand.c
index 744ab4d0b..03ae3206e 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -2949,7 +2949,7 @@ switch(cond_type = identify_operator(&s, &opname))
int err;
if (!(re = pcre2_compile((PCRE2_SPTR)sub[1], PCRE2_ZERO_TERMINATED,
- PCRE_COPT, &err, &offset, pcre_cmp_ctx)))
+ PCRE_COPT, &err, &offset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
@@ -3444,7 +3444,7 @@ switch(cond_type = identify_operator(&s, &opname))
TRUE, FALSE);
md = pcre2_match_data_create(4+1, pcre_gen_ctx);
if (pcre2_match(re, sub[0], PCRE2_ZERO_TERMINATED, 0, PCRE_EOPT,
- md, pcre_mtc_ctx) < 0)
+ md, pcre_gen_mtc_ctx) < 0)
{
DEBUG(D_expand) debug_printf("no match for SRS'd local-part pattern\n");
goto srs_result;
@@ -3521,6 +3521,7 @@ switch(cond_type = identify_operator(&s, &opname))
boolvalue = TRUE;
srs_result:
+ /* pcre2_match_data_free(md); gen ctx needs no free */
if (yield) *yield = (boolvalue == testfor);
return s;
}
@@ -5899,7 +5900,7 @@ while (*s)
/* Compile the regular expression */
if (!(re = pcre2_compile((PCRE2_SPTR)sub[1], PCRE2_ZERO_TERMINATED,
- PCRE_COPT, &err, &roffset, pcre_cmp_ctx)))
+ PCRE_COPT, &err, &roffset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
@@ -5922,7 +5923,7 @@ while (*s)
{
PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
int n = pcre2_match(re, (PCRE2_SPTR)subject, slen, moffset + moffsetextra,
- PCRE_EOPT | emptyopt, md, pcre_mtc_ctx);
+ PCRE_EOPT | emptyopt, md, pcre_gen_mtc_ctx);
uschar * insert;
/* No match - if we previously set PCRE_NOTEMPTY after a null match, this
@@ -5984,6 +5985,7 @@ while (*s)
/* All done - restore numerical variables. */
+ /* pcre2_match_data_free(md); gen ctx needs no free */
restore_expand_strings(save_expand_nmax, save_expand_nstring,
save_expand_nlength);
break;
diff --git a/src/src/filter.c b/src/src/filter.c
index ad017e567..a3e31a3b5 100644
--- a/src/src/filter.c
+++ b/src/src/filter.c
@@ -1599,7 +1599,7 @@ switch (c->type)
if (!(re = pcre2_compile((PCRE2_SPTR)exp[1], PCRE2_ZERO_TERMINATED,
PCRE_COPT | (c->type == cond_matches ? PCRE2_CASELESS : 0),
- &err, &offset, pcre_cmp_ctx)))
+ &err, &offset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
diff --git a/src/src/globals.c b/src/src/globals.c
index 18988e9da..62c9b2659 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1209,8 +1209,10 @@ uschar *override_pid_file_path = NULL;
BOOL panic_coredump = FALSE;
pcre2_general_context * pcre_gen_ctx = NULL;
-pcre2_compile_context * pcre_cmp_ctx = NULL;
-pcre2_match_context * pcre_mtc_ctx = NULL;
+pcre2_compile_context * pcre_gen_cmp_ctx = NULL;
+pcre2_match_context * pcre_gen_mtc_ctx = NULL;
+pcre2_general_context * pcre_mlc_ctx = NULL;
+pcre2_compile_context * pcre_mlc_cmp_ctx = NULL;
uschar *percent_hack_domains = NULL;
uschar *pid_file_path = US PID_FILE_PATH
diff --git a/src/src/globals.h b/src/src/globals.h
index ca5b0ccc9..0f0471101 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -794,8 +794,10 @@ extern uschar *override_pid_file_path; /* Value of -oP argument */
extern BOOL panic_coredump; /* SEGV rather than exit, on LOG_PANIC_DIE */
extern pcre2_general_context * pcre_gen_ctx; /* pcre memory management */
-extern pcre2_compile_context * pcre_cmp_ctx;
-extern pcre2_match_context * pcre_mtc_ctx;
+extern pcre2_compile_context * pcre_gen_cmp_ctx;
+extern pcre2_match_context * pcre_gen_mtc_ctx;
+extern pcre2_general_context * pcre_mlc_ctx;
+extern pcre2_compile_context * pcre_mlc_cmp_ctx;
extern uschar *percent_hack_domains; /* Local domains for which '% operates */
extern uschar *pid_file_path; /* For writing daemon pids */
diff --git a/src/src/malware.c b/src/src/malware.c
index 4719a5d61..976438511 100644
--- a/src/src/malware.c
+++ b/src/src/malware.c
@@ -306,7 +306,7 @@ PCRE2_SIZE roffset;
const pcre2_code * cre;
if (!(cre = pcre2_compile((PCRE2_SPTR)re, PCRE2_ZERO_TERMINATED,
- PCRE_COPT, &err, &roffset, pcre_cmp_ctx)))
+ PCRE_COPT, &err, &roffset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
@@ -320,12 +320,13 @@ uschar *
m_pcre_exec(const pcre2_code * cre, uschar * text)
{
pcre2_match_data * md = pcre2_match_data_create(2, pcre_gen_ctx);
-int i = pcre2_match(cre, text, PCRE2_ZERO_TERMINATED, 0, 0, md, pcre_mtc_ctx);
+int i = pcre2_match(cre, text, PCRE2_ZERO_TERMINATED, 0, 0, md, pcre_gen_mtc_ctx);
PCRE2_UCHAR * substr = NULL;
PCRE2_SIZE slen;
if (i >= 2) /* Got it */
- pcre2_substring_get_bynumber(md, 1, &substr, &slen);
+ pcre2_substring_get_bynumber(md, 1, &substr, &slen); /* uses same ctx as md */
+/* pcre2_match_data_free(md); gen ctx needs no free */
return US substr;
}
@@ -945,7 +946,7 @@ badseek: err = errno;
/* try matcher on the line, grab substring */
result = pcre2_match(drweb_re, (PCRE2_SPTR)tmpbuf, PCRE2_ZERO_TERMINATED,
- 0, 0, md, pcre_mtc_ctx);
+ 0, 0, md, pcre_gen_mtc_ctx);
if (result >= 2)
{
PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
@@ -959,6 +960,7 @@ badseek: err = errno;
g = string_catn(g, US ovec[2], ovec[3] - ovec[2]);
}
}
+ /* pcre2_match_data_free(md); gen ctx needs no free */
}
malware_name = string_from_gstring(g);
}
diff --git a/src/src/regex.c b/src/src/regex.c
index 5c0f7c4e0..9b7b07405 100644
--- a/src/src/regex.c
+++ b/src/src/regex.c
@@ -46,7 +46,7 @@ while ((regex_string = string_nextinlist(&list, &sep, NULL, 0)))
/* compile our regular expression */
if (!(re = pcre2_compile( (PCRE2_SPTR) regex_string, PCRE2_ZERO_TERMINATED,
- 0, &err, &pcre_erroffset, pcre_cmp_ctx)))
+ 0, &err, &pcre_erroffset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
@@ -75,7 +75,7 @@ for (pcre_list * ri = re_list_head; ri; ri = ri->next)
int n;
/* try matcher on the line */
- if ((n = pcre2_match(ri->re, (PCRE2_SPTR)linebuffer, len, 0, 0, md, pcre_mtc_ctx)) > 0)
+ if ((n = pcre2_match(ri->re, (PCRE2_SPTR)linebuffer, len, 0, 0, md, pcre_gen_mtc_ctx)) > 0)
{
Ustrncpy(regex_match_string_buffer, ri->pcre_text,
sizeof(regex_match_string_buffer)-1);
@@ -85,14 +85,14 @@ for (pcre_list * ri = re_list_head; ri; ri = ri->next)
{
PCRE2_UCHAR * cstr;
PCRE2_SIZE cslen;
- pcre2_substring_get_bynumber(md, nn, &cstr, &cslen);
+ pcre2_substring_get_bynumber(md, nn, &cstr, &cslen); /* uses same ctx as md */
regex_vars[nn-1] = CUS cstr;
}
return OK;
}
}
-pcre2_match_data_free(md);
+/* pcre2_match_data_free(md); gen ctx needs no free */
return FAIL;
}
diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c
index 93281efda..600fb6125 100644
--- a/src/src/transports/appendfile.c
+++ b/src/src/transports/appendfile.c
@@ -681,7 +681,7 @@ for (struct dirent *ent; ent = readdir(dir); )
{
pcre2_match_data * md = pcre2_match_data_create(2, pcre_gen_ctx);
int rc = pcre2_match(re, (PCRE2_SPTR)name, PCRE2_ZERO_TERMINATED,
- 0, 0, md, pcre_mtc_ctx);
+ 0, 0, md, pcre_gen_mtc_ctx);
PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
if ( rc >= 0
&& (rc = pcre2_get_ovector_count(md)) >= 2)
@@ -694,9 +694,11 @@ for (struct dirent *ent; ent = readdir(dir); )
DEBUG(D_transport)
debug_printf("check_dir_size: size from %s is " OFF_T_FMT "\n", name,
size);
+ /* pcre2_match_data_free(md); gen ctx needs no free */
continue;
}
}
+ /* pcre2_match_data_free(md); gen ctx needs no free */
DEBUG(D_transport)
debug_printf("check_dir_size: regex did not match %s\n", name);
}
@@ -2219,7 +2221,7 @@ else
if (ob->quota_size_regex)
{
if (!(re = pcre2_compile((PCRE2_SPTR)ob->quota_size_regex,
- PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_cmp_ctx)))
+ PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
@@ -2308,7 +2310,7 @@ else
int check_path_len = Ustrlen(check_path);
if (!(dir_regex = pcre2_compile((PCRE2_SPTR)ob->maildir_dir_regex,
- PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_cmp_ctx)))
+ PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index 7f529b7ca..4450d948d 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1849,57 +1849,57 @@ pcre2_match_data * md = pcre2_match_data_create(1, pcre_gen_ctx);
#ifndef DISABLE_TLS
if ( checks & OPTION_TLS
&& pcre2_match(regex_STARTTLS,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
#endif
checks &= ~OPTION_TLS;
if ( checks & OPTION_IGNQ
&& pcre2_match(regex_IGNOREQUOTA,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
checks &= ~OPTION_IGNQ;
if ( checks & OPTION_CHUNKING
&& pcre2_match(regex_CHUNKING,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
checks &= ~OPTION_CHUNKING;
#ifndef DISABLE_PRDR
if ( checks & OPTION_PRDR
&& pcre2_match(regex_PRDR,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
#endif
checks &= ~OPTION_PRDR;
#ifdef SUPPORT_I18N
if ( checks & OPTION_UTF8
&& pcre2_match(regex_UTF8,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
#endif
checks &= ~OPTION_UTF8;
if ( checks & OPTION_DSN
&& pcre2_match(regex_DSN,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
checks &= ~OPTION_DSN;
if ( checks & OPTION_PIPE
&& pcre2_match(regex_PIPELINING,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
checks &= ~OPTION_PIPE;
if ( checks & OPTION_SIZE
&& pcre2_match(regex_SIZE,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
checks &= ~OPTION_SIZE;
#ifndef DISABLE_PIPE_CONNECT
if ( checks & OPTION_EARLY_PIPE
&& pcre2_match(regex_EARLY_PIPE,
- (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_mtc_ctx) < 0)
+ (PCRE2_SPTR)buf, bsize, 0, PCRE_EOPT, md, pcre_gen_mtc_ctx) < 0)
#endif
checks &= ~OPTION_EARLY_PIPE;
-pcre2_match_data_free(md);
+/* pcre2_match_data_free(md); gen ctx needs no free */
/* debug_printf("%s: found 0x%04x\n", __FUNCTION__, checks); */
return checks;
}
diff --git a/src/src/transports/tf_maildir.c b/src/src/transports/tf_maildir.c
index a83fc6f09..6bff1eb69 100644
--- a/src/src/transports/tf_maildir.c
+++ b/src/src/transports/tf_maildir.c
@@ -149,7 +149,7 @@ if (maildirfolder_create_regex)
DEBUG(D_transport) debug_printf("checking for maildirfolder requirement\n");
if (!(re = pcre2_compile((PCRE2_SPTR)maildirfolder_create_regex,
- PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_cmp_ctx)))
+ PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_gen_cmp_ctx)))
{
uschar errbuf[128];
pcre2_get_error_message(err, errbuf, sizeof(errbuf));