diff src/core/ngx_regex.c @ 656:9d21dad0b5a1 NGINX_1_1_12

nginx 1.1.12 *) Change: a "proxy_pass" directive without URI part now uses changed URI after redirection with the "error_page" directive; Thanks to Lanshun Zhou. *) Feature: the "proxy/fastcgi/scgi/uwsgi_cache_lock", "proxy/fastcgi/scgi/uwsgi_cache_lock_timeout" directives. *) Feature: the "pcre_jit" directive. *) Feature: the "if" SSI command supports captures in regular expressions. *) Bugfix: the "if" SSI command did not work inside the "block" command. *) Bugfix: the "limit_conn_log_level" and "limit_req_log_level" directives might not work. *) Bugfix: the "limit_rate" directive did not allow to use full throughput, even if limit value was very high. *) Bugfix: the "sendfile_max_chunk" directive did not work, if the "limit_rate" directive was used. *) Bugfix: a "proxy_pass" directive without URI part always used original request URI if variables were used. *) Bugfix: a "proxy_pass" directive without URI part might use original request after redirection with the "try_files" directive; Thanks to Lanshun Zhou. *) Bugfix: in the ngx_http_scgi_module. *) Bugfix: in the ngx_http_mp4_module. *) Bugfix: nginx could not be built on Solaris; the bug had appeared in 1.1.9.
author Igor Sysoev <http://sysoev.ru>
date Mon, 26 Dec 2011 00:00:00 +0400
parents 753f505670e0
children d0f7a625f27c
line wrap: on
line diff
--- 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 *r
         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;
+}