[core] convert simple config cond regex to pre/sfx

convert simple config condition regex to prefix/suffix match
master
Glenn Strauss 10 months ago
parent b3e80a1363
commit dcb5f2318b

@ -1235,6 +1235,43 @@ int config_finalize(server *srv, const buffer *default_server_tag) {
return 0;
}
/* check if condition regex captures are used by modules (redirect,rewrite)
* and convert back to regex if condition was simplified to non-regex by
* configparser_simplify_regex() */
if (__builtin_expect( (srv->config_captures != 0), 0)) {
for (uint32_t i = 1; i < srv->config_context->used; ++i) {
data_config * const dc =
(data_config *)srv->config_context->data[i];
if (__builtin_expect( (0 == dc->capture_idx), 1))
continue;
switch (dc->cond) {
case CONFIG_COND_EQ:
case CONFIG_COND_PREFIX:
case CONFIG_COND_SUFFIX:
break;
/*case CONFIG_COND_NE:*/
/*case CONFIG_COND_MATCH:*/
/*case CONFIG_COND_NOMATCH:*/
/*case CONFIG_COND_ELSE:*/
default:
continue;
}
buffer * const b = &dc->string;
if (dc->cond != CONFIG_COND_SUFFIX || b->ptr[0] == '.') {
buffer_extend(b, 1);
memmove(b->ptr+1, b->ptr, buffer_clen(b)-1);
b->ptr[0] = (dc->cond == CONFIG_COND_SUFFIX) ? '\\' : '^';
}
if (dc->cond != CONFIG_COND_PREFIX)
buffer_append_string_len(b, CONST_STR_LEN("$"));
dc->cond = CONFIG_COND_MATCH;
/*(config_pcre_keyvalue())*/
const int pcre_jit = config_feature_bool(srv, "server.pcre_jit", 1);
if (!data_config_pcre_compile(dc, pcre_jit, srv->errh))
return 0;
}
}
#ifdef HAVE_PCRE2_H
for (uint32_t i = 1; i < srv->config_context->used; ++i) {
data_config * const dc =

@ -177,9 +177,51 @@ configparser_comp_key_id(const buffer * const obj_tag, const buffer * const comp
return COMP_UNSET;
}
static config_cond_t
configparser_simplify_regex(buffer * const b)
{
/* translate simple regex anchored with ^ and/or $ to simpler match types
* (note: skips if regex contains any '\\', even if some could be removed,
* though we special-case "\.ext"; skips if other '.' found in str)
* (currently assumes CONFIG_COND_NOMATCH input, not CONFIG_COND_NOMATCH) */
uint32_t len = buffer_clen(b);
config_cond_t cond = CONFIG_COND_MATCH;
int off = 0;
if (len && b->ptr[len-1] == '$') {
cond = CONFIG_COND_SUFFIX;
if (b->ptr[0] == '\\' && b->ptr[1] == '.')
off = 2;
else if (b->ptr[0] == '^') {
off = 1;
cond = CONFIG_COND_EQ;
}
--len;
}
else if (b->ptr[0] == '^') {
off = 1;
cond = CONFIG_COND_PREFIX;
}
else
return CONFIG_COND_MATCH;
static const char regex_chars[] = "\\^$.|?*+()[]{}";
if (strcspn(b->ptr+off, regex_chars) != len - off)
return CONFIG_COND_MATCH;
if (off) { /*(remove only first char if (off == 2) to keep '.' in "\.")*/
memmove(b->ptr, b->ptr+1, len-1);
--len;
}
buffer_truncate(b, len);
return cond;
}
static void
configparser_parse_condition(config_t * const ctx, const buffer * const obj_tag, const buffer * const comp_tag, const config_cond_t cond, buffer * const rvalue)
configparser_parse_condition(config_t * const ctx, const buffer * const obj_tag, const buffer * const comp_tag, config_cond_t cond, buffer * const rvalue)
{
const comp_key_t comp = configparser_comp_key_id(obj_tag, comp_tag);
if (cond == CONFIG_COND_MATCH && comp != COMP_SERVER_SOCKET)
cond = configparser_simplify_regex(rvalue);
const char *op = NULL;
switch(cond) {
case CONFIG_COND_NE: op = "!="; break;
@ -219,7 +261,7 @@ configparser_parse_condition(config_t * const ctx, const buffer * const obj_tag,
else {
dc = data_config_init();
dc->cond = cond;
dc->comp = configparser_comp_key_id(obj_tag, comp_tag);
dc->comp = comp;
buffer_copy_buffer(&dc->key, tb);
buffer_copy_buffer(&dc->comp_tag, comp_tag);

Loading…
Cancel
Save