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>