From e8c1efd5dfc11b5001113198741536648067c024 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Wed, 18 Apr 2018 01:38:41 -0400 Subject: [PATCH] [core] data_config_pcre_compile,exec() collect PCRE usage related to config processing --- src/CMakeLists.txt | 1 + src/Makefile.am | 2 +- src/configfile-glue.c | 20 +-------------- src/configfile.h | 4 +++ src/configparser.y | 43 +++---------------------------- src/data_config.c | 60 +++++++++++++++++++++++++++++++++++++++++++ src/meson.build | 1 + 7 files changed, 72 insertions(+), 59 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 20a68842..c1c6627d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -662,6 +662,7 @@ add_executable(test_configfile test_configfile.c buffer.c array.c + data_config.c data_string.c keyvalue.c vector.c diff --git a/src/Makefile.am b/src/Makefile.am index 8b2828b6..66de3219 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -520,7 +520,7 @@ test_buffer_LDADD = $(LIBUNWIND_LIBS) test_base64_SOURCES = test_base64.c base64.c buffer.c test_base64_LDADD = $(LIBUNWIND_LIBS) -test_configfile_SOURCES = test_configfile.c buffer.c array.c data_string.c keyvalue.c vector.c log.c sock_addr.c +test_configfile_SOURCES = test_configfile.c buffer.c array.c data_config.c data_string.c keyvalue.c vector.c log.c sock_addr.c test_configfile_LDADD = $(PCRE_LIB) $(LIBUNWIND_LIBS) noinst_HEADERS = $(hdr) diff --git a/src/configfile-glue.c b/src/configfile-glue.c index 7e5679dc..a2b6bdca 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -12,10 +12,6 @@ #include #include -#ifdef HAVE_PCRE_H -#include -#endif - /** * like all glue code this file contains functions which * are the external interface of lighttpd. The functions @@ -480,29 +476,15 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat } else { return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; } - break; -#ifdef HAVE_PCRE_H case CONFIG_COND_NOMATCH: case CONFIG_COND_MATCH: { - int n; - -#ifndef elementsof -#define elementsof(x) (sizeof(x) / sizeof(x[0])) -#endif - n = pcre_exec(dc->regex, dc->regex_study, CONST_BUF_LEN(l), 0, 0, - cache->matches, elementsof(cache->matches)); - - cache->patterncount = n; - if (n > 0) { - cache->comp_value = l; + if (data_config_pcre_exec(dc, cache, l) > 0) { return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; } else { /* cache is already cleared */ return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE; } - break; } -#endif default: /* no way */ break; diff --git a/src/configfile.h b/src/configfile.h index 83fecad4..1cef1209 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -79,7 +79,11 @@ struct data_config { #endif }; +struct cond_cache_t; /* declaration */ + data_config *data_config_init(void); +int data_config_pcre_compile(data_config *dc); +int data_config_pcre_exec(data_config *dc, struct cond_cache_t *cache, buffer *b); typedef struct { server *srv; diff --git a/src/configparser.y b/src/configparser.y index bd51b66c..396cbdf3 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -12,13 +12,10 @@ #include #include +#include #include #include -#ifdef HAVE_PCRE_H -#include -#endif - static void configparser_push(config_t *ctx, data_config *dc, int isnew) { if (isnew) { dc->context_ndx = ctx->all_configs->used; @@ -694,49 +691,17 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio } } + dc->string = buffer_init_buffer(rvalue); + if (ctx->ok) switch(E) { case CONFIG_COND_NE: case CONFIG_COND_EQ: - dc->string = buffer_init_buffer(rvalue); break; case CONFIG_COND_NOMATCH: case CONFIG_COND_MATCH: { -#ifdef HAVE_PCRE_H - const char *errptr; - int erroff, captures; - - if (NULL == (dc->regex = - pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) { - dc->string = buffer_init_string(errptr); - dc->cond = CONFIG_COND_UNSET; - - fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", - rvalue->ptr, errptr, erroff); - + if (!data_config_pcre_compile(dc)) { ctx->ok = 0; - } else if (NULL == (dc->regex_study = - pcre_study(dc->regex, 0, &errptr)) && - errptr != NULL) { - fprintf(stderr, "studying regex failed: %s -> %s\n", - rvalue->ptr, errptr); - ctx->ok = 0; - } else if (0 != (pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, &captures))) { - fprintf(stderr, "getting capture count for regex failed: %s\n", - rvalue->ptr); - ctx->ok = 0; - } else if (captures > 9) { - fprintf(stderr, "Too many captures in regex, use (?:...) instead of (...): %s\n", - rvalue->ptr); - ctx->ok = 0; - } else { - dc->string = buffer_init_buffer(rvalue); } -#else - fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n" - "(perhaps just a missing pcre-devel package ?) \n", - B->ptr, C->ptr); - ctx->ok = 0; - #endif break; } diff --git a/src/data_config.c b/src/data_config.c index 4082d794..dbf6860d 100644 --- a/src/data_config.c +++ b/src/data_config.c @@ -1,5 +1,6 @@ #include "first.h" +#include "base.h" /* (cond_cache_t) */ #include "array.h" #include "configfile.h" @@ -153,3 +154,62 @@ data_config *data_config_init(void) { return ds; } + +int data_config_pcre_compile(data_config *dc) { +#ifdef HAVE_PCRE_H + /* (use fprintf() on error, as this is called from configparser.y) */ + const char *errptr; + int erroff, captures; + + if (dc->regex) pcre_free(dc->regex); + if (dc->regex_study) pcre_free(dc->regex_study); + + dc->regex = pcre_compile(dc->string->ptr, 0, &errptr, &erroff, NULL); + if (NULL == dc->regex) { + fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", + dc->string->ptr, errptr, erroff); + return 0; + } + + dc->regex_study = pcre_study(dc->regex, 0, &errptr); + if (NULL == dc->regex_study && errptr != NULL) { + fprintf(stderr, "studying regex failed: %s -> %s\n", + dc->string->ptr, errptr); + return 0; + } + + erroff = pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, + &captures); + if (0 != erroff) { + fprintf(stderr, "getting capture count for regex failed: %s\n", + dc->string->ptr); + return 0; + } else if (captures > 9) { + fprintf(stderr, "Too many captures in regex, use (?:...) instead of (...): %s\n", + dc->string->ptr); + return 0; + } + return 1; +#else + fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n" + "(perhaps just a missing pcre-devel package ?) \n", + dc->comp_key->ptr, dc->comp_tag->ptr); + return 0; +#endif +} + +int data_config_pcre_exec(data_config *dc, cond_cache_t *cache, buffer *b) { +#ifdef HAVE_PCRE_H + #ifndef elementsof + #define elementsof(x) (sizeof(x) / sizeof(x[0])) + #endif + cache->patterncount = + pcre_exec(dc->regex, dc->regex_study, CONST_BUF_LEN(b), 0, 0, + cache->matches, elementsof(cache->matches)); + if (cache->patterncount > 0) + cache->comp_value = b; /* holds pointer to b (!) for pattern subst */ + return cache->patterncount; +#else + return 0; +#endif +} diff --git a/src/meson.build b/src/meson.build index 57b66d8f..855e52b1 100644 --- a/src/meson.build +++ b/src/meson.build @@ -703,6 +703,7 @@ test('test_configfile', executable('test_configfile', 'test_configfile.c', 'buffer.c', 'array.c', + 'data_config.c', 'data_string.c', 'keyvalue.c', 'vector.c',