Return to ngx_regex.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / nginx / src / core |
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: }