xref: /unit/src/nxt_pcre.c (revision 1721:53b6ab9b324b)
1*1721Saxel.duch@nginx.com /*
2*1721Saxel.duch@nginx.com  * Copyright (C) Axel Duch
3*1721Saxel.duch@nginx.com  * Copyright (C) NGINX, Inc.
4*1721Saxel.duch@nginx.com  */
5*1721Saxel.duch@nginx.com 
6*1721Saxel.duch@nginx.com #include <nxt_main.h>
7*1721Saxel.duch@nginx.com #include <nxt_regex.h>
8*1721Saxel.duch@nginx.com #include <pcre.h>
9*1721Saxel.duch@nginx.com 
10*1721Saxel.duch@nginx.com 
11*1721Saxel.duch@nginx.com struct nxt_regex_s {
12*1721Saxel.duch@nginx.com     pcre        *code;
13*1721Saxel.duch@nginx.com     pcre_extra  *extra;
14*1721Saxel.duch@nginx.com     nxt_str_t   pattern;
15*1721Saxel.duch@nginx.com };
16*1721Saxel.duch@nginx.com 
17*1721Saxel.duch@nginx.com struct nxt_regex_match_s {
18*1721Saxel.duch@nginx.com     int  ovecsize;
19*1721Saxel.duch@nginx.com     int  ovec[];
20*1721Saxel.duch@nginx.com };
21*1721Saxel.duch@nginx.com 
22*1721Saxel.duch@nginx.com 
23*1721Saxel.duch@nginx.com static void *nxt_pcre_malloc(size_t size);
24*1721Saxel.duch@nginx.com static void nxt_pcre_free(void *p);
25*1721Saxel.duch@nginx.com 
26*1721Saxel.duch@nginx.com static nxt_mp_t  *nxt_pcre_mp;
27*1721Saxel.duch@nginx.com 
28*1721Saxel.duch@nginx.com 
29*1721Saxel.duch@nginx.com nxt_regex_t *
nxt_regex_compile(nxt_mp_t * mp,nxt_str_t * source,nxt_regex_err_t * err)30*1721Saxel.duch@nginx.com nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, nxt_regex_err_t *err)
31*1721Saxel.duch@nginx.com {
32*1721Saxel.duch@nginx.com     int          erroffset;
33*1721Saxel.duch@nginx.com     char         *pattern;
34*1721Saxel.duch@nginx.com     void         *saved_malloc, *saved_free;
35*1721Saxel.duch@nginx.com     nxt_regex_t  *re;
36*1721Saxel.duch@nginx.com 
37*1721Saxel.duch@nginx.com     err->offset = source->length;
38*1721Saxel.duch@nginx.com 
39*1721Saxel.duch@nginx.com     re = nxt_mp_get(mp, sizeof(nxt_regex_t) + source->length + 1);
40*1721Saxel.duch@nginx.com     if (nxt_slow_path(re == NULL)) {
41*1721Saxel.duch@nginx.com         err->msg = "memory allocation failed";
42*1721Saxel.duch@nginx.com         return NULL;
43*1721Saxel.duch@nginx.com     }
44*1721Saxel.duch@nginx.com 
45*1721Saxel.duch@nginx.com     pattern = nxt_pointer_to(re, sizeof(nxt_regex_t));
46*1721Saxel.duch@nginx.com 
47*1721Saxel.duch@nginx.com     nxt_memcpy(pattern, source->start, source->length);
48*1721Saxel.duch@nginx.com     pattern[source->length] = '\0';
49*1721Saxel.duch@nginx.com 
50*1721Saxel.duch@nginx.com     re->pattern.length = source->length;
51*1721Saxel.duch@nginx.com     re->pattern.start = (u_char *) pattern;
52*1721Saxel.duch@nginx.com 
53*1721Saxel.duch@nginx.com     saved_malloc = pcre_malloc;
54*1721Saxel.duch@nginx.com     saved_free = pcre_free;
55*1721Saxel.duch@nginx.com 
56*1721Saxel.duch@nginx.com     pcre_malloc = nxt_pcre_malloc;
57*1721Saxel.duch@nginx.com     pcre_free = nxt_pcre_free;
58*1721Saxel.duch@nginx.com     nxt_pcre_mp = mp;
59*1721Saxel.duch@nginx.com 
60*1721Saxel.duch@nginx.com     re->code = pcre_compile(pattern, 0, &err->msg, &erroffset, NULL);
61*1721Saxel.duch@nginx.com     if (nxt_fast_path(re->code != NULL)) {
62*1721Saxel.duch@nginx.com #if 0
63*1721Saxel.duch@nginx.com         re->extra = pcre_study(re->code, PCRE_STUDY_JIT_COMPILE, &err->msg);
64*1721Saxel.duch@nginx.com         if (nxt_slow_path(re->extra == NULL && err->msg != NULL)) {
65*1721Saxel.duch@nginx.com             nxt_log_warn(thr->log, "pcre_study(%V) failed: %s", source, err->msg);
66*1721Saxel.duch@nginx.com         }
67*1721Saxel.duch@nginx.com #else
68*1721Saxel.duch@nginx.com         re->extra = NULL;
69*1721Saxel.duch@nginx.com #endif
70*1721Saxel.duch@nginx.com 
71*1721Saxel.duch@nginx.com     } else {
72*1721Saxel.duch@nginx.com         err->offset = erroffset;
73*1721Saxel.duch@nginx.com         re = NULL;
74*1721Saxel.duch@nginx.com     }
75*1721Saxel.duch@nginx.com 
76*1721Saxel.duch@nginx.com     pcre_malloc = saved_malloc;
77*1721Saxel.duch@nginx.com     pcre_free = saved_free;
78*1721Saxel.duch@nginx.com 
79*1721Saxel.duch@nginx.com     return re;
80*1721Saxel.duch@nginx.com }
81*1721Saxel.duch@nginx.com 
82*1721Saxel.duch@nginx.com 
83*1721Saxel.duch@nginx.com static void*
nxt_pcre_malloc(size_t size)84*1721Saxel.duch@nginx.com nxt_pcre_malloc(size_t size)
85*1721Saxel.duch@nginx.com {
86*1721Saxel.duch@nginx.com     if (nxt_slow_path(nxt_pcre_mp == NULL)) {
87*1721Saxel.duch@nginx.com         nxt_thread_log_alert("pcre_malloc(%uz) called without memory pool",
88*1721Saxel.duch@nginx.com                              size);
89*1721Saxel.duch@nginx.com         return NULL;
90*1721Saxel.duch@nginx.com     }
91*1721Saxel.duch@nginx.com 
92*1721Saxel.duch@nginx.com     nxt_thread_log_debug("pcre_malloc(%uz), pool %p", size, nxt_pcre_mp);
93*1721Saxel.duch@nginx.com 
94*1721Saxel.duch@nginx.com     return nxt_mp_get(nxt_pcre_mp, size);
95*1721Saxel.duch@nginx.com }
96*1721Saxel.duch@nginx.com 
97*1721Saxel.duch@nginx.com 
98*1721Saxel.duch@nginx.com static void
nxt_pcre_free(void * p)99*1721Saxel.duch@nginx.com nxt_pcre_free(void *p)
100*1721Saxel.duch@nginx.com {
101*1721Saxel.duch@nginx.com }
102*1721Saxel.duch@nginx.com 
103*1721Saxel.duch@nginx.com 
104*1721Saxel.duch@nginx.com nxt_regex_match_t *
nxt_regex_match_create(nxt_mp_t * mp,size_t size)105*1721Saxel.duch@nginx.com nxt_regex_match_create(nxt_mp_t *mp, size_t size)
106*1721Saxel.duch@nginx.com {
107*1721Saxel.duch@nginx.com     nxt_regex_match_t  *match;
108*1721Saxel.duch@nginx.com 
109*1721Saxel.duch@nginx.com     match = nxt_mp_get(mp, sizeof(nxt_regex_match_t) + sizeof(int) * size);
110*1721Saxel.duch@nginx.com     if (nxt_fast_path(match != NULL)) {
111*1721Saxel.duch@nginx.com         match->ovecsize = size;
112*1721Saxel.duch@nginx.com     }
113*1721Saxel.duch@nginx.com 
114*1721Saxel.duch@nginx.com     return match;
115*1721Saxel.duch@nginx.com }
116*1721Saxel.duch@nginx.com 
117*1721Saxel.duch@nginx.com 
118*1721Saxel.duch@nginx.com nxt_int_t
nxt_regex_match(nxt_regex_t * re,u_char * subject,size_t length,nxt_regex_match_t * match)119*1721Saxel.duch@nginx.com nxt_regex_match(nxt_regex_t *re, u_char *subject, size_t length,
120*1721Saxel.duch@nginx.com     nxt_regex_match_t *match)
121*1721Saxel.duch@nginx.com {
122*1721Saxel.duch@nginx.com     int  ret;
123*1721Saxel.duch@nginx.com 
124*1721Saxel.duch@nginx.com     ret = pcre_exec(re->code, re->extra, (const char *) subject, length, 0, 0,
125*1721Saxel.duch@nginx.com                     match->ovec, match->ovecsize);
126*1721Saxel.duch@nginx.com     if (nxt_slow_path(ret < PCRE_ERROR_NOMATCH)) {
127*1721Saxel.duch@nginx.com         nxt_thread_log_error(NXT_LOG_ERR,
128*1721Saxel.duch@nginx.com                              "pcre_exec() failed: %d on \"%*s\" using \"%V\"",
129*1721Saxel.duch@nginx.com                              ret, length, subject, &re->pattern);
130*1721Saxel.duch@nginx.com 
131*1721Saxel.duch@nginx.com         return NXT_ERROR;
132*1721Saxel.duch@nginx.com     }
133*1721Saxel.duch@nginx.com 
134*1721Saxel.duch@nginx.com     return (ret != PCRE_ERROR_NOMATCH);
135*1721Saxel.duch@nginx.com }
136