Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.11 ]​[ nginx-1.14.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 
0011 
0012 typedef struct {
0013     ngx_flag_t  pcre_jit;
0014 } ngx_regex_conf_t;
0015 
0016 
0017 static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
0018 static void ngx_libc_cdecl ngx_regex_free(void *p);
0019 #if (NGX_HAVE_PCRE_JIT)
0020 static void ngx_pcre_free_studies(void *data);
0021 #endif
0022 
0023 static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
0024 
0025 static void *ngx_regex_create_conf(ngx_cycle_t *cycle);
0026 static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf);
0027 
0028 static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data);
0029 static ngx_conf_post_t  ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };
0030 
0031 
0032 static ngx_command_t  ngx_regex_commands[] = {
0033 
0034     { ngx_string("pcre_jit"),
0035       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
0036       ngx_conf_set_flag_slot,
0037       0,
0038       offsetof(ngx_regex_conf_t, pcre_jit),
0039       &ngx_regex_pcre_jit_post },
0040 
0041       ngx_null_command
0042 };
0043 
0044 
0045 static ngx_core_module_t  ngx_regex_module_ctx = {
0046     ngx_string("regex"),
0047     ngx_regex_create_conf,
0048     ngx_regex_init_conf
0049 };
0050 
0051 
0052 ngx_module_t  ngx_regex_module = {
0053     NGX_MODULE_V1,
0054     &ngx_regex_module_ctx,                 /* module context */
0055     ngx_regex_commands,                    /* module directives */
0056     NGX_CORE_MODULE,                       /* module type */
0057     NULL,                                  /* init master */
0058     ngx_regex_module_init,                 /* init module */
0059     NULL,                                  /* init process */
0060     NULL,                                  /* init thread */
0061     NULL,                                  /* exit thread */
0062     NULL,                                  /* exit process */
0063     NULL,                                  /* exit master */
0064     NGX_MODULE_V1_PADDING
0065 };
0066 
0067 
0068 static ngx_pool_t  *ngx_pcre_pool;
0069 static ngx_list_t  *ngx_pcre_studies;
0070 
0071 
0072 void
0073 ngx_regex_init(void)
0074 {
0075     pcre_malloc = ngx_regex_malloc;
0076     pcre_free = ngx_regex_free;
0077 }
0078 
0079 
0080 static ngx_inline void
0081 ngx_regex_malloc_init(ngx_pool_t *pool)
0082 {
0083     ngx_pcre_pool = pool;
0084 }
0085 
0086 
0087 static ngx_inline void
0088 ngx_regex_malloc_done(void)
0089 {
0090     ngx_pcre_pool = NULL;
0091 }
0092 
0093 
0094 ngx_int_t
0095 ngx_regex_compile(ngx_regex_compile_t *rc)
0096 {
0097     int               n, erroff;
0098     char             *p;
0099     pcre             *re;
0100     const char       *errstr;
0101     ngx_regex_elt_t  *elt;
0102 
0103     ngx_regex_malloc_init(rc->pool);
0104 
0105     re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
0106                       &errstr, &erroff, NULL);
0107 
0108     /* ensure that there is no current pool */
0109     ngx_regex_malloc_done();
0110 
0111     if (re == NULL) {
0112         if ((size_t) erroff == rc->pattern.len) {
0113            rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
0114                               "pcre_compile() failed: %s in \"%V\"",
0115                                errstr, &rc->pattern)
0116                       - rc->err.data;
0117 
0118         } else {
0119            rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
0120                               "pcre_compile() failed: %s in \"%V\" at \"%s\"",
0121                                errstr, &rc->pattern, rc->pattern.data + erroff)
0122                       - rc->err.data;
0123         }
0124 
0125         return NGX_ERROR;
0126     }
0127 
0128     rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t));
0129     if (rc->regex == NULL) {
0130         goto nomem;
0131     }
0132 
0133     rc->regex->code = re;
0134 
0135     /* do not study at runtime */
0136 
0137     if (ngx_pcre_studies != NULL) {
0138         elt = ngx_list_push(ngx_pcre_studies);
0139         if (elt == NULL) {
0140             goto nomem;
0141         }
0142 
0143         elt->regex = rc->regex;
0144         elt->name = rc->pattern.data;
0145     }
0146 
0147     n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
0148     if (n < 0) {
0149         p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
0150         goto failed;
0151     }
0152 
0153     if (rc->captures == 0) {
0154         return NGX_OK;
0155     }
0156 
0157     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
0158     if (n < 0) {
0159         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
0160         goto failed;
0161     }
0162 
0163     if (rc->named_captures == 0) {
0164         return NGX_OK;
0165     }
0166 
0167     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
0168     if (n < 0) {
0169         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
0170         goto failed;
0171     }
0172 
0173     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
0174     if (n < 0) {
0175         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
0176         goto failed;
0177     }
0178 
0179     return NGX_OK;
0180 
0181 failed:
0182 
0183     rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
0184                   - rc->err.data;
0185     return NGX_ERROR;
0186 
0187 nomem:
0188 
0189     rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
0190                                "regex \"%V\" compilation failed: no memory",
0191                                &rc->pattern)
0192                   - rc->err.data;
0193     return NGX_ERROR;
0194 }
0195 
0196 
0197 ngx_int_t
0198 ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
0199 {
0200     ngx_int_t         n;
0201     ngx_uint_t        i;
0202     ngx_regex_elt_t  *re;
0203 
0204     re = a->elts;
0205 
0206     for (i = 0; i < a->nelts; i++) {
0207 
0208         n = ngx_regex_exec(re[i].regex, s, NULL, 0);
0209 
0210         if (n == NGX_REGEX_NO_MATCHED) {
0211             continue;
0212         }
0213 
0214         if (n < 0) {
0215             ngx_log_error(NGX_LOG_ALERT, log, 0,
0216                           ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
0217                           n, s, re[i].name);
0218             return NGX_ERROR;
0219         }
0220 
0221         /* match */
0222 
0223         return NGX_OK;
0224     }
0225 
0226     return NGX_DECLINED;
0227 }
0228 
0229 
0230 static void * ngx_libc_cdecl
0231 ngx_regex_malloc(size_t size)
0232 {
0233     ngx_pool_t      *pool;
0234     pool = ngx_pcre_pool;
0235 
0236     if (pool) {
0237         return ngx_palloc(pool, size);
0238     }
0239 
0240     return NULL;
0241 }
0242 
0243 
0244 static void ngx_libc_cdecl
0245 ngx_regex_free(void *p)
0246 {
0247     return;
0248 }
0249 
0250 
0251 #if (NGX_HAVE_PCRE_JIT)
0252 
0253 static void
0254 ngx_pcre_free_studies(void *data)
0255 {
0256     ngx_list_t *studies = data;
0257 
0258     ngx_uint_t        i;
0259     ngx_list_part_t  *part;
0260     ngx_regex_elt_t  *elts;
0261 
0262     part = &studies->part;
0263     elts = part->elts;
0264 
0265     for (i = 0; /* void */ ; i++) {
0266 
0267         if (i >= part->nelts) {
0268             if (part->next == NULL) {
0269                 break;
0270             }
0271 
0272             part = part->next;
0273             elts = part->elts;
0274             i = 0;
0275         }
0276 
0277         if (elts[i].regex->extra != NULL) {
0278             pcre_free_study(elts[i].regex->extra);
0279         }
0280     }
0281 }
0282 
0283 #endif
0284 
0285 
0286 static ngx_int_t
0287 ngx_regex_module_init(ngx_cycle_t *cycle)
0288 {
0289     int               opt;
0290     const char       *errstr;
0291     ngx_uint_t        i;
0292     ngx_list_part_t  *part;
0293     ngx_regex_elt_t  *elts;
0294 
0295     opt = 0;
0296 
0297 #if (NGX_HAVE_PCRE_JIT)
0298     {
0299     ngx_regex_conf_t    *rcf;
0300     ngx_pool_cleanup_t  *cln;
0301 
0302     rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
0303 
0304     if (rcf->pcre_jit) {
0305         opt = PCRE_STUDY_JIT_COMPILE;
0306 
0307         /*
0308          * The PCRE JIT compiler uses mmap for its executable codes, so we
0309          * have to explicitly call the pcre_free_study() function to free
0310          * this memory.
0311          */
0312 
0313         cln = ngx_pool_cleanup_add(cycle->pool, 0);
0314         if (cln == NULL) {
0315             return NGX_ERROR;
0316         }
0317 
0318         cln->handler = ngx_pcre_free_studies;
0319         cln->data = ngx_pcre_studies;
0320     }
0321     }
0322 #endif
0323 
0324     ngx_regex_malloc_init(cycle->pool);
0325 
0326     part = &ngx_pcre_studies->part;
0327     elts = part->elts;
0328 
0329     for (i = 0; /* void */ ; i++) {
0330 
0331         if (i >= part->nelts) {
0332             if (part->next == NULL) {
0333                 break;
0334             }
0335 
0336             part = part->next;
0337             elts = part->elts;
0338             i = 0;
0339         }
0340 
0341         elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr);
0342 
0343         if (errstr != NULL) {
0344             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0345                           "pcre_study() failed: %s in \"%s\"",
0346                           errstr, elts[i].name);
0347         }
0348 
0349 #if (NGX_HAVE_PCRE_JIT)
0350         if (opt & PCRE_STUDY_JIT_COMPILE) {
0351             int jit, n;
0352 
0353             jit = 0;
0354             n = pcre_fullinfo(elts[i].regex->code, elts[i].regex->extra,
0355                               PCRE_INFO_JIT, &jit);
0356 
0357             if (n != 0 || jit != 1) {
0358                 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
0359                               "JIT compiler does not support pattern: \"%s\"",
0360                               elts[i].name);
0361             }
0362         }
0363 #endif
0364     }
0365 
0366     ngx_regex_malloc_done();
0367 
0368     ngx_pcre_studies = NULL;
0369 
0370     return NGX_OK;
0371 }
0372 
0373 
0374 static void *
0375 ngx_regex_create_conf(ngx_cycle_t *cycle)
0376 {
0377     ngx_regex_conf_t  *rcf;
0378 
0379     rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
0380     if (rcf == NULL) {
0381         return NULL;
0382     }
0383 
0384     rcf->pcre_jit = NGX_CONF_UNSET;
0385 
0386     ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
0387     if (ngx_pcre_studies == NULL) {
0388         return NULL;
0389     }
0390 
0391     return rcf;
0392 }
0393 
0394 
0395 static char *
0396 ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf)
0397 {
0398     ngx_regex_conf_t *rcf = conf;
0399 
0400     ngx_conf_init_value(rcf->pcre_jit, 0);
0401 
0402     return NGX_CONF_OK;
0403 }
0404 
0405 
0406 static char *
0407 ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
0408 {
0409     ngx_flag_t  *fp = data;
0410 
0411     if (*fp == 0) {
0412         return NGX_CONF_OK;
0413     }
0414 
0415 #if (NGX_HAVE_PCRE_JIT)
0416     {
0417     int  jit, r;
0418 
0419     jit = 0;
0420     r = pcre_config(PCRE_CONFIG_JIT, &jit);
0421 
0422     if (r != 0 || jit != 1) {
0423         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
0424                            "PCRE library does not support JIT");
0425         *fp = 0;
0426     }
0427     }
0428 #else
0429     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
0430                        "nginx was built without PCRE JIT support");
0431     *fp = 0;
0432 #endif
0433 
0434     return NGX_CONF_OK;
0435 }