1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 /* Fluent Bit
4 * ==========
5 * Copyright (C) 2019-2021 The Fluent Bit Authors
6 * Copyright (C) 2015-2018 Treasure Data Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #include <fluent-bit/flb_info.h>
22 #include <fluent-bit/flb_regex.h>
23 #include <fluent-bit/flb_log.h>
24 #include <fluent-bit/flb_mem.h>
25
26 #include <string.h>
27 #include <onigmo.h>
28
29 static int
cb_onig_named(const UChar * name,const UChar * name_end,int ngroup_num,int * group_nums,regex_t * reg,void * data)30 cb_onig_named(const UChar *name, const UChar *name_end,
31 int ngroup_num, int *group_nums,
32 regex_t *reg, void *data)
33 {
34 int i;
35 int gn;
36 struct flb_regex_search *s;
37 OnigRegion *region;
38
39 s = (struct flb_regex_search *) data;
40 region = s->region;
41
42 for (i = 0; i < ngroup_num; i++) {
43 gn = group_nums[i];
44 onig_name_to_backref_number(reg, name, name_end, region);
45
46 if (s->cb_match) {
47 s->cb_match((const char *)name,
48 s->str + region->beg[gn],
49 region->end[gn] - region->beg[gn],
50 s->data);
51 }
52
53 if (region->end[gn] >= 0) {
54 s->last_pos = region->end[gn];
55 }
56 }
57
58 return 0;
59 }
60
str_to_regex(const char * pattern,OnigRegex * reg)61 static int str_to_regex(const char *pattern, OnigRegex *reg)
62 {
63 int ret;
64 int len;
65 const char *start;
66 const char *end;
67 OnigErrorInfo einfo;
68
69 len = strlen(pattern);
70 start = pattern;
71 end = pattern + len;
72
73 if (pattern[0] == '/' && pattern[len - 1] == '/') {
74 start++;
75 end--;
76 }
77
78 ret = onig_new(reg,
79 (const unsigned char *)start, (const unsigned char *)end,
80 ONIG_OPTION_DEFAULT,
81 ONIG_ENCODING_UTF8, ONIG_SYNTAX_RUBY, &einfo);
82
83 if (ret != ONIG_NORMAL) {
84 return -1;
85 }
86 return 0;
87 }
88
89 /* Initialize backend library */
flb_regex_init()90 int flb_regex_init()
91 {
92 return onig_init();
93 }
94
flb_regex_create(const char * pattern)95 struct flb_regex *flb_regex_create(const char *pattern)
96 {
97 int ret;
98 struct flb_regex *r;
99
100 /* Create context */
101 r = flb_malloc(sizeof(struct flb_regex));
102 if (!r) {
103 flb_errno();
104 return NULL;
105 }
106
107 /* Compile pattern */
108 ret = str_to_regex(pattern, (OnigRegex *) &r->regex);
109 if (ret == -1) {
110 flb_free(r);
111 return NULL;
112 }
113
114 return r;
115 }
116
flb_regex_do(struct flb_regex * r,const char * str,size_t slen,struct flb_regex_search * result)117 ssize_t flb_regex_do(struct flb_regex *r, const char *str, size_t slen,
118 struct flb_regex_search *result)
119 {
120 int ret;
121 const char *start;
122 const char *end;
123 const char *range;
124 OnigRegion *region;
125
126 region = onig_region_new();
127 if (!region) {
128 result->region = NULL;
129 return -1;
130 }
131
132 /* Search scope */
133 start = str;
134 end = start + slen;
135 range = end;
136
137 ret = onig_search(r->regex,
138 (const unsigned char *)str,
139 (const unsigned char *)end,
140 (const unsigned char *)start,
141 (const unsigned char *)range,
142 region, ONIG_OPTION_NONE);
143 if (ret == ONIG_MISMATCH) {
144 result->region = NULL;
145 onig_region_free(region, 1);
146 return -1;
147 }
148 else if (ret < 0) {
149 result->region = NULL;
150 onig_region_free(region, 1);
151 return -1;
152 }
153
154 result->region = region;
155 result->str = str;
156
157 ret = region->num_regs - 1;
158
159 if (ret == 0) {
160 result->region = NULL;
161 onig_region_free(region, 1);
162 }
163
164 return ret;
165 }
166
flb_regex_results_get(struct flb_regex_search * result,int i,ptrdiff_t * start,ptrdiff_t * end)167 int flb_regex_results_get(struct flb_regex_search *result, int i,
168 ptrdiff_t *start, ptrdiff_t *end)
169 {
170 OnigRegion *region;
171
172 region = (OnigRegion *) result->region;
173 if (!region) {
174 return -1;
175 }
176
177 if (i >= region->num_regs) {
178 return -1;
179 }
180
181 *start = region->beg[i];
182 *end = region->end[i];
183
184 return 0;
185 }
186
flb_regex_results_release(struct flb_regex_search * result)187 void flb_regex_results_release(struct flb_regex_search *result)
188 {
189 onig_region_free(result->region, 1);
190 }
191
flb_regex_results_size(struct flb_regex_search * result)192 int flb_regex_results_size(struct flb_regex_search *result)
193 {
194 OnigRegion *region;
195
196 region = (OnigRegion *) result->region;
197 if (!region) {
198 return -1;
199 }
200
201 return region->num_regs;
202 }
203
flb_regex_match(struct flb_regex * r,unsigned char * str,size_t slen)204 int flb_regex_match(struct flb_regex *r, unsigned char *str, size_t slen)
205 {
206 int ret;
207 unsigned char *start;
208 unsigned char *end;
209 unsigned char *range;
210
211 /* Search scope */
212 start = (unsigned char *) str;
213 end = start + slen;
214 range = end;
215
216 ret = onig_search(r->regex, str, end, start, range, NULL, ONIG_OPTION_NONE);
217
218 if (ret == ONIG_MISMATCH) {
219 return 0;
220 }
221 else if (ret < 0) {
222 return ret;
223 }
224 return 1;
225 }
226
227
flb_regex_parse(struct flb_regex * r,struct flb_regex_search * result,void (* cb_match)(const char *,const char *,size_t,void *),void * data)228 int flb_regex_parse(struct flb_regex *r, struct flb_regex_search *result,
229 void (*cb_match) (const char *, /* name */
230 const char *, size_t, /* value */
231 void *), /* caller data */
232 void *data)
233 {
234 int ret;
235
236 result->data = data;
237 result->cb_match = cb_match;
238 result->last_pos = -1;
239
240 ret = onig_foreach_name(r->regex, cb_onig_named, result);
241 onig_region_free(result->region, 1);
242
243 if (ret == 0) {
244 return result->last_pos;
245 }
246 return -1;
247 }
248
flb_regex_destroy(struct flb_regex * r)249 int flb_regex_destroy(struct flb_regex *r)
250 {
251 onig_free(r->regex);
252 flb_free(r);
253 return 0;
254 }
255
flb_regex_exit()256 void flb_regex_exit()
257 {
258 onig_end();
259 }
260