[core] use stack w/ pcre_exec unless save captures

use stack w/ pcre_exec unless saving captures from config conditions

reduce memory allocations per request where lighttpd.conf does not
contain url.redirect or url.rewrite rules where replacements reference
a match of the enclosing lighttpd.conf condition (e.g. %0, %1, %2 ...)

move cond_cache_t 'patterncount' to cond_match_t 'captures'
While cond_match_t is no longer sized power-2, it is generally expected
to be used much less frequently than before (which was all the time),
since it is now used only with url.redirect or url.rewrite with
references %0, %1, %2, ...
personal/stbuehler/tests-path
Glenn Strauss 2021-11-20 03:29:38 -05:00
parent 3b3574c5e6
commit 6d47d4c699
10 changed files with 16 additions and 33 deletions

View File

@ -642,19 +642,22 @@ void config_cond_cache_reset(request_st * const r) {
static int config_pcre_match(request_st * const r, const data_config * const dc, const buffer * const b) {
#ifdef HAVE_PCRE_H
if (__builtin_expect( (0 == dc->capture_idx), 1)) {
int matches[3 * 10];
return pcre_exec(dc->regex, dc->regex_study, BUF_PTR_LEN(b), 0, 0,
matches, sizeof(matches)/sizeof(*matches));
}
#ifndef elementsof
#define elementsof(x) (sizeof(x) / sizeof(x[0]))
#endif
cond_match_t * const cond_match =
r->cond_match[dc->capture_idx] = r->cond_match_data + dc->capture_idx;
cond_match->comp_value = b; /*holds pointer to b (!) for pattern subst*/
/* Note: patterncount is in cond_cache_t instead of cond_match_t only
* so that both structures are sized power-2 for efficient array access */
cond_cache_t * const cache = &r->cond_cache[dc->context_ndx];
cache->patterncount =
cond_match->captures =
pcre_exec(dc->regex, dc->regex_study, BUF_PTR_LEN(b), 0, 0,
cond_match->matches, elementsof(cond_match->matches));
return cache->patterncount;
return cond_match->captures;
#else
UNUSED(r);
UNUSED(dc);

View File

@ -1229,19 +1229,7 @@ int config_finalize(server *srv, const buffer *default_server_tag) {
}
/* adjust cond_match_data list size if regex config conditions present */
if (srv->config_context->used > 1) {
const data_config *dcrx = NULL;
for (uint32_t i = 1; i < srv->config_context->used; ++i) {
const data_config * const dc =
(data_config *)srv->config_context->data[i];
if ((dc->cond==CONFIG_COND_MATCH || dc->cond==CONFIG_COND_NOMATCH)
&& 0 == dc->capture_idx) {
dcrx = dc;
break;
}
}
if (dcrx || srv->config_captures) ++srv->config_captures;
}
if (srv->config_captures) ++srv->config_captures;
return 1;
}

View File

@ -113,7 +113,7 @@ static void pcre_keyvalue_buffer_append_match(buffer *b, const char **list, int
static void pcre_keyvalue_buffer_append_ctxmatch(buffer *b, const pcre_keyvalue_ctx *ctx, unsigned int num, int flags) {
const struct cond_match_t * const cache = ctx->cache;
if (!cache) return; /* no enclosing match context */
if ((int)num < ctx->cond_match_count) {
if ((int)num < cache->captures) {
const int off = cache->matches[(num <<= 1)]; /*(num *= 2)*/
const int len = cache->matches[num+1] - off;
burl_append(b, cache->comp_value->ptr + off, (size_t)len, flags);

View File

@ -12,7 +12,6 @@ struct pcre_keyvalue; /* declaration */
typedef struct pcre_keyvalue_ctx {
struct cond_match_t *cache;
struct burl_parts_t *burl;
int cond_match_count;
int m;
} pcre_keyvalue_ctx;

View File

@ -243,7 +243,7 @@ static int mod_dirlisting_exclude(pcre_keyvalue_buffer * const kvb, const char *
* must have been configured with empty kvb 'value' during init)*/
buffer input = { NULL, len+1, 0 };
*(const char **)&input.ptr = name;
pcre_keyvalue_ctx ctx = { NULL, NULL, 0, -1 };
pcre_keyvalue_ctx ctx = { NULL, NULL, -1 };
#ifdef __COVERITY__
/*(again, must have been configured w/ empty kvb 'value' during init)*/
struct cond_match_t cache;

View File

@ -169,8 +169,6 @@ URIHANDLER_FUNC(mod_redirect_uri_handler) {
ctx.cache = NULL;
if (p->conf.redirect->x0) { /*(p->conf.redirect->x0 is capture_idx)*/
ctx.cond_match_count =
r->cond_cache[p->conf.redirect->cfgidx].patterncount;
ctx.cache = r->cond_match[p->conf.redirect->x0];
}
ctx.burl = &burl;

View File

@ -291,8 +291,6 @@ static handler_t process_rewrite_rules(request_st * const r, plugin_data *p, con
ctx.cache = NULL;
if (kvb->x0) { /*(kvb->x0 is capture_idx)*/
ctx.cond_match_count =
r->cond_cache[kvb->cfgidx].patterncount;
ctx.cache = r->cond_match[kvb->x0];
}
ctx.burl = &burl;

View File

@ -185,7 +185,7 @@ static int mod_trigger_b4_dl_init_regex(server * const srv, config_plugin_value_
static int mod_trigger_b4_dl_match(pcre_keyvalue_buffer * const kvb, const buffer * const input) {
/*(re-use keyvalue.[ch] for match-only;
* must have been configured with empty kvb 'value' during init)*/
pcre_keyvalue_ctx ctx = { NULL, NULL, 0, -1 };
pcre_keyvalue_ctx ctx = { NULL, NULL, -1 };
#ifdef __COVERITY__
/*(again, must have been configured w/ empty kvb 'value' during init)*/
struct cond_match_t cache;

View File

@ -163,16 +163,13 @@ typedef struct cond_cache_t {
int8_t result; /*(cond_result_t)*/
/* result without preconditions (must never be "skip") */
int8_t local_result; /*(cond_result_t)*/
int16_t patterncount;
} cond_cache_t; /* 8 bytes (2^3) */
} cond_cache_t; /* 2 bytes (2^1) */
typedef struct cond_match_t {
const buffer *comp_value; /* just a pointer */
#if !(defined(_LP64) || defined(__LP64__) || defined(_WIN64)) /*(not 64-bit)*/
int dummy_alignment; /*(for alignment in 32-bit)*/
#endif
int captures;
int matches[3 * 10];
} cond_match_t; /* 128 bytes (2^7) */
} cond_match_t;
int config_check_cond(request_st *r, int context_ndx);

View File

@ -61,10 +61,10 @@ static void test_keyvalue_pcre_keyvalue_buffer_process (void) {
buffer_copy_string_len(scheme, CONST_STR_LEN("http"));
buffer_copy_string_len(authority, CONST_STR_LEN("www.example.com"));
/* model outer conditional match of $HTTP["host"] =~ "^(www).example.com$" */
ctx.cond_match_count = 2;
ctx.cache = &cache;
memset(&cache, 0, sizeof(cache));
cache.comp_value = authority;
cache.captures = 2;
cache.matches[0] = 0;
cache.matches[1] = 15;
cache.matches[2] = 0;