Annotation of embedaddon/nginx/src/core/ngx_regex.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: 
                     11: 
                     12: typedef struct {
                     13:     ngx_flag_t  pcre_jit;
                     14: } ngx_regex_conf_t;
                     15: 
                     16: 
                     17: static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
                     18: static void ngx_libc_cdecl ngx_regex_free(void *p);
                     19: #if (NGX_HAVE_PCRE_JIT)
                     20: static void ngx_pcre_free_studies(void *data);
                     21: #endif
                     22: 
                     23: static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
                     24: 
                     25: static void *ngx_regex_create_conf(ngx_cycle_t *cycle);
                     26: static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf);
                     27: 
                     28: static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data);
                     29: static ngx_conf_post_t  ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };
                     30: 
                     31: 
                     32: static ngx_command_t  ngx_regex_commands[] = {
                     33: 
                     34:     { ngx_string("pcre_jit"),
                     35:       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
                     36:       ngx_conf_set_flag_slot,
                     37:       0,
                     38:       offsetof(ngx_regex_conf_t, pcre_jit),
                     39:       &ngx_regex_pcre_jit_post },
                     40: 
                     41:       ngx_null_command
                     42: };
                     43: 
                     44: 
                     45: static ngx_core_module_t  ngx_regex_module_ctx = {
                     46:     ngx_string("regex"),
                     47:     ngx_regex_create_conf,
                     48:     ngx_regex_init_conf
                     49: };
                     50: 
                     51: 
                     52: ngx_module_t  ngx_regex_module = {
                     53:     NGX_MODULE_V1,
                     54:     &ngx_regex_module_ctx,                 /* module context */
                     55:     ngx_regex_commands,                    /* module directives */
                     56:     NGX_CORE_MODULE,                       /* module type */
                     57:     NULL,                                  /* init master */
                     58:     ngx_regex_module_init,                 /* init module */
                     59:     NULL,                                  /* init process */
                     60:     NULL,                                  /* init thread */
                     61:     NULL,                                  /* exit thread */
                     62:     NULL,                                  /* exit process */
                     63:     NULL,                                  /* exit master */
                     64:     NGX_MODULE_V1_PADDING
                     65: };
                     66: 
                     67: 
                     68: static ngx_pool_t  *ngx_pcre_pool;
                     69: static ngx_list_t  *ngx_pcre_studies;
                     70: 
                     71: 
                     72: void
                     73: ngx_regex_init(void)
                     74: {
                     75:     pcre_malloc = ngx_regex_malloc;
                     76:     pcre_free = ngx_regex_free;
                     77: }
                     78: 
                     79: 
                     80: static ngx_inline void
                     81: ngx_regex_malloc_init(ngx_pool_t *pool)
                     82: {
                     83: #if (NGX_THREADS)
                     84:     ngx_core_tls_t  *tls;
                     85: 
                     86:     if (ngx_threaded) {
                     87:         tls = ngx_thread_get_tls(ngx_core_tls_key);
                     88:         tls->pool = pool;
                     89:         return;
                     90:     }
                     91: 
                     92: #endif
                     93: 
                     94:     ngx_pcre_pool = pool;
                     95: }
                     96: 
                     97: 
                     98: static ngx_inline void
                     99: ngx_regex_malloc_done(void)
                    100: {
                    101: #if (NGX_THREADS)
                    102:     ngx_core_tls_t  *tls;
                    103: 
                    104:     if (ngx_threaded) {
                    105:         tls = ngx_thread_get_tls(ngx_core_tls_key);
                    106:         tls->pool = NULL;
                    107:         return;
                    108:     }
                    109: 
                    110: #endif
                    111: 
                    112:     ngx_pcre_pool = NULL;
                    113: }
                    114: 
                    115: 
                    116: ngx_int_t
                    117: ngx_regex_compile(ngx_regex_compile_t *rc)
                    118: {
                    119:     int               n, erroff;
                    120:     char             *p;
                    121:     pcre             *re;
                    122:     const char       *errstr;
                    123:     ngx_regex_elt_t  *elt;
                    124: 
                    125:     ngx_regex_malloc_init(rc->pool);
                    126: 
                    127:     re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
                    128:                       &errstr, &erroff, NULL);
                    129: 
                    130:     /* ensure that there is no current pool */
                    131:     ngx_regex_malloc_done();
                    132: 
                    133:     if (re == NULL) {
                    134:         if ((size_t) erroff == rc->pattern.len) {
                    135:            rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
                    136:                               "pcre_compile() failed: %s in \"%V\"",
                    137:                                errstr, &rc->pattern)
                    138:                       - rc->err.data;
                    139: 
                    140:         } else {
                    141:            rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
                    142:                               "pcre_compile() failed: %s in \"%V\" at \"%s\"",
                    143:                                errstr, &rc->pattern, rc->pattern.data + erroff)
                    144:                       - rc->err.data;
                    145:         }
                    146: 
                    147:         return NGX_ERROR;
                    148:     }
                    149: 
                    150:     rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t));
                    151:     if (rc->regex == NULL) {
                    152:         return NGX_ERROR;
                    153:     }
                    154: 
                    155:     rc->regex->code = re;
                    156: 
                    157:     /* do not study at runtime */
                    158: 
                    159:     if (ngx_pcre_studies != NULL) {
                    160:         elt = ngx_list_push(ngx_pcre_studies);
                    161:         if (elt == NULL) {
                    162:             return NGX_ERROR;
                    163:         }
                    164: 
                    165:         elt->regex = rc->regex;
                    166:         elt->name = rc->pattern.data;
                    167:     }
                    168: 
                    169:     n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
                    170:     if (n < 0) {
                    171:         p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
                    172:         goto failed;
                    173:     }
                    174: 
                    175:     if (rc->captures == 0) {
                    176:         return NGX_OK;
                    177:     }
                    178: 
                    179:     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
                    180:     if (n < 0) {
                    181:         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
                    182:         goto failed;
                    183:     }
                    184: 
                    185:     if (rc->named_captures == 0) {
                    186:         return NGX_OK;
                    187:     }
                    188: 
                    189:     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
                    190:     if (n < 0) {
                    191:         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
                    192:         goto failed;
                    193:     }
                    194: 
                    195:     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
                    196:     if (n < 0) {
                    197:         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
                    198:         goto failed;
                    199:     }
                    200: 
                    201:     return NGX_OK;
                    202: 
                    203: failed:
                    204: 
                    205:     rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
                    206:                   - rc->err.data;
                    207:     return NGX_OK;
                    208: }
                    209: 
                    210: 
                    211: ngx_int_t
                    212: ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
                    213: {
                    214:     ngx_int_t         n;
                    215:     ngx_uint_t        i;
                    216:     ngx_regex_elt_t  *re;
                    217: 
                    218:     re = a->elts;
                    219: 
                    220:     for (i = 0; i < a->nelts; i++) {
                    221: 
                    222:         n = ngx_regex_exec(re[i].regex, s, NULL, 0);
                    223: 
                    224:         if (n == NGX_REGEX_NO_MATCHED) {
                    225:             continue;
                    226:         }
                    227: 
                    228:         if (n < 0) {
                    229:             ngx_log_error(NGX_LOG_ALERT, log, 0,
                    230:                           ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
                    231:                           n, s, re[i].name);
                    232:             return NGX_ERROR;
                    233:         }
                    234: 
                    235:         /* match */
                    236: 
                    237:         return NGX_OK;
                    238:     }
                    239: 
                    240:     return NGX_DECLINED;
                    241: }
                    242: 
                    243: 
                    244: static void * ngx_libc_cdecl
                    245: ngx_regex_malloc(size_t size)
                    246: {
                    247:     ngx_pool_t      *pool;
                    248: #if (NGX_THREADS)
                    249:     ngx_core_tls_t  *tls;
                    250: 
                    251:     if (ngx_threaded) {
                    252:         tls = ngx_thread_get_tls(ngx_core_tls_key);
                    253:         pool = tls->pool;
                    254: 
                    255:     } else {
                    256:         pool = ngx_pcre_pool;
                    257:     }
                    258: 
                    259: #else
                    260: 
                    261:     pool = ngx_pcre_pool;
                    262: 
                    263: #endif
                    264: 
                    265:     if (pool) {
                    266:         return ngx_palloc(pool, size);
                    267:     }
                    268: 
                    269:     return NULL;
                    270: }
                    271: 
                    272: 
                    273: static void ngx_libc_cdecl
                    274: ngx_regex_free(void *p)
                    275: {
                    276:     return;
                    277: }
                    278: 
                    279: 
                    280: #if (NGX_HAVE_PCRE_JIT)
                    281: 
                    282: static void
                    283: ngx_pcre_free_studies(void *data)
                    284: {
                    285:     ngx_list_t *studies = data;
                    286: 
                    287:     ngx_uint_t        i;
                    288:     ngx_list_part_t  *part;
                    289:     ngx_regex_elt_t  *elts;
                    290: 
                    291:     part = &studies->part;
                    292:     elts = part->elts;
                    293: 
                    294:     for (i = 0 ; /* void */ ; i++) {
                    295: 
                    296:         if (i >= part->nelts) {
                    297:             if (part->next == NULL) {
                    298:                 break;
                    299:             }
                    300: 
                    301:             part = part->next;
                    302:             elts = part->elts;
                    303:             i = 0;
                    304:         }
                    305: 
                    306:         if (elts[i].regex->extra != NULL) {
                    307:             pcre_free_study(elts[i].regex->extra);
                    308:         }
                    309:     }
                    310: }
                    311: 
                    312: #endif
                    313: 
                    314: 
                    315: static ngx_int_t
                    316: ngx_regex_module_init(ngx_cycle_t *cycle)
                    317: {
                    318:     int               opt;
                    319:     const char       *errstr;
                    320:     ngx_uint_t        i;
                    321:     ngx_list_part_t  *part;
                    322:     ngx_regex_elt_t  *elts;
                    323: 
                    324:     opt = 0;
                    325: 
                    326: #if (NGX_HAVE_PCRE_JIT)
                    327:     {
                    328:     ngx_regex_conf_t    *rcf;
                    329:     ngx_pool_cleanup_t  *cln;
                    330: 
                    331:     rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
                    332: 
                    333:     if (rcf->pcre_jit) {
                    334:         opt = PCRE_STUDY_JIT_COMPILE;
                    335: 
                    336:         /*
                    337:          * The PCRE JIT compiler uses mmap for its executable codes, so we
                    338:          * have to explicitly call the pcre_free_study() function to free
                    339:          * this memory.
                    340:          */
                    341: 
                    342:         cln = ngx_pool_cleanup_add(cycle->pool, 0);
                    343:         if (cln == NULL) {
                    344:             return NGX_ERROR;
                    345:         }
                    346: 
                    347:         cln->handler = ngx_pcre_free_studies;
                    348:         cln->data = ngx_pcre_studies;
                    349:     }
                    350:     }
                    351: #endif
                    352: 
                    353:     ngx_regex_malloc_init(cycle->pool);
                    354: 
                    355:     part = &ngx_pcre_studies->part;
                    356:     elts = part->elts;
                    357: 
                    358:     for (i = 0 ; /* void */ ; i++) {
                    359: 
                    360:         if (i >= part->nelts) {
                    361:             if (part->next == NULL) {
                    362:                 break;
                    363:             }
                    364: 
                    365:             part = part->next;
                    366:             elts = part->elts;
                    367:             i = 0;
                    368:         }
                    369: 
                    370:         elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr);
                    371: 
                    372:         if (errstr != NULL) {
                    373:             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    374:                           "pcre_study() failed: %s in \"%s\"",
                    375:                           errstr, elts[i].name);
                    376:         }
                    377: 
                    378: #if (NGX_HAVE_PCRE_JIT)
                    379:         if (opt & PCRE_STUDY_JIT_COMPILE) {
                    380:             int jit, n;
                    381: 
                    382:             jit = 0;
                    383:             n = pcre_fullinfo(elts[i].regex->code, elts[i].regex->extra,
                    384:                               PCRE_INFO_JIT, &jit);
                    385: 
                    386:             if (n != 0 || jit != 1) {
                    387:                 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
                    388:                               "JIT compiler does not support pattern: \"%s\"",
                    389:                               elts[i].name);
                    390:             }
                    391:         }
                    392: #endif
                    393:     }
                    394: 
                    395:     ngx_regex_malloc_done();
                    396: 
                    397:     ngx_pcre_studies = NULL;
                    398: 
                    399:     return NGX_OK;
                    400: }
                    401: 
                    402: 
                    403: static void *
                    404: ngx_regex_create_conf(ngx_cycle_t *cycle)
                    405: {
                    406:     ngx_regex_conf_t  *rcf;
                    407: 
                    408:     rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
                    409:     if (rcf == NULL) {
                    410:         return NULL;
                    411:     }
                    412: 
                    413:     rcf->pcre_jit = NGX_CONF_UNSET;
                    414: 
                    415:     ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
                    416:     if (ngx_pcre_studies == NULL) {
                    417:         return NULL;
                    418:     }
                    419: 
                    420:     return rcf;
                    421: }
                    422: 
                    423: 
                    424: static char *
                    425: ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf)
                    426: {
                    427:     ngx_regex_conf_t *rcf = conf;
                    428: 
                    429:     ngx_conf_init_value(rcf->pcre_jit, 0);
                    430: 
                    431:     return NGX_CONF_OK;
                    432: }
                    433: 
                    434: 
                    435: static char *
                    436: ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
                    437: {
                    438:     ngx_flag_t  *fp = data;
                    439: 
                    440:     if (*fp == 0) {
                    441:         return NGX_CONF_OK;
                    442:     }
                    443: 
                    444: #if (NGX_HAVE_PCRE_JIT)
                    445:     {
                    446:     int  jit, r;
                    447: 
                    448:     jit = 0;
                    449:     r = pcre_config(PCRE_CONFIG_JIT, &jit);
                    450: 
                    451:     if (r != 0 || jit != 1) {
                    452:         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                    453:                            "PCRE library does not support JIT");
                    454:         *fp = 0;
                    455:     }
                    456:     }
                    457: #else
                    458:     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                    459:                        "nginx was built without PCRE JIT support");
                    460:     *fp = 0;
                    461: #endif
                    462: 
                    463:     return NGX_CONF_OK;
                    464: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>