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