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/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, NULL); +#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, NULL); +#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; @@ -91,6 +92,11 @@ static int excludes_buffer_append(excludes_buffer 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 int excludes_buffer_append(excludes_buffer 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, NULL); +#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]); } 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; @@ -72,6 +73,11 @@ static int rewrite_rule_buffer_append(rewrite_rule 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 int rewrite_rule_buffer_append(rewrite_rule 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, NULL); +#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]); } @@ -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, NULL); +#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, NULL); +#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, NULL); +#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); }