1 /*
2 * Copyright (C) Axel Duch
3 * Copyright (C) NGINX, Inc.
4 */
5
6 #include <nxt_main.h>
7 #include <nxt_regex.h>
8
9 #define PCRE2_CODE_UNIT_WIDTH 8
10 #include <pcre2.h>
11
12
13 static void *nxt_pcre2_malloc(PCRE2_SIZE size, void *memory_data);
14 static void nxt_pcre2_free(void *p, void *memory_data);
15
16
17 struct nxt_regex_s {
18 pcre2_code *code;
19 nxt_str_t pattern;
20 };
21
22
23 nxt_regex_t *
nxt_regex_compile(nxt_mp_t * mp,nxt_str_t * source,nxt_regex_err_t * err)24 nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, nxt_regex_err_t *err)
25 {
26 int errcode;
27 nxt_int_t ret;
28 PCRE2_SIZE erroffset;
29 nxt_regex_t *re;
30 pcre2_general_context *general_ctx;
31 pcre2_compile_context *compile_ctx;
32
33 static const u_char alloc_error[] = "memory allocation failed";
34
35 general_ctx = pcre2_general_context_create(nxt_pcre2_malloc,
36 nxt_pcre2_free, mp);
37 if (nxt_slow_path(general_ctx == NULL)) {
38 goto alloc_fail;
39 }
40
41 compile_ctx = pcre2_compile_context_create(general_ctx);
42 if (nxt_slow_path(compile_ctx == NULL)) {
43 goto alloc_fail;
44 }
45
46 re = nxt_mp_get(mp, sizeof(nxt_regex_t));
47 if (nxt_slow_path(re == NULL)) {
48 goto alloc_fail;
49 }
50
51 if (nxt_slow_path(nxt_str_dup(mp, &re->pattern, source) == NULL)) {
52 goto alloc_fail;
53 }
54
55 re->code = pcre2_compile((PCRE2_SPTR) source->start, source->length, 0,
56 &errcode, &erroffset, compile_ctx);
57 if (nxt_slow_path(re->code == NULL)) {
58 err->offset = erroffset;
59
60 ret = pcre2_get_error_message(errcode, (PCRE2_UCHAR *) err->msg,
61 ERR_BUF_SIZE);
62 if (ret < 0) {
63 (void) nxt_sprintf(err->msg, err->msg + ERR_BUF_SIZE,
64 "compilation failed with unknown "
65 "error code: %d%Z", errcode);
66 }
67
68 return NULL;
69 }
70
71 #if 0
72 errcode = pcre2_jit_compile(re, PCRE2_JIT_COMPLETE);
73 if (nxt_slow_path(errcode != 0 && errcode != PCRE2_ERROR_JIT_BADOPTION)) {
74 ret = pcre2_get_error_message(errcode, (PCRE2_UCHAR *) err->msg,
75 ERR_BUF_SIZE);
76 if (ret < 0) {
77 (void) nxt_sprintf(err->msg, err->msg + ERR_BUF_SIZE,
78 "JIT compilation failed with unknown "
79 "error code: %d%Z", errcode);
80 }
81
82 return NULL;
83 }
84 #endif
85
86 return re;
87
88 alloc_fail:
89
90 err->offset = source->length;
91 nxt_memcpy(err->msg, alloc_error, sizeof(alloc_error));
92
93 return NULL;
94 }
95
96
97 static void *
nxt_pcre2_malloc(PCRE2_SIZE size,void * mp)98 nxt_pcre2_malloc(PCRE2_SIZE size, void *mp)
99 {
100 return nxt_mp_get(mp, size);
101 }
102
103
104 static void
nxt_pcre2_free(void * p,void * mp)105 nxt_pcre2_free(void *p, void *mp)
106 {
107 }
108
109
110 nxt_regex_match_t *
nxt_regex_match_create(nxt_mp_t * mp,size_t size)111 nxt_regex_match_create(nxt_mp_t *mp, size_t size)
112 {
113 nxt_regex_match_t *match;
114 pcre2_general_context *ctx;
115
116 ctx = pcre2_general_context_create(nxt_pcre2_malloc, nxt_pcre2_free, mp);
117 if (nxt_slow_path(ctx == NULL)) {
118 nxt_thread_log_alert("pcre2_general_context_create() failed");
119 return NULL;
120 }
121
122 match = pcre2_match_data_create(size, ctx);
123 if (nxt_slow_path(match == NULL)) {
124 nxt_thread_log_alert("pcre2_match_data_create(%uz) failed", size);
125 return NULL;
126 }
127
128 return match;
129 }
130
131
132 nxt_int_t
nxt_regex_match(nxt_regex_t * re,u_char * subject,size_t length,nxt_regex_match_t * match)133 nxt_regex_match(nxt_regex_t *re, u_char *subject, size_t length,
134 nxt_regex_match_t *match)
135 {
136 nxt_int_t ret;
137 PCRE2_UCHAR errptr[ERR_BUF_SIZE];
138
139 ret = pcre2_match(re->code, (PCRE2_SPTR) subject, length, 0, 0, match,
140 NULL);
141
142 if (nxt_slow_path(ret < PCRE2_ERROR_NOMATCH)) {
143
144 if (pcre2_get_error_message(ret, errptr, ERR_BUF_SIZE) < 0) {
145 nxt_thread_log_error(NXT_LOG_ERR,
146 "pcre2_match() failed: %d on \"%*s\" "
147 "using \"%V\"", ret, length, subject,
148 &re->pattern);
149
150 } else {
151 nxt_thread_log_error(NXT_LOG_ERR,
152 "pcre2_match() failed: %s (%d) on \"%*s\" "
153 "using \"%V\"", errptr, ret, length, subject,
154 &re->pattern);
155 }
156
157 return NXT_ERROR;
158 }
159
160 return (ret != PCRE2_ERROR_NOMATCH);
161 }
162