3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
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
);
23 static ngx_int_t
ngx_regex_module_init(ngx_cycle_t
*cycle
);
25 static void *ngx_regex_create_conf(ngx_cycle_t
*cycle
);
26 static char *ngx_regex_init_conf(ngx_cycle_t
*cycle
, void *conf
);
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
};
32 static ngx_command_t ngx_regex_commands
[] = {
34 { ngx_string("pcre_jit"),
35 NGX_MAIN_CONF
|NGX_DIRECT_CONF
|NGX_CONF_TAKE1
,
36 ngx_conf_set_flag_slot
,
38 offsetof(ngx_regex_conf_t
, pcre_jit
),
39 &ngx_regex_pcre_jit_post
},
45 static ngx_core_module_t ngx_regex_module_ctx
= {
47 ngx_regex_create_conf
,
52 ngx_module_t ngx_regex_module
= {
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 */
68 static ngx_pool_t
*ngx_pcre_pool
;
69 static ngx_list_t
*ngx_pcre_studies
;
75 pcre_malloc
= ngx_regex_malloc
;
76 pcre_free
= ngx_regex_free
;
80 static ngx_inline
void
81 ngx_regex_malloc_init(ngx_pool_t
*pool
)
87 tls
= ngx_thread_get_tls(ngx_core_tls_key
);
98 static ngx_inline
void
99 ngx_regex_malloc_done(void)
105 tls
= ngx_thread_get_tls(ngx_core_tls_key
);
112 ngx_pcre_pool
= NULL
;
117 ngx_regex_compile(ngx_regex_compile_t
*rc
)
123 ngx_regex_elt_t
*elt
;
125 ngx_regex_malloc_init(rc
->pool
);
127 re
= pcre_compile((const char *) rc
->pattern
.data
, (int) rc
->options
,
128 &errstr
, &erroff
, NULL
);
130 /* ensure that there is no current pool */
131 ngx_regex_malloc_done();
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
)
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
)
150 rc
->regex
= ngx_pcalloc(rc
->pool
, sizeof(ngx_regex_t
));
151 if (rc
->regex
== NULL
) {
155 rc
->regex
->code
= re
;
157 /* do not study at runtime */
159 if (ngx_pcre_studies
!= NULL
) {
160 elt
= ngx_list_push(ngx_pcre_studies
);
165 elt
->regex
= rc
->regex
;
166 elt
->name
= rc
->pattern
.data
;
169 n
= pcre_fullinfo(re
, NULL
, PCRE_INFO_CAPTURECOUNT
, &rc
->captures
);
171 p
= "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
175 if (rc
->captures
== 0) {
179 n
= pcre_fullinfo(re
, NULL
, PCRE_INFO_NAMECOUNT
, &rc
->named_captures
);
181 p
= "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
185 if (rc
->named_captures
== 0) {
189 n
= pcre_fullinfo(re
, NULL
, PCRE_INFO_NAMEENTRYSIZE
, &rc
->name_size
);
191 p
= "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
195 n
= pcre_fullinfo(re
, NULL
, PCRE_INFO_NAMETABLE
, &rc
->names
);
197 p
= "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
205 rc
->err
.len
= ngx_snprintf(rc
->err
.data
, rc
->err
.len
, p
, &rc
->pattern
, n
)
212 ngx_regex_exec_array(ngx_array_t
*a
, ngx_str_t
*s
, ngx_log_t
*log
)
220 for (i
= 0; i
< a
->nelts
; i
++) {
222 n
= ngx_regex_exec(re
[i
].regex
, s
, NULL
, 0);
224 if (n
== NGX_REGEX_NO_MATCHED
) {
229 ngx_log_error(NGX_LOG_ALERT
, log
, 0,
230 ngx_regex_exec_n
" failed: %i on \"%V\" using \"%s\"",
244 static void * ngx_libc_cdecl
245 ngx_regex_malloc(size_t size
)
252 tls
= ngx_thread_get_tls(ngx_core_tls_key
);
256 pool
= ngx_pcre_pool
;
261 pool
= ngx_pcre_pool
;
266 return ngx_palloc(pool
, size
);
273 static void ngx_libc_cdecl
274 ngx_regex_free(void *p
)
280 #if (NGX_HAVE_PCRE_JIT)
283 ngx_pcre_free_studies(void *data
)
285 ngx_list_t
*studies
= data
;
288 ngx_list_part_t
*part
;
289 ngx_regex_elt_t
*elts
;
291 part
= &studies
->part
;
294 for (i
= 0 ; /* void */ ; i
++) {
296 if (i
>= part
->nelts
) {
297 if (part
->next
== NULL
) {
306 if (elts
[i
].regex
->extra
!= NULL
) {
307 pcre_free_study(elts
[i
].regex
->extra
);
316 ngx_regex_module_init(ngx_cycle_t
*cycle
)
321 ngx_list_part_t
*part
;
322 ngx_regex_elt_t
*elts
;
326 #if (NGX_HAVE_PCRE_JIT)
328 ngx_regex_conf_t
*rcf
;
329 ngx_pool_cleanup_t
*cln
;
331 rcf
= (ngx_regex_conf_t
*) ngx_get_conf(cycle
->conf_ctx
, ngx_regex_module
);
334 opt
= PCRE_STUDY_JIT_COMPILE
;
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
342 cln
= ngx_pool_cleanup_add(cycle
->pool
, 0);
347 cln
->handler
= ngx_pcre_free_studies
;
348 cln
->data
= ngx_pcre_studies
;
353 ngx_regex_malloc_init(cycle
->pool
);
355 part
= &ngx_pcre_studies
->part
;
358 for (i
= 0 ; /* void */ ; i
++) {
360 if (i
>= part
->nelts
) {
361 if (part
->next
== NULL
) {
370 elts
[i
].regex
->extra
= pcre_study(elts
[i
].regex
->code
, opt
, &errstr
);
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
);
378 #if (NGX_HAVE_PCRE_JIT)
379 if (opt
& PCRE_STUDY_JIT_COMPILE
) {
383 n
= pcre_fullinfo(elts
[i
].regex
->code
, elts
[i
].regex
->extra
,
384 PCRE_INFO_JIT
, &jit
);
386 if (n
!= 0 || jit
!= 1) {
387 ngx_log_error(NGX_LOG_INFO
, cycle
->log
, 0,
388 "JIT compiler does not support pattern: \"%s\"",
395 ngx_regex_malloc_done();
397 ngx_pcre_studies
= NULL
;
404 ngx_regex_create_conf(ngx_cycle_t
*cycle
)
406 ngx_regex_conf_t
*rcf
;
408 rcf
= ngx_pcalloc(cycle
->pool
, sizeof(ngx_regex_conf_t
));
413 rcf
->pcre_jit
= NGX_CONF_UNSET
;
415 ngx_pcre_studies
= ngx_list_create(cycle
->pool
, 8, sizeof(ngx_regex_elt_t
));
416 if (ngx_pcre_studies
== NULL
) {
425 ngx_regex_init_conf(ngx_cycle_t
*cycle
, void *conf
)
427 ngx_regex_conf_t
*rcf
= conf
;
429 ngx_conf_init_value(rcf
->pcre_jit
, 0);
436 ngx_regex_pcre_jit(ngx_conf_t
*cf
, void *post
, void *data
)
438 ngx_flag_t
*fp
= data
;
444 #if (NGX_HAVE_PCRE_JIT)
449 r
= pcre_config(PCRE_CONFIG_JIT
, &jit
);
451 if (r
!= 0 || jit
!= 1) {
452 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
453 "PCRE library does not support JIT");
458 ngx_conf_log_error(NGX_LOG_WARN
, cf
, 0,
459 "nginx was built without PCRE JIT support");