diff --git a/src/configfile-glue.c b/src/configfile-glue.c index 7602e419..e5403626 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -687,16 +687,18 @@ static int config_pcre_match(request_st * const r, const data_config * const dc, matches, sizeof(matches)/sizeof(*matches)); } - #ifndef elementsof - #define elementsof(x) (sizeof(x) / sizeof(x[0])) - #endif const int capture_offset = dc->capture_idx - 1; cond_match_t * const cond_match = r->cond_match[capture_offset] = r->cond_match_data + capture_offset; + if (__builtin_expect( (NULL == cond_match->matches), 0)) { + /*(allocate on demand)*/ + cond_match->matches = malloc(dc->ovec_nelts * sizeof(int *)); + force_assert(cond_match->matches); + } cond_match->comp_value = b; /*holds pointer to b (!) for pattern subst*/ cond_match->captures = pcre_exec(dc->regex, dc->regex_study, BUF_PTR_LEN(b), 0, 0, - cond_match->matches, elementsof(cond_match->matches)); + cond_match->matches, dc->ovec_nelts); return cond_match->captures; #else diff --git a/src/configfile.h b/src/configfile.h index a181ee72..794fc936 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -41,6 +41,7 @@ struct data_config { #elif defined(HAVE_PCRE_H) void *regex; struct pcre_extra *regex_study; + int ovec_nelts; #endif int capture_idx; int ext; diff --git a/src/data_config.c b/src/data_config.c index 56c3a416..f8cacb97 100644 --- a/src/data_config.c +++ b/src/data_config.c @@ -166,6 +166,7 @@ int data_config_pcre_compile(data_config * const dc, const int pcre_jit, log_err dc->string.ptr); return 0; } + dc->ovec_nelts = 3 * (captures + 1); return 1; #else diff --git a/src/plugin_config.h b/src/plugin_config.h index f61646c9..f4e4e452 100644 --- a/src/plugin_config.h +++ b/src/plugin_config.h @@ -173,12 +173,9 @@ typedef struct cond_match_t { const buffer *comp_value; /* just a pointer */ #ifdef HAVE_PCRE2_H struct pcre2_real_match_data_8 *match_data; - int captures; - void *matches; /* (PCRE2_SIZE *) */ - #elif defined(HAVE_PCRE_H) - int captures; - int matches[3 * 10]; #endif + int captures; + void *matches; /* pcre2:(PCRE2_SIZE *), pcre:(int *) */ } cond_match_t; int config_check_cond(request_st *r, int context_ndx); diff --git a/src/reqpool.c b/src/reqpool.c index 9ffc1ddd..aca37a4d 100644 --- a/src/reqpool.c +++ b/src/reqpool.c @@ -232,12 +232,15 @@ request_free_data (request_st * const r) free(r->cond_cache); #ifdef HAVE_PCRE if (r->cond_match_data) { - #ifdef HAVE_PCRE2_H for (int i = 0, used = r->con->srv->config_captures; i < used; ++i) { + #ifdef HAVE_PCRE2_H if (r->cond_match_data[i].match_data) pcre2_match_data_free(r->cond_match_data[i].match_data); + #else /* HAVE_PCRE_H */ + if (r->cond_match_data[i].matches) + free(r->cond_match_data[i].matches); + #endif } - #endif free(r->cond_match_data); free(r->cond_match); } diff --git a/src/t/test_keyvalue.c b/src/t/test_keyvalue.c index 57c8bcd3..0c63e437 100644 --- a/src/t/test_keyvalue.c +++ b/src/t/test_keyvalue.c @@ -67,12 +67,14 @@ static void test_keyvalue_pcre_keyvalue_buffer_process (void) { cache.captures = 2; #ifdef HAVE_PCRE2_H PCRE2_SIZE matches[4]; - cache.matches = matches; + #else /* HAVE_PCRE_H */ + int matches[4]; #endif - cache.matches[0] = 0; - cache.matches[1] = 15; - cache.matches[2] = 0; - cache.matches[3] = 3; + matches[0] = 0; + matches[1] = 15; + matches[2] = 0; + matches[3] = 3; + cache.matches = matches; /* converted from prior sparse tests/mod-redirect.t and tests/mod-rewrite.t * (real-world use should prefer ${url.path} and ${qsa} in substitutions)