xref: /lighttpd1.4/src/data_config.c (revision 5e14db43)
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