Annotation of embedaddon/nginx/src/core/ngx_regex.c, revision 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>