xref: /lighttpd1.4/src/data_config.c (revision 66698469)
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__
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__
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 	vector_config_weak_clear(&ds->children);
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 
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;
66 
67 	ds = calloc(1, sizeof(*ds));
68 	force_assert(ds);
69 
70 	ds->comp_key = "";
71 	ds->value = array_init(4);
72 	vector_config_weak_init(&ds->children);
73 
74 	ds->type = TYPE_CONFIG;
75 	ds->fn = &config_fn;
76 
77 	return ds;
78 }
79 
80 #include "log.h"
81 
82 int data_config_pcre_compile(data_config * const dc, const int pcre_jit, log_error_st * const errh) {
83 
84   #ifdef HAVE_PCRE2_H
85 
86     int errcode;
87     PCRE2_SIZE erroff;
88     PCRE2_UCHAR errbuf[1024];
89 
90     dc->code = pcre2_compile((PCRE2_SPTR)BUF_PTR_LEN(&dc->string),
91                              PCRE2_UTF, &errcode, &erroff, NULL);
92     if (NULL == dc->code) {
93         pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));
94         log_error(errh, __FILE__, __LINE__,
95                   "pcre2_compile: %s at offset %zu, regex: %s",
96                   (char *)errbuf, erroff, dc->string.ptr);
97         return 0;
98     }
99 
100     if (pcre_jit) {
101         errcode = pcre2_jit_compile(dc->code, PCRE2_JIT_COMPLETE);
102         if (0 != errcode && errcode != PCRE2_ERROR_JIT_BADOPTION) {
103             pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));
104             log_error(errh, __FILE__, __LINE__,
105                       "pcre2_jit_compile: %s, regex: %s",
106                       (char *)errbuf, dc->string.ptr);
107         }
108         /*return 0;*/
109     }
110 
111     uint32_t captures;
112     errcode = pcre2_pattern_info(dc->code, PCRE2_INFO_CAPTURECOUNT, &captures);
113     if (0 != errcode) {
114         pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));
115         log_error(errh, __FILE__, __LINE__,
116           "pcre2_pattern_info: %s, regex: %s", (char *)errbuf, dc->string.ptr);
117         return 0;
118     }
119     else if (captures > 9) {
120         log_error(errh, __FILE__, __LINE__,
121           "Too many captures in regex, use (?:...) instead of (...): %s",
122           dc->string.ptr);
123         return 0;
124     }
125 
126    #if 0 /*(see config_finalize())*/
127     dc->match_data = pcre2_match_data_create_from_pattern(dc->code, NULL);
128     force_assert(dc->match_data);
129    #endif
130 
131     return 1;
132 
133   #elif defined(HAVE_PCRE_H)
134 
135     const char *errptr;
136     int erroff, captures;
137 
138     dc->regex = pcre_compile(dc->string.ptr, 0, &errptr, &erroff, NULL);
139     if (NULL == dc->regex) {
140         log_error(errh, __FILE__, __LINE__,
141                   "parsing regex failed: %s -> %s at offset %d\n",
142                   dc->string.ptr, errptr, erroff);
143         return 0;
144     }
145 
146     const int study_options = pcre_jit ? PCRE_STUDY_JIT_COMPILE : 0;
147     dc->regex_study = pcre_study(dc->regex, study_options, &errptr);
148     if (NULL == dc->regex_study && errptr != NULL) {
149         log_error(errh, __FILE__, __LINE__,
150                   "studying regex failed: %s -> %s\n",
151                   dc->string.ptr, errptr);
152         return 0;
153     }
154 
155     erroff = pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT,
156                            &captures);
157     if (0 != erroff) {
158         log_error(errh, __FILE__, __LINE__,
159                   "getting capture count for regex failed: %s\n",
160                   dc->string.ptr);
161         return 0;
162     }
163     else if (captures > 9) {
164         log_error(errh, __FILE__, __LINE__,
165                   "Too many captures in regex, use (?:...) instead of (...): %s\n",
166                   dc->string.ptr);
167         return 0;
168     }
169     dc->ovec_nelts = 3 * (captures + 1);
170     return 1;
171 
172   #else
173 
174     UNUSED(pcre_jit);
175     log_error(errh, __FILE__, __LINE__,
176               "can't handle '%s' as you compiled without pcre support. \n"
177               "(perhaps just a missing pcre-devel package ?) \n",
178               dc->comp_key);
179     return 0;
180 
181   #endif
182 }
183