Index: src/data_config.c =================================================================== --- src/data_config.c (revision 2805) +++ src/data_config.c (working copy) @@ -28,8 +28,14 @@ static void data_config_free(data_unset *d) { if (ds->string) buffer_free(ds->string); #ifdef HAVE_PCRE_H if (ds->regex) pcre_free(ds->regex); - if (ds->regex_study) pcre_free(ds->regex_study); + if (ds->regex_study) { +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(ds->regex_study); +#else + pcre_free(ds->regex_study); #endif + } +#endif free(d); } Index: src/base.h =================================================================== --- src/base.h (revision 2805) +++ src/base.h (working copy) @@ -20,6 +20,10 @@ # include #endif +#ifdef HAVE_PCRE_H +# include +#endif + #include "buffer.h" #include "array.h" #include "chunk.h" @@ -651,10 +655,12 @@ typedef struct server { #ifdef USE_OPENSSL int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq, off_t max_bytes); #endif +#if defined(HAVE_PCRE_H) && defined(PCRE_STUDY_JIT_COMPILE) + pcre_jit_stack *jit_stack; +#endif uid_t uid; gid_t gid; } server; - #endif Index: src/configparser.y =================================================================== --- src/configparser.y (revision 2805) +++ src/configparser.y (working copy) @@ -471,6 +471,11 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop #ifdef HAVE_PCRE_H const char *errptr; int erroff, captures; +#ifdef PCRE_STUDY_JIT_COMPILE + static int study_options = PCRE_STUDY_JIT_COMPILE; +#else + static int study_options = 0; +#endif if (NULL == (dc->regex = pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) { @@ -482,21 +487,26 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop ctx->ok = 0; } else if (NULL == (dc->regex_study = - pcre_study(dc->regex, 0, &errptr)) && + pcre_study(dc->regex, study_options, &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); +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_assign_jit_stack(dc->regex_study, NULL, ctx->srv->jit_stack); +#endif + 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" Index: src/mod_ssi.c =================================================================== --- src/mod_ssi.c (revision 2805) +++ src/mod_ssi.c (working copy) @@ -80,8 +80,15 @@ FREE_FUNC(mod_ssi_free) { array_free(p->ssi_vars); array_free(p->ssi_cgi_env); #ifdef HAVE_PCRE_H - pcre_free(p->ssi_regex); + if (p->ssi_regex) pcre_free(p->ssi_regex); + if (p->ssi_regex_extra) { +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(p->ssi_regex_extra); +#else + pcre_free(p->ssi_regex_extra); #endif + } +#endif buffer_free(p->timefmt); buffer_free(p->stat_fn); @@ -98,7 +105,12 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) { #ifdef HAVE_PCRE_H const char *errptr; int erroff; +#ifdef PCRE_STUDY_JIT_EXTRA + static int study_options = PCRE_STUDY_JIT_EXTRA; +#else + static int study_options = 0; #endif +#endif config_values_t cv[] = { { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ @@ -135,6 +147,16 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) { erroff, errptr); return HANDLER_ERROR; } + if (NULL == (p->ssi_regex_extra = pcre_study(p->ssi_regex, study_options, &errptr))) { + log_error_write(srv, __FILE__, __LINE__, "ss", + "ssi: pcre study ", + errptr); + return HANDLER_ERROR; + } +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_assign_jit_stack(p->ssi_regex_extra, NULL, srv->jit_stack); +#endif + #else log_error_write(srv, __FILE__, __LINE__, "s", "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules"); @@ -1041,7 +1063,7 @@ static int mod_ssi_handle_request(server *srv, con * */ #ifdef HAVE_PCRE_H - for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) { + for (i = 0; (n = pcre_exec(p->ssi_regex, p->ssi_regex_extra, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) { const char **l; /* take everything from last offset to current match pos */ Index: src/mod_ssi.h =================================================================== --- src/mod_ssi.h (revision 2805) +++ src/mod_ssi.h (working copy) @@ -23,6 +23,7 @@ typedef struct { #ifdef HAVE_PCRE_H pcre *ssi_regex; + pcre_extra *ssi_regex_extra; #endif buffer *timefmt; int sizefmt; Index: src/mod_dirlisting.c =================================================================== --- src/mod_dirlisting.c (revision 2805) +++ src/mod_dirlisting.c (working copy) @@ -38,6 +38,7 @@ typedef struct { #ifdef HAVE_PCRE_H pcre *regex; + pcre_extra *regex_extra; #endif buffer *string; } excludes; @@ -86,11 +87,16 @@ static excludes_buffer *excludes_buffer_init(void) return exb; } -static int excludes_buffer_append(excludes_buffer *exb, buffer *string) { +static int excludes_buffer_append(excludes_buffer *exb, buffer *string, server *srv) { #ifdef HAVE_PCRE_H size_t i; const char *errptr; int erroff; +#ifdef PCRE_STUDY_JIT_COMPILE + static int study_options = PCRE_STUDY_JIT_COMPILE; +#else + static int study_options = 0; +#endif if (!string) return -1; @@ -119,6 +125,14 @@ static excludes_buffer *excludes_buffer_init(void) return -1; } + if (NULL == (exb->ptr[exb->used]->regex_extra = pcre_study(exb->ptr[exb->used]->regex, + study_options, &errptr))) { + return -1; + } +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_assign_jit_stack(exb->ptr[exb->used]->regex_extra, NULL, srv->jit_stack); +#endif + exb->ptr[exb->used]->string = buffer_init(); buffer_copy_string_buffer(exb->ptr[exb->used]->string, string); @@ -139,6 +153,13 @@ static void excludes_buffer_free(excludes_buffer * for (i = 0; i < exb->size; i++) { if (exb->ptr[i]->regex) pcre_free(exb->ptr[i]->regex); + if (exb->ptr[i]->regex_extra) { +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(exb->ptr[i]->regex_extra); +#else + pcre_free(exb->ptr[i]->regex_extra); +#endif + } if (exb->ptr[i]->string) buffer_free(exb->ptr[i]->string); free(exb->ptr[i]); } @@ -220,7 +241,7 @@ static int parse_config_entry(server *srv, plugin_ } if (0 != excludes_buffer_append(s->excludes, - ((data_string *)(da->value->data[j]))->value)) { + ((data_string *)(da->value->data[j]))->value, srv)) { #ifdef HAVE_PCRE_H log_error_write(srv, __FILE__, __LINE__, "sb", "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value); Index: src/mod_rewrite.c =================================================================== --- src/mod_rewrite.c (revision 2805) +++ src/mod_rewrite.c (working copy) @@ -12,6 +12,7 @@ #ifdef HAVE_PCRE_H typedef struct { pcre *key; + pcre_extra *key_extra; buffer *value; @@ -68,10 +69,15 @@ static rewrite_rule_buffer *rewrite_rule_buffer_in return kvb; } -static int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) { +static int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once, server *srv) { size_t i; const char *errptr; int erroff; +#ifdef PCRE_STUDY_JIT_COMPILE + static int study_options = PCRE_STUDY_JIT_COMPILE; +#else + static int study_options = 0; +#endif if (!key) return -1; @@ -96,9 +102,17 @@ static rewrite_rule_buffer *rewrite_rule_buffer_in if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr, 0, &errptr, &erroff, NULL))) { + return -1; + } + if (NULL == (kvb->ptr[kvb->used]->key_extra = pcre_study(kvb->ptr[kvb->used]->key, + study_options, &errptr)) && + errptr != NULL) { return -1; } +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_assign_jit_stack(kvb->ptr[kvb->used]->key_extra, NULL, srv->jit_stack); +#endif kvb->ptr[kvb->used]->value = buffer_init(); buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value); @@ -115,6 +129,13 @@ static void rewrite_rule_buffer_free(rewrite_rule_ for (i = 0; i < kvb->size; i++) { if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key); if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value); + if (kvb->ptr[i]->key_extra) { +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(kvb->ptr[i]->key_extra); +#else + pcre_free(kvb->ptr[i]->key_extra); +#endif + } free(kvb->ptr[i]); } @@ -188,7 +209,7 @@ static int parse_config_entry(server *srv, array * if (0 != rewrite_rule_buffer_append(kvb, ((data_string *)(da->value->data[j]))->key, ((data_string *)(da->value->data[j]))->value, - once)) { + once, srv)) { log_error_write(srv, __FILE__, __LINE__, "sb", "pcre-compile failed for", da->value->data[j]->key); } @@ -364,6 +385,7 @@ static int process_rewrite_rules(server *srv, conn for (i = 0; i < kvb->used; i++) { pcre *match; + pcre_extra *extra; const char *pattern; size_t pattern_len; int n; @@ -372,10 +394,11 @@ static int process_rewrite_rules(server *srv, conn int ovec[N * 3]; match = rule->key; + extra = rule->key_extra; pattern = rule->value->ptr; pattern_len = rule->value->used - 1; - if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { + if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { if (n != PCRE_ERROR_NOMATCH) { log_error_write(srv, __FILE__, __LINE__, "sd", "execution error while matching: ", n); Index: src/mod_trigger_b4_dl.c =================================================================== --- src/mod_trigger_b4_dl.c (revision 2805) +++ src/mod_trigger_b4_dl.c (working copy) @@ -42,6 +42,8 @@ typedef struct { #if defined(HAVE_PCRE_H) pcre *trigger_regex; pcre *download_regex; + pcre_extra *trigger_regex_extra; + pcre_extra *download_regex_extra; #endif #if defined(HAVE_GDBM_H) GDBM_FILE db; @@ -102,7 +104,21 @@ FREE_FUNC(mod_trigger_b4_dl_free) { #if defined(HAVE_PCRE_H) if (s->trigger_regex) pcre_free(s->trigger_regex); if (s->download_regex) pcre_free(s->download_regex); + if (s->trigger_regex_extra) { +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(s->trigger_regex_extra); +#else + pcre_free(s->trigger_regex_extra); #endif + } + if (s->download_regex_extra) { +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(s->download_regex_extra); +#else + pcre_free(s->download_regex_extra); +#endif + } +#endif #if defined(HAVE_GDBM_H) if (s->db) gdbm_close(s->db); #endif @@ -150,7 +166,12 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { #if defined(HAVE_PCRE_H) const char *errptr; int erroff; +#ifdef PCRE_STUDY_JIT_EXTRA + static int study_options = PCRE_STUDY_JIT_EXTRA; +#else + static int study_options = 0; #endif +#endif s = calloc(1, sizeof(plugin_config)); s->db_filename = buffer_init(); @@ -196,6 +217,16 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { s->download_url, "pos:", erroff); return HANDLER_ERROR; } + if (NULL == (s->download_regex_extra = pcre_study(s->download_regex, + study_options, &errptr))) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "studying regex for download-url failed:", + s->download_url); + return HANDLER_ERROR; + } +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_assign_jit_stack(s->download_regex_extra, NULL, srv->jit_stack); +#endif } if (!buffer_is_empty(s->trigger_url)) { @@ -208,6 +239,16 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { return HANDLER_ERROR; } + if (NULL == (s->trigger_regex_extra = pcre_study(s->trigger_regex, + study_options, &errptr))) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "studying regex for trigger-url failed:", + s->trigger_url); + return HANDLER_ERROR; + } +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_assign_jit_stack(s->trigger_regex_extra, NULL, srv->jit_stack); +#endif } #endif @@ -358,7 +399,7 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { } /* check if URL is a trigger -> insert IP into DB */ - if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) { + if ((n = pcre_exec(p->conf.trigger_regex, p->conf.trigger_regex_extra, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) { if (n != PCRE_ERROR_NOMATCH) { log_error_write(srv, __FILE__, __LINE__, "sd", "execution error while matching:", n); Index: src/keyvalue.c =================================================================== --- src/keyvalue.c (revision 2805) +++ src/keyvalue.c (working copy) @@ -319,7 +319,12 @@ int pcre_keyvalue_buffer_append(server *srv, pcre_ const char *errptr; int erroff; pcre_keyvalue *kv; +#ifdef PCRE_STUDY_JIT_COMPILE + static int study_options = PCRE_STUDY_JIT_COMPILE; +#else + static int study_options = 0; #endif +#endif if (!key) return -1; @@ -351,11 +356,13 @@ int pcre_keyvalue_buffer_append(server *srv, pcre_ "rexexp compilation error at ", errptr); return -1; } - - if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) && + if (NULL == (kv->key_extra = pcre_study(kv->key, study_options, &errptr)) && errptr != NULL) { return -1; } +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_assign_jit_stack(kv->key_extra, NULL, srv->jit_stack); +#endif kv->value = buffer_init_string(value); @@ -378,7 +385,13 @@ void pcre_keyvalue_buffer_free(pcre_keyvalue_buffe for (i = 0; i < kvb->size; i++) { kv = kvb->kv[i]; if (kv->key) pcre_free(kv->key); - if (kv->key_extra) pcre_free(kv->key_extra); + if (kv->key_extra) { +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(kv->key_extra); +#else + pcre_free(kv->key_extra); +#endif + } if (kv->value) buffer_free(kv->value); free(kv); } Index: src/server.c =================================================================== --- src/server.c (revision 2805) +++ src/server.c (working copy) @@ -250,6 +250,10 @@ static server *server_init(void) { srv->split_vals = array_init(); +#if defined(HAVE_PCRE_H) && defined(PCRE_STUDY_JIT_COMPILE) + srv->jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024); +#endif + return srv; } @@ -349,6 +353,11 @@ static void server_free(server *srv) { } #endif +#if defined(HAVE_PCRE_H) && defined(PCRE_STUDY_JIT_COMPILE) + if (srv->jit_stack) + pcre_jit_stack_free(srv->jit_stack); +#endif + free(srv); } @@ -454,6 +463,11 @@ static void show_features (void) { #else "\t- PCRE support\n" #endif +#if defined(HAVE_PCRE_H) && defined(PCRE_STUDY_JIT_COMPILE) + "\t+ PCRE JIT support\n" +#else + "\t- PCRE JIT support\n" +#endif #ifdef HAVE_MYSQL "\t+ mySQL support\n" #else