1 #include "first.h"
2
3 #include "array.h"
4 #include "configfile.h"
5
6 #include <string.h>
7 #include <stdlib.h>
8
9 #ifdef HAVE_PCRE2_H
10 #define PCRE2_CODE_UNIT_WIDTH 8
11 #include <pcre2.h>
12 #elif defined(HAVE_PCRE_H)
13 #include <pcre.h>
14 #ifndef PCRE_STUDY_JIT_COMPILE
15 #define PCRE_STUDY_JIT_COMPILE 0
16 #define pcre_free_study(x) pcre_free(x)
17 #endif
18 #endif
19
20 __attribute_cold__
data_config_copy(const data_unset * s)21 static data_unset *data_config_copy(const data_unset *s) {
22 data_config *src = (data_config *)s;
23 data_config *ds = data_config_init();
24
25 ds->comp = src->comp;
26 if (!buffer_is_unset(&src->key)) {
27 buffer_copy_buffer(&ds->key, &src->key);
28 ds->comp_key = ds->key.ptr + (src->comp_key - src->key.ptr);
29 }
30 buffer_copy_buffer(&ds->comp_tag, &src->comp_tag);
31 array_copy_array(ds->value, src->value);
32 return (data_unset *)ds;
33 }
34
35 __attribute_cold__
data_config_free(data_unset * d)36 static void data_config_free(data_unset *d) {
37 data_config *ds = (data_config *)d;
38
39 free(ds->key.ptr);
40 free(ds->comp_tag.ptr);
41
42 array_free(ds->value);
43 free(ds->children.data);
44
45 free(ds->string.ptr);
46 #ifdef HAVE_PCRE2_H
47 if (ds->code) pcre2_code_free(ds->code);
48 #if 0 /*(see config_finalize())*/
49 if (ds->match_data) pcre2_match_data_free(ds->match_data);
50 #endif
51 #elif defined(HAVE_PCRE_H)
52 if (ds->regex) pcre_free(ds->regex);
53 if (ds->regex_study) pcre_free_study(ds->regex_study);
54 #endif
55
56 free(d);
57 }
58
data_config_init(void)59 data_config *data_config_init(void) {
60 static const struct data_methods config_fn = {
61 data_config_copy,
62 data_config_free,
63 NULL
64 };
65 data_config *ds = ck_calloc(1, sizeof(*ds));
66
67 ds->comp_key = "";
68 ds->value = array_init(4);
69
70 ds->type = TYPE_CONFIG;
71 ds->fn = &config_fn;
72
73 return ds;
74 }
75
76 #include "log.h"
77
data_config_pcre_compile(data_config * const dc,const int pcre_jit,log_error_st * const errh)78 int data_config_pcre_compile(data_config * const dc, const int pcre_jit, log_error_st * const errh) {
79
80 #ifdef HAVE_PCRE2_H
81
82 int errcode;
83 PCRE2_SIZE erroff;
84 PCRE2_UCHAR errbuf[1024];
85
86 dc->code = pcre2_compile((PCRE2_SPTR)BUF_PTR_LEN(&dc->string),
87 PCRE2_UTF, &errcode, &erroff, NULL);
88 if (NULL == dc->code) {
89 pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));
90 log_error(errh, __FILE__, __LINE__,
91 "pcre2_compile: %s at offset %zu, regex: %s",
92 (char *)errbuf, erroff, dc->string.ptr);
93 return 0;
94 }
95
96 if (pcre_jit) {
97 errcode = pcre2_jit_compile(dc->code, PCRE2_JIT_COMPLETE);
98 if (0 != errcode && errcode != PCRE2_ERROR_JIT_BADOPTION) {
99 pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));
100 log_error(errh, __FILE__, __LINE__,
101 "pcre2_jit_compile: %s, regex: %s",
102 (char *)errbuf, dc->string.ptr);
103 }
104 /*return 0;*/
105 }
106
107 uint32_t captures;
108 errcode = pcre2_pattern_info(dc->code, PCRE2_INFO_CAPTURECOUNT, &captures);
109 if (0 != errcode) {
110 pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));
111 log_error(errh, __FILE__, __LINE__,
112 "pcre2_pattern_info: %s, regex: %s", (char *)errbuf, dc->string.ptr);
113 return 0;
114 }
115 else if (captures > 9) {
116 log_error(errh, __FILE__, __LINE__,
117 "Too many captures in regex, use (?:...) instead of (...): %s",
118 dc->string.ptr);
119 return 0;
120 }
121
122 #if 0 /*(see config_finalize())*/
123 dc->match_data = pcre2_match_data_create_from_pattern(dc->code, NULL);
124 force_assert(dc->match_data);
125 #endif
126
127 return 1;
128
129 #elif defined(HAVE_PCRE_H)
130
131 const char *errptr;
132 int erroff, captures;
133
134 dc->regex = pcre_compile(dc->string.ptr, 0, &errptr, &erroff, NULL);
135 if (NULL == dc->regex) {
136 log_error(errh, __FILE__, __LINE__,
137 "parsing regex failed: %s -> %s at offset %d\n",
138 dc->string.ptr, errptr, erroff);
139 return 0;
140 }
141
142 const int study_options = pcre_jit ? PCRE_STUDY_JIT_COMPILE : 0;
143 dc->regex_study = pcre_study(dc->regex, study_options, &errptr);
144 if (NULL == dc->regex_study && errptr != NULL) {
145 log_error(errh, __FILE__, __LINE__,
146 "studying regex failed: %s -> %s\n",
147 dc->string.ptr, errptr);
148 return 0;
149 }
150
151 erroff = pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT,
152 &captures);
153 if (0 != erroff) {
154 log_error(errh, __FILE__, __LINE__,
155 "getting capture count for regex failed: %s\n",
156 dc->string.ptr);
157 return 0;
158 }
159 else if (captures > 9) {
160 log_error(errh, __FILE__, __LINE__,
161 "Too many captures in regex, use (?:...) instead of (...): %s\n",
162 dc->string.ptr);
163 return 0;
164 }
165 dc->ovec_nelts = 3 * (captures + 1);
166 return 1;
167
168 #else
169
170 UNUSED(pcre_jit);
171 log_error(errh, __FILE__, __LINE__,
172 "can't handle '%s' as you compiled without pcre support. \n"
173 "(perhaps just a missing pcre-devel package ?) \n",
174 dc->comp_key);
175 return 0;
176
177 #endif
178 }
179