[core] extend pcre_keyvalue_ctx to pass more state

extend pcre_keyvalue_ctx to pass internal state
personal/stbuehler/tests-path
Glenn Strauss 2021-11-21 00:47:35 -05:00
parent 6d47d4c699
commit 7db817c59a
4 changed files with 30 additions and 22 deletions

View File

@ -91,8 +91,8 @@ int pcre_keyvalue_buffer_append(log_error_st *errh, pcre_keyvalue_buffer *kvb, c
void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb) {
#ifdef HAVE_PCRE_H
for (uint32_t i = 0; i < kvb->used; ++i) {
pcre_keyvalue * const kv = kvb->kv+i;
pcre_keyvalue *kv = kvb->kv;
for (int i = 0, used = (int)kvb->used; i < used; ++i, ++kv) {
if (kv->key) pcre_free(kv->key);
if (kv->key_extra) pcre_free_study(kv->key_extra);
/*free (kv->value.ptr);*//*(see pcre_keyvalue_buffer_append)*/
@ -104,23 +104,27 @@ void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb) {
}
#ifdef HAVE_PCRE_H
static void pcre_keyvalue_buffer_append_match(buffer *b, const char **list, int n, unsigned int num, int flags) {
if (num < (unsigned int)n) { /* n is always > 0 */
burl_append(b, list[num], strlen(list[num]), flags);
static void pcre_keyvalue_buffer_append_match(buffer *b, const pcre_keyvalue_ctx *ctx, unsigned int num, int flags) {
if (num < (unsigned int)ctx->n) { /* n is always > 0 */
const int *ovec = (int *)ctx->ovec;
const size_t off = (size_t)ovec[(num <<= 1)]; /*(num *= 2)*/
const size_t len = (size_t)ovec[num+1] - off;
burl_append(b, ctx->subject + off, len, flags);
}
}
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 < 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);
if (num < (unsigned int)cache->captures) {
const int *ovec = (int *)cache->matches;
const size_t off = (size_t)ovec[(num <<= 1)]; /*(num *= 2)*/
const size_t len = (size_t)ovec[num+1] - off;
burl_append(b, cache->comp_value->ptr + off, len, flags);
}
}
static int pcre_keyvalue_buffer_subst_ext(buffer *b, const char *pattern, const char **list, int n, const pcre_keyvalue_ctx *ctx) {
static int pcre_keyvalue_buffer_subst_ext(buffer *b, const char *pattern, const pcre_keyvalue_ctx *ctx) {
const unsigned char *p = (unsigned char *)pattern+2;/* +2 past ${} or %{} */
int flags = 0;
while (!light_isdigit(*p) && *p != '}' && *p != '\0') {
@ -256,13 +260,13 @@ static int pcre_keyvalue_buffer_subst_ext(buffer *b, const char *pattern, const
}
if (0 == flags) flags = BURL_ENCODE_PSNDE; /* default */
pattern[0] == '$' /*(else '%')*/
? pcre_keyvalue_buffer_append_match(b, list, n, num, flags)
? pcre_keyvalue_buffer_append_match(b, ctx, num, flags)
: pcre_keyvalue_buffer_append_ctxmatch(b, ctx, num, flags);
}
return (int)(p + 1 - (unsigned char *)pattern - 2);
}
static void pcre_keyvalue_buffer_subst(buffer *b, const buffer *patternb, const char **list, int n, const pcre_keyvalue_ctx *ctx) {
static void pcre_keyvalue_buffer_subst(buffer *b, const buffer *patternb, const pcre_keyvalue_ctx *ctx) {
const char *pattern = patternb->ptr;
const size_t pattern_len = buffer_clen(patternb);
size_t start = 0;
@ -277,13 +281,13 @@ static void pcre_keyvalue_buffer_subst(buffer *b, const buffer *patternb, const
buffer_append_string_len(b, pattern + start, k - start);
if (pattern[k + 1] == '{') {
int num = pcre_keyvalue_buffer_subst_ext(b, pattern+k, list, n, ctx);
int num = pcre_keyvalue_buffer_subst_ext(b, pattern+k, ctx);
if (num < 0) return; /* error; truncate result */
k += (size_t)num;
} else if (light_isdigit(((unsigned char *)pattern)[k + 1])) {
unsigned int num = (unsigned int)pattern[k + 1] - '0';
pattern[k] == '$' /*(else '%')*/
? pcre_keyvalue_buffer_append_match(b, list, n, num, 0)
? pcre_keyvalue_buffer_append_match(b, ctx, num, 0)
: pcre_keyvalue_buffer_append_ctxmatch(b, ctx, num, 0);
} else {
/* enable escape: "%%" => "%", "%a" => "%a", "$$" => "$" */
@ -299,8 +303,8 @@ static void pcre_keyvalue_buffer_subst(buffer *b, const buffer *patternb, const
}
handler_t pcre_keyvalue_buffer_process(const pcre_keyvalue_buffer *kvb, pcre_keyvalue_ctx *ctx, const buffer *input, buffer *result) {
for (int i = 0, used = (int)kvb->used; i < used; ++i) {
const pcre_keyvalue * const kv = kvb->kv+i;
const pcre_keyvalue *kv = kvb->kv;
for (int i = 0, used = (int)kvb->used; i < used; ++i, ++kv) {
#define N 20
int ovec[N * 3];
#undef N
@ -318,11 +322,11 @@ handler_t pcre_keyvalue_buffer_process(const pcre_keyvalue_buffer *kvb, pcre_key
return HANDLER_GO_ON;
}
else { /* it matched */
const char **list;
ctx->m = i;
pcre_get_substring_list(input->ptr, ovec, n, &list);
pcre_keyvalue_buffer_subst(result, &kv->value, list, n, ctx);
pcre_free(list);
ctx->n = n;
ctx->subject = input->ptr;
ctx->ovec = ovec;
pcre_keyvalue_buffer_subst(result, &kv->value, ctx);
return HANDLER_FINISHED;
}
}

View File

@ -13,6 +13,10 @@ typedef struct pcre_keyvalue_ctx {
struct cond_match_t *cache;
struct burl_parts_t *burl;
int m;
/*(internal use)*/
int n;
void *ovec;
const char *subject;
} pcre_keyvalue_ctx;
typedef struct {

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, -1 };
pcre_keyvalue_ctx ctx = { NULL, NULL, -1, 0, NULL, NULL };
#ifdef __COVERITY__
/*(again, must have been configured w/ empty kvb 'value' during init)*/
struct cond_match_t cache;

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, -1 };
pcre_keyvalue_ctx ctx = { NULL, NULL, -1, 0, NULL, NULL };
#ifdef __COVERITY__
/*(again, must have been configured w/ empty kvb 'value' during init)*/
struct cond_match_t cache;