diff options
Diffstat (limited to 'src/core/ngx_regex.c')
-rw-r--r-- | src/core/ngx_regex.c | 215 |
1 files changed, 210 insertions, 5 deletions
diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c index af00f8319..fc5296ac1 100644 --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -8,11 +8,61 @@ #include <ngx_core.h> +typedef struct { + ngx_flag_t pcre_jit; +} ngx_regex_conf_t; + + static void * ngx_libc_cdecl ngx_regex_malloc(size_t size); static void ngx_libc_cdecl ngx_regex_free(void *p); +static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle); + +static void *ngx_regex_create_conf(ngx_cycle_t *cycle); +static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf); + +static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data); +static ngx_conf_post_t ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit }; + + +static ngx_command_t ngx_regex_commands[] = { + + { ngx_string("pcre_jit"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + 0, + offsetof(ngx_regex_conf_t, pcre_jit), + &ngx_regex_pcre_jit_post }, + + ngx_null_command +}; + + +static ngx_core_module_t ngx_regex_module_ctx = { + ngx_string("regex"), + ngx_regex_create_conf, + ngx_regex_init_conf +}; + + +ngx_module_t ngx_regex_module = { + NGX_MODULE_V1, + &ngx_regex_module_ctx, /* module context */ + ngx_regex_commands, /* module directives */ + NGX_CORE_MODULE, /* module type */ + NULL, /* init master */ + ngx_regex_module_init, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + static ngx_pool_t *ngx_pcre_pool; +static ngx_list_t *ngx_pcre_studies; void @@ -62,10 +112,11 @@ ngx_regex_malloc_done(void) ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc) { - int n, erroff; - char *p; - const char *errstr; - ngx_regex_t *re; + int n, erroff; + char *p; + pcre *re; + const char *errstr; + ngx_regex_elt_t *elt; ngx_regex_malloc_init(rc->pool); @@ -92,7 +143,24 @@ ngx_regex_compile(ngx_regex_compile_t *rc) return NGX_ERROR; } - rc->regex = re; + rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t)); + if (rc->regex == NULL) { + return NGX_ERROR; + } + + rc->regex->pcre = re; + + /* do not study at runtime */ + + if (ngx_pcre_studies != NULL) { + elt = ngx_list_push(ngx_pcre_studies); + if (elt == NULL) { + return NGX_ERROR; + } + + elt->regex = rc->regex; + elt->name = rc->pattern.data; + } n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures); if (n < 0) { @@ -203,3 +271,140 @@ ngx_regex_free(void *p) { return; } + + +static ngx_int_t +ngx_regex_module_init(ngx_cycle_t *cycle) +{ + int opt; + const char *errstr; + ngx_uint_t i; + ngx_list_part_t *part; + ngx_regex_elt_t *elts; + + opt = 0; + +#if (NGX_HAVE_PCRE_JIT) + { + ngx_regex_conf_t *rcf; + + rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module); + + if (rcf->pcre_jit) { + opt = PCRE_STUDY_JIT_COMPILE; + } + } +#endif + + ngx_regex_malloc_init(cycle->pool); + + part = &ngx_pcre_studies->part; + elts = part->elts; + + for (i = 0 ; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + elts = part->elts; + i = 0; + } + + elts[i].regex->extra = pcre_study(elts[i].regex->pcre, opt, &errstr); + + if (errstr != NULL) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "pcre_study() failed: %s in \"%s\"", + errstr, elts[i].name); + } + +#if (NGX_HAVE_PCRE_JIT) + if (opt & PCRE_STUDY_JIT_COMPILE) { + int jit, n; + + jit = 0; + n = pcre_fullinfo(elts[i].regex->pcre, elts[i].regex->extra, + PCRE_INFO_JIT, &jit); + + if (n != 0 || jit != 1) { + ngx_log_error(NGX_LOG_INFO, cycle->log, 0, + "JIT compiler does not support pattern: \"%s\"", + elts[i].name); + } + } +#endif + } + + ngx_regex_malloc_done(); + + ngx_pcre_studies = NULL; + + return NGX_OK; +} + + +static void * +ngx_regex_create_conf(ngx_cycle_t *cycle) +{ + ngx_regex_conf_t *rcf; + + rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t)); + if (rcf == NULL) { + return NULL; + } + + rcf->pcre_jit = NGX_CONF_UNSET; + + ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t)); + if (ngx_pcre_studies == NULL) { + return NULL; + } + + return rcf; +} + + +static char * +ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf) +{ + ngx_regex_conf_t *rcf = conf; + + ngx_conf_init_value(rcf->pcre_jit, 0); + + return NGX_CONF_OK; +} + + +static char * +ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data) +{ + ngx_flag_t *fp = data; + + if (*fp == 0) { + return NGX_CONF_OK; + } + +#if (NGX_HAVE_PCRE_JIT) + { + int jit, r; + + jit = 0; + r = pcre_config(PCRE_CONFIG_JIT, &jit); + + if (r != 0 || jit != 1) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "PCRE library does not support JIT"); + *fp = 0; + } + } +#else + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "nginx was build without PCRE JIT support"); + *fp = 0; +#endif + + return NGX_CONF_OK; +} |