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>