From: Jeremy Harris Date: Fri, 10 Jun 2022 10:54:17 +0000 (+0100) Subject: Use pool storage for regex operations X-Git-Tag: exim-4.97-RC0~282^2~9 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/c3d7f28680dda05ca6d8415cffbff8a233c0ae74 Use pool storage for regex operations --- 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));