ngtcp2: Use APK style release number
[feed/packages.git] / net / uwsgi / patches / 020-add-pcre2-support.patch
1 From 7835662f76831a76e4cc04791fcf2ee1ea725931 Mon Sep 17 00:00:00 2001
2 From: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
3 Date: Tue, 25 Jul 2023 16:17:52 +0200
4 Subject: [PATCH 01/12] uwsgiconfig: prepare for pcre2
5
6 ---
7 uwsgiconfig.py | 45 ++++++++++++++++++++++-----------------------
8 1 file changed, 22 insertions(+), 23 deletions(-)
9
10 --- a/uwsgiconfig.py
11 +++ b/uwsgiconfig.py
12 @@ -1079,30 +1079,29 @@ class uConf(object):
13
14 has_pcre = False
15
16 - # re-enable after pcre fix
17 - if self.get('pcre'):
18 - if self.get('pcre') == 'auto':
19 - pcreconf = spcall('pcre-config --libs')
20 - if pcreconf:
21 - self.libs.append(pcreconf)
22 - pcreconf = spcall("pcre-config --cflags")
23 - self.cflags.append(pcreconf)
24 - self.gcc_list.append('core/regexp')
25 - self.cflags.append("-DUWSGI_PCRE")
26 - has_pcre = True
27 -
28 + required_pcre = self.get('pcre')
29 + if required_pcre:
30 + pcre_libs = spcall('pcre2-config --libs8')
31 + if pcre_libs:
32 + pcre_cflags = spcall("pcre2-config --cflags")
33 + pcre_define = "-DUWSGI_PCRE2"
34 else:
35 - pcreconf = spcall('pcre-config --libs')
36 - if pcreconf is None:
37 - print("*** libpcre headers unavailable. uWSGI build is interrupted. You have to install pcre development package or disable pcre")
38 - sys.exit(1)
39 - else:
40 - self.libs.append(pcreconf)
41 - pcreconf = spcall("pcre-config --cflags")
42 - self.cflags.append(pcreconf)
43 - self.gcc_list.append('core/regexp')
44 - self.cflags.append("-DUWSGI_PCRE")
45 - has_pcre = True
46 + pcre_libs = spcall('pcre-config --libs')
47 + pcre_cflags = spcall("pcre-config --cflags")
48 + pcre_define = "-DUWSGI_PCRE"
49 + else:
50 + pcre_libs = None
51 +
52 + if required_pcre:
53 + if required_pcre != 'auto' and pcre_libs is None:
54 + print("*** libpcre headers unavailable. uWSGI build is interrupted. You have to install pcre development package or disable pcre")
55 + sys.exit(1)
56 +
57 + self.libs.append(pcre_libs)
58 + self.cflags.append(pcre_cflags)
59 + self.gcc_list.append('core/regexp')
60 + self.cflags.append(pcre_define)
61 + has_pcre = True
62
63 if has_pcre:
64 report['pcre'] = True
65 --- a/core/alarm.c
66 +++ b/core/alarm.c
67 @@ -160,7 +160,7 @@ static struct uwsgi_alarm_instance *uwsg
68 }
69
70
71 -#ifdef UWSGI_PCRE
72 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
73 static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
74
75 struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
76 @@ -170,7 +170,7 @@ static int uwsgi_alarm_log_add(char *ala
77 }
78
79 ual = uwsgi_calloc(sizeof(struct uwsgi_alarm_log));
80 - if (uwsgi_regexp_build(regexp, &ual->pattern, &ual->pattern_extra)) {
81 + if (uwsgi_regexp_build(regexp, &ual->pattern)) {
82 free(ual);
83 return -1;
84 }
85 @@ -331,7 +331,7 @@ void uwsgi_alarms_init() {
86 usl = usl->next;
87 }
88
89 -#ifdef UWSGI_PCRE
90 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
91 // then map log-alarm
92 usl = uwsgi.alarm_logs_list;
93 while (usl) {
94 @@ -377,14 +377,14 @@ void uwsgi_alarm_trigger_uai(struct uwsg
95 }
96 }
97
98 -#ifdef UWSGI_PCRE
99 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
100 // check if a log should raise an alarm
101 void uwsgi_alarm_log_check(char *msg, size_t len) {
102 if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12))
103 return;
104 struct uwsgi_alarm_log *ual = uwsgi.alarm_logs;
105 while (ual) {
106 - if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
107 + if (uwsgi_regexp_match(ual->pattern, msg, len) >= 0) {
108 if (!ual->negate) {
109 struct uwsgi_alarm_ll *uall = ual->alarms;
110 while (uall) {
111 --- a/core/logging.c
112 +++ b/core/logging.c
113 @@ -414,7 +414,7 @@ void uwsgi_setup_log_master(void) {
114 usl = usl->next;
115 }
116
117 -#ifdef UWSGI_PCRE
118 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
119 // set logger by its id
120 struct uwsgi_regexp_list *url = uwsgi.log_route;
121 while (url) {
122 @@ -1398,11 +1398,11 @@ int uwsgi_master_log(void) {
123
124 ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
125 if (rlen > 0) {
126 -#ifdef UWSGI_PCRE
127 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
128 uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen);
129 struct uwsgi_regexp_list *url = uwsgi.log_drain_rules;
130 while (url) {
131 - if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
132 + if (uwsgi_regexp_match(url->pattern, uwsgi.log_master_buf, rlen) >= 0) {
133 return 0;
134 }
135 url = url->next;
136 @@ -1411,7 +1411,7 @@ int uwsgi_master_log(void) {
137 int show = 0;
138 url = uwsgi.log_filter_rules;
139 while (url) {
140 - if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
141 + if (uwsgi_regexp_match(url->pattern, uwsgi.log_master_buf, rlen) >= 0) {
142 show = 1;
143 break;
144 }
145 @@ -1424,7 +1424,7 @@ int uwsgi_master_log(void) {
146 url = uwsgi.log_route;
147 int finish = 0;
148 while (url) {
149 - if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
150 + if (uwsgi_regexp_match(url->pattern, uwsgi.log_master_buf, rlen) >= 0) {
151 struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
152 if (ul_route) {
153 uwsgi_log_func_do(uwsgi.requested_log_encoders, ul_route, uwsgi.log_master_buf, rlen);
154 @@ -1464,11 +1464,11 @@ int uwsgi_master_req_log(void) {
155
156 ssize_t rlen = read(uwsgi.shared->worker_req_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
157 if (rlen > 0) {
158 -#ifdef UWSGI_PCRE
159 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
160 struct uwsgi_regexp_list *url = uwsgi.log_req_route;
161 int finish = 0;
162 while (url) {
163 - if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
164 + if (uwsgi_regexp_match(url->pattern, uwsgi.log_master_buf, rlen) >= 0) {
165 struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
166 if (ul_route) {
167 uwsgi_log_func_do(uwsgi.requested_log_req_encoders, ul_route, uwsgi.log_master_buf, rlen);
168 --- a/core/regexp.c
169 +++ b/core/regexp.c
170 @@ -1,4 +1,4 @@
171 -#ifdef UWSGI_PCRE
172 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
173 #include "uwsgi.h"
174
175 extern struct uwsgi_server uwsgi;
176 @@ -13,48 +13,110 @@ void uwsgi_opt_pcre_jit(char *opt, char
177 #endif
178 }
179
180 -int uwsgi_regexp_build(char *re, pcre ** pattern, pcre_extra ** pattern_extra) {
181 +int uwsgi_regexp_build(char *re, uwsgi_pcre ** pattern) {
182
183 +#ifdef UWSGI_PCRE2
184 + int errnbr;
185 + long unsigned int erroff;
186 +
187 + *pattern = pcre2_compile((const unsigned char *) re, PCRE2_ZERO_TERMINATED, 0, &errnbr, &erroff, NULL);
188 +#else
189 const char *errstr;
190 int erroff;
191
192 - *pattern = pcre_compile((const char *) re, 0, &errstr, &erroff, NULL);
193 - if (!*pattern) {
194 + *pattern = uwsgi_malloc(sizeof(uwsgi_pcre));
195 + (*pattern)->p = pcre_compile((const char *) re, 0, &errstr, &erroff, NULL);
196 +#endif
197 +#ifdef UWSGI_PCRE2
198 + if (!(*pattern)) {
199 + uwsgi_log("pcre error: code %d at offset %d\n", errnbr, erroff);
200 +#else
201 + if (!((*pattern)->p)) {
202 uwsgi_log("pcre error: %s at offset %d\n", errstr, erroff);
203 +#endif
204 return -1;
205 }
206
207 +#ifdef UWSGI_PCRE2
208 + if (uwsgi.pcre_jit) {
209 + errnbr = pcre2_jit_compile(*pattern, PCRE2_JIT_COMPLETE);
210 + if (errnbr) {
211 + pcre2_code_free(*pattern);
212 + uwsgi_log("pcre JIT compile error code %d\n", errnbr);
213 + return -1;
214 + }
215 +#else
216 int opt = uwsgi.pcre_jit;
217
218 - *pattern_extra = (pcre_extra *) pcre_study((const pcre *) *pattern, opt, &errstr);
219 - if (*pattern_extra == NULL && errstr != NULL) {
220 - pcre_free(*pattern);
221 + (*pattern)->extra = (pcre_extra *) pcre_study((const pcre *) (*pattern)->p, opt, &errstr);
222 + if ((*pattern)->extra == NULL && errstr != NULL) {
223 + pcre_free((*pattern)->p);
224 + free(*pattern);
225 uwsgi_log("pcre (study) error: %s\n", errstr);
226 return -1;
227 +#endif
228 }
229
230 return 0;
231
232 }
233
234 -int uwsgi_regexp_match(pcre * pattern, pcre_extra * pattern_extra, char *subject, int length) {
235 -
236 - return pcre_exec((const pcre *) pattern, (const pcre_extra *) pattern_extra, subject, length, 0, 0, NULL, 0);
237 +int uwsgi_regexp_match(uwsgi_pcre *pattern, const char *subject, int length) {
238 +#ifdef UWSGI_PCRE2
239 + return pcre2_match(pattern, (const unsigned char *)subject, length, 0, 0, NULL, NULL);
240 +#else
241 + return pcre_exec((const pcre *) pattern->p, (const pcre_extra *) pattern->extra, subject, length, 0, 0, NULL, 0);
242 +#endif
243 }
244
245 -int uwsgi_regexp_match_ovec(pcre * pattern, pcre_extra * pattern_extra, char *subject, int length, int *ovec, int n) {
246 +int uwsgi_regexp_match_ovec(uwsgi_pcre *pattern, const char *subject, int length, int *ovec, int n) {
247 +
248 +#ifdef UWSGI_PCRE2
249 + int rc;
250 + int i;
251 + pcre2_match_data *match_data;
252 + size_t *pcre2_ovec;
253 +
254 + match_data = pcre2_match_data_create_from_pattern(pattern, NULL);
255 + rc = pcre2_match(pattern, (const unsigned char *)subject, length, 0, 0, match_data, NULL);
256
257 + /*
258 + * Quoting PCRE{,2} spec, "The first pair of integers, ovector[0]
259 + * and ovector[1], identify the portion of the subject string matched
260 + * by the entire pattern. The next pair is used for the first capturing
261 + * subpattern, and so on." Therefore, the ovector size is the number of
262 + * capturing subpatterns (INFO_CAPTURECOUNT), from uwsgi_regexp_ovector(),
263 + * as matching pairs, plus room for the first pair.
264 + */
265 if (n > 0) {
266 - return pcre_exec((const pcre *) pattern, (const pcre_extra *) pattern_extra, subject, length, 0, 0, ovec, (n + 1) * 3);
267 + // copy pcre2 output vector to uwsgi output vector
268 + pcre2_ovec = pcre2_get_ovector_pointer(match_data);
269 + for (i=0;i<(n+1)*2;i++) {
270 + ovec[i] = pcre2_ovec[i];
271 + }
272 +#else
273 + if (n > 0) {
274 + return pcre_exec((const pcre *) pattern->p, (const pcre_extra *) pattern->extra, subject, length, 0, 0, ovec, PCRE_OVECTOR_BYTESIZE(n));
275 +#endif
276 }
277 - return pcre_exec((const pcre *) pattern, (const pcre_extra *) pattern_extra, subject, length, 0, 0, NULL, 0);
278 +
279 +#ifdef UWSGI_PCRE2
280 + pcre2_match_data_free(match_data);
281 +
282 + return rc;
283 +#else
284 + return pcre_exec((const pcre *) pattern->p, (const pcre_extra *) pattern->extra, subject, length, 0, 0, NULL, 0);
285 +#endif
286 }
287
288 -int uwsgi_regexp_ovector(pcre * pattern, pcre_extra * pattern_extra) {
289 +int uwsgi_regexp_ovector(const uwsgi_pcre *pattern) {
290
291 int n;
292 -
293 - if (pcre_fullinfo((const pcre *) pattern, (const pcre_extra *) pattern_extra, PCRE_INFO_CAPTURECOUNT, &n))
294 +#ifdef UWSGI_PCRE2
295 + if (pcre2_pattern_info(pattern, PCRE2_INFO_CAPTURECOUNT, &n))
296 +#else
297 + if (pcre_fullinfo((const pcre *) pattern->p, (const pcre_extra *) pattern->extra, PCRE_INFO_CAPTURECOUNT, &n))
298 +#endif
299 return 0;
300
301 return n;
302 @@ -66,7 +128,7 @@ char *uwsgi_regexp_apply_ovec(char *src,
303 int dollar = 0;
304
305 size_t dollars = n;
306 -
307 +
308 for(i=0;i<dst_n;i++) {
309 if (dst[i] == '$') {
310 dollars++;
311 --- a/core/routing.c
312 +++ b/core/routing.c
313 @@ -211,7 +211,7 @@ int uwsgi_apply_routes_do(struct uwsgi_r
314 subject = *subject2 ;
315 subject_len = *subject_len2;
316 }
317 - n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, subject, subject_len, routes->ovector[wsgi_req->async_id], routes->ovn[wsgi_req->async_id]);
318 + n = uwsgi_regexp_match_ovec(routes->pattern, subject, subject_len, routes->ovector[wsgi_req->async_id], routes->ovn[wsgi_req->async_id]);
319 }
320 else {
321 int ret = routes->if_func(wsgi_req, routes);
322 @@ -506,15 +506,15 @@ void uwsgi_fixup_routes(struct uwsgi_rou
323
324 // fill them if needed... (this is an optimization for route with a static subject)
325 if (ur->subject && ur->subject_len) {
326 - if (uwsgi_regexp_build(ur->orig_route, &ur->pattern, &ur->pattern_extra)) {
327 + if (uwsgi_regexp_build(ur->orig_route, &ur->pattern)) {
328 exit(1);
329 }
330
331 int i;
332 for(i=0;i<uwsgi.cores;i++) {
333 - ur->ovn[i] = uwsgi_regexp_ovector(ur->pattern, ur->pattern_extra);
334 + ur->ovn[i] = uwsgi_regexp_ovector(ur->pattern);
335 if (ur->ovn[i] > 0) {
336 - ur->ovector[i] = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn[i] + 1)));
337 + ur->ovector[i] = uwsgi_calloc(sizeof(int) * PCRE_OVECTOR_BYTESIZE(ur->ovn[i]));
338 }
339 }
340 }
341 @@ -1484,38 +1484,47 @@ static int uwsgi_route_condition_regexp(
342 ur->condition_ub[wsgi_req->async_id] = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
343 if (!ur->condition_ub[wsgi_req->async_id]) return -1;
344
345 - pcre *pattern;
346 - pcre_extra *pattern_extra;
347 + uwsgi_pcre *pattern;
348 char *re = uwsgi_concat2n(semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str), "", 0);
349 - if (uwsgi_regexp_build(re, &pattern, &pattern_extra)) {
350 + if (uwsgi_regexp_build(re, &pattern)) {
351 free(re);
352 return -1;
353 }
354 free(re);
355
356 // a condition has no initialized vectors, let's create them
357 - ur->ovn[wsgi_req->async_id] = uwsgi_regexp_ovector(pattern, pattern_extra);
358 + ur->ovn[wsgi_req->async_id] = uwsgi_regexp_ovector(pattern);
359 if (ur->ovn[wsgi_req->async_id] > 0) {
360 ur->ovector[wsgi_req->async_id] = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn[wsgi_req->async_id] + 1)));
361 }
362
363 - if (uwsgi_regexp_match_ovec(pattern, pattern_extra, ur->condition_ub[wsgi_req->async_id]->buf, ur->condition_ub[wsgi_req->async_id]->pos, ur->ovector[wsgi_req->async_id], ur->ovn[wsgi_req->async_id] ) >= 0) {
364 - pcre_free(pattern);
365 + if (uwsgi_regexp_match_ovec(pattern, ur->condition_ub[wsgi_req->async_id]->buf, ur->condition_ub[wsgi_req->async_id]->pos, ur->ovector[wsgi_req->async_id], ur->ovn[wsgi_req->async_id] ) >= 0) {
366 +#ifdef UWSGI_PCRE2
367 + pcre2_code_free(pattern);
368 +#else
369 + pcre_free(pattern->p);
370 #ifdef PCRE_STUDY_JIT_COMPILE
371 - pcre_free_study(pattern_extra);
372 + pcre_free_study(pattern->extra);
373 #else
374 - pcre_free(pattern_extra);
375 + pcre_free(pattern->extra);
376 +#endif
377 + free(pattern);
378 #endif
379 return 1;
380 }
381
382 - pcre_free(pattern);
383 +#ifdef UWSGI_PCRE2
384 + pcre2_code_free(pattern);
385 +#else
386 + pcre_free(pattern->p);
387 #ifdef PCRE_STUDY_JIT_COMPILE
388 - pcre_free_study(pattern_extra);
389 + pcre_free_study(pattern->extra);
390 #else
391 - pcre_free(pattern_extra);
392 + pcre_free(pattern->extra);
393 #endif
394 - return 0;
395 + free(pattern);
396 +#endif
397 + return 0;
398 }
399
400 static int uwsgi_route_condition_empty(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
401 --- a/core/ssl.c
402 +++ b/core/ssl.c
403 @@ -145,10 +145,10 @@ static int uwsgi_sni_cb(SSL *ssl, int *a
404
405 if (uwsgi.subscription_dotsplit) goto end;
406
407 -#ifdef UWSGI_PCRE
408 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
409 struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
410 while(url) {
411 - if (uwsgi_regexp_match(url->pattern, url->pattern_extra, (char *)servername, servername_len) >= 0) {
412 + if (uwsgi_regexp_match(url->pattern, (char *)servername, servername_len) >= 0) {
413 SSL_set_SSL_CTX(ssl, url->custom_ptr);
414 return SSL_TLSEXT_ERR_OK;
415 }
416 @@ -621,7 +621,7 @@ void uwsgi_opt_sni(char *opt, char *valu
417 return;
418 }
419
420 -#ifdef UWSGI_PCRE
421 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
422 if (!strcmp(opt, "sni-regexp")) {
423 struct uwsgi_regexp_list *url = uwsgi_regexp_new_list(&uwsgi.sni_regexp, v);
424 url->custom_ptr = ctx;
425 @@ -630,7 +630,7 @@ void uwsgi_opt_sni(char *opt, char *valu
426 #endif
427 struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, v);
428 usl->custom_ptr = ctx;
429 -#ifdef UWSGI_PCRE
430 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
431 }
432 #endif
433
434 --- a/core/static.c
435 +++ b/core/static.c
436 @@ -35,11 +35,11 @@ int uwsgi_static_want_gzip(struct wsgi_r
437 usl = usl->next;
438 }
439
440 -#ifdef UWSGI_PCRE
441 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
442 // check for regexp
443 struct uwsgi_regexp_list *url = uwsgi.static_gzip;
444 while(url) {
445 - if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
446 + if (uwsgi_regexp_match(url->pattern, filename, *filename_len) >= 0) {
447 goto gzip;
448 }
449 url = url->next;
450 @@ -216,7 +216,7 @@ int uwsgi_add_expires_type(struct wsgi_r
451 return 0;
452 }
453
454 -#ifdef UWSGI_PCRE
455 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
456 int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filename_len, struct stat *st) {
457
458 struct uwsgi_dyn_dict *udd = uwsgi.static_expires;
459 @@ -225,7 +225,7 @@ int uwsgi_add_expires(struct wsgi_reques
460 char expires[31];
461
462 while (udd) {
463 - if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
464 + if (uwsgi_regexp_match(udd->pattern, filename, filename_len) >= 0) {
465 int delta = uwsgi_str_num(udd->value, udd->vallen);
466 int size = uwsgi_http_date(now + delta, expires);
467 if (size > 0) {
468 @@ -238,7 +238,7 @@ int uwsgi_add_expires(struct wsgi_reques
469
470 udd = uwsgi.static_expires_mtime;
471 while (udd) {
472 - if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
473 + if (uwsgi_regexp_match(udd->pattern, filename, filename_len) >= 0) {
474 int delta = uwsgi_str_num(udd->value, udd->vallen);
475 int size = uwsgi_http_date(st->st_mtime + delta, expires);
476 if (size > 0) {
477 @@ -260,7 +260,7 @@ int uwsgi_add_expires_path_info(struct w
478 char expires[31];
479
480 while (udd) {
481 - if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
482 + if (uwsgi_regexp_match(udd->pattern, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
483 int delta = uwsgi_str_num(udd->value, udd->vallen);
484 int size = uwsgi_http_date(now + delta, expires);
485 if (size > 0) {
486 @@ -273,7 +273,7 @@ int uwsgi_add_expires_path_info(struct w
487
488 udd = uwsgi.static_expires_path_info_mtime;
489 while (udd) {
490 - if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
491 + if (uwsgi_regexp_match(udd->pattern, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
492 int delta = uwsgi_str_num(udd->value, udd->vallen);
493 int size = uwsgi_http_date(st->st_mtime + delta, expires);
494 if (size > 0) {
495 @@ -295,7 +295,7 @@ int uwsgi_add_expires_uri(struct wsgi_re
496 char expires[31];
497
498 while (udd) {
499 - if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
500 + if (uwsgi_regexp_match(udd->pattern, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
501 int delta = uwsgi_str_num(udd->value, udd->vallen);
502 int size = uwsgi_http_date(now + delta, expires);
503 if (size > 0) {
504 @@ -308,7 +308,7 @@ int uwsgi_add_expires_uri(struct wsgi_re
505
506 udd = uwsgi.static_expires_uri_mtime;
507 while (udd) {
508 - if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
509 + if (uwsgi_regexp_match(udd->pattern, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
510 int delta = uwsgi_str_num(udd->value, udd->vallen);
511 int size = uwsgi_http_date(st->st_mtime + delta, expires);
512 if (size > 0) {
513 @@ -507,7 +507,7 @@ int uwsgi_real_file_serve(struct wsgi_re
514 if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
515 }
516
517 -#ifdef UWSGI_PCRE
518 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
519 uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
520 uwsgi_add_expires_path_info(wsgi_req, st);
521 uwsgi_add_expires_uri(wsgi_req, st);
522 --- a/core/utils.c
523 +++ b/core/utils.c
524 @@ -2301,7 +2301,7 @@ struct uwsgi_string_list *uwsgi_string_n
525 return uwsgi_string;
526 }
527
528 -#ifdef UWSGI_PCRE
529 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
530 struct uwsgi_regexp_list *uwsgi_regexp_custom_new_list(struct uwsgi_regexp_list **list, char *value, char *custom) {
531
532 struct uwsgi_regexp_list *url = *list, *old_url;
533 @@ -2320,7 +2320,7 @@ struct uwsgi_regexp_list *uwsgi_regexp_c
534 old_url->next = url;
535 }
536
537 - if (uwsgi_regexp_build(value, &url->pattern, &url->pattern_extra)) {
538 + if (uwsgi_regexp_build(value, &url->pattern)) {
539 exit(1);
540 }
541 url->next = NULL;
542 @@ -2333,14 +2333,13 @@ struct uwsgi_regexp_list *uwsgi_regexp_c
543
544 int uwsgi_regexp_match_pattern(char *pattern, char *str) {
545
546 - pcre *regexp;
547 - pcre_extra *regexp_extra;
548 + uwsgi_pcre *regexp;
549
550 - if (uwsgi_regexp_build(pattern, &regexp, &regexp_extra))
551 + if (uwsgi_regexp_build(pattern, &regexp))
552 return 1;
553 - return !uwsgi_regexp_match(regexp, regexp_extra, str, strlen(str));
554 -}
555
556 + return !uwsgi_regexp_match(regexp, str, strlen(str));
557 +}
558
559 #endif
560
561 --- a/core/uwsgi.c
562 +++ b/core/uwsgi.c
563 @@ -130,7 +130,7 @@ static struct uwsgi_option uwsgi_base_op
564 {"if-hostname", required_argument, 0, "(opt logic) check for hostname", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_hostname, UWSGI_OPT_IMMEDIATE},
565 {"if-not-hostname", required_argument, 0, "(opt logic) check for hostname", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_hostname, UWSGI_OPT_IMMEDIATE},
566
567 -#ifdef UWSGI_PCRE
568 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
569 {"if-hostname-match", required_argument, 0, "(opt logic) try to match hostname against a regular expression", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_hostname_match, UWSGI_OPT_IMMEDIATE},
570 {"if-not-hostname-match", required_argument, 0, "(opt logic) try to match hostname against a regular expression", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_hostname_match, UWSGI_OPT_IMMEDIATE},
571 #endif
572 @@ -548,7 +548,7 @@ static struct uwsgi_option uwsgi_base_op
573 {"ksm", optional_argument, 0, "enable Linux KSM", uwsgi_opt_set_int, &uwsgi.linux_ksm, 0},
574 #endif
575 #endif
576 -#ifdef UWSGI_PCRE
577 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
578 {"pcre-jit", no_argument, 0, "enable pcre jit (if available)", uwsgi_opt_pcre_jit, NULL, UWSGI_OPT_IMMEDIATE},
579 #endif
580 {"never-swap", no_argument, 0, "lock all memory pages avoiding swapping", uwsgi_opt_true, &uwsgi.never_swap, 0},
581 @@ -679,7 +679,7 @@ static struct uwsgi_option uwsgi_base_op
582 {"ssl-enable-sslv3", no_argument, 0, "enable SSLv3 (insecure)", uwsgi_opt_true, &uwsgi.sslv3, 0},
583 {"ssl-enable-tlsv1", no_argument, 0, "enable TLSv1 (insecure)", uwsgi_opt_true, &uwsgi.tlsv1, 0},
584 {"ssl-option", required_argument, 0, "set a raw ssl option (numeric value)", uwsgi_opt_add_string_list, &uwsgi.ssl_options, 0},
585 -#ifdef UWSGI_PCRE
586 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
587 {"sni-regexp", required_argument, 0, "add an SNI-governed SSL context (the key is a regexp)", uwsgi_opt_sni, NULL, 0},
588 #endif
589 {"ssl-tmp-dir", required_argument, 0, "store ssl-related temp files in the specified directory", uwsgi_opt_set_str, &uwsgi.ssl_tmp_dir, 0},
590 @@ -715,7 +715,7 @@ static struct uwsgi_option uwsgi_base_op
591 {"log-req-encoder", required_argument, 0, "add an item in the log req encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_req_encoders, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
592
593
594 -#ifdef UWSGI_PCRE
595 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
596 {"log-drain", required_argument, 0, "drain (do not show) log lines matching the specified regexp", uwsgi_opt_add_regexp_list, &uwsgi.log_drain_rules, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
597 {"log-filter", required_argument, 0, "show only log lines matching the specified regexp", uwsgi_opt_add_regexp_list, &uwsgi.log_filter_rules, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
598 {"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
599 @@ -736,7 +736,7 @@ static struct uwsgi_option uwsgi_base_op
600 {"alarm-lq", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
601 {"alarm-listen-queue", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
602 {"listen-queue-alarm", required_argument, 0, "raise the specified alarm when the socket backlog queue is full", uwsgi_opt_add_string_list, &uwsgi.alarm_backlog, UWSGI_OPT_MASTER},
603 -#ifdef UWSGI_PCRE
604 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
605 {"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
606 {"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
607 {"not-log-alarm", required_argument, 0, "skip the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list_custom, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
608 @@ -915,7 +915,7 @@ static struct uwsgi_option uwsgi_base_op
609 {"static-expires-type", required_argument, 0, "set the Expires header based on content type", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type, UWSGI_OPT_MIME},
610 {"static-expires-type-mtime", required_argument, 0, "set the Expires header based on content type and file mtime", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type_mtime, UWSGI_OPT_MIME},
611
612 -#ifdef UWSGI_PCRE
613 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
614 {"static-expires", required_argument, 0, "set the Expires header based on filename regexp", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires, UWSGI_OPT_MIME},
615 {"static-expires-mtime", required_argument, 0, "set the Expires header based on filename regexp and file mtime", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires_mtime, UWSGI_OPT_MIME},
616
617 @@ -2424,7 +2424,7 @@ void uwsgi_setup(int argc, char *argv[],
618 }
619
620 uwsgi_log_initial("clock source: %s\n", uwsgi.clock->name);
621 -#ifdef UWSGI_PCRE
622 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
623 if (uwsgi.pcre_jit) {
624 uwsgi_log_initial("pcre jit enabled\n");
625 }
626 @@ -4186,7 +4186,7 @@ void uwsgi_opt_add_string_list_custom(ch
627 usl->custom = 1;
628 }
629
630 -#ifdef UWSGI_PCRE
631 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
632 void uwsgi_opt_add_regexp_list(char *opt, char *value, void *list) {
633 struct uwsgi_regexp_list **ptr = (struct uwsgi_regexp_list **) list;
634 uwsgi_regexp_new_list(ptr, value);
635 @@ -4452,7 +4452,7 @@ void uwsgi_opt_add_dyn_dict(char *opt, c
636
637 }
638
639 -#ifdef UWSGI_PCRE
640 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
641 void uwsgi_opt_add_regexp_dyn_dict(char *opt, char *value, void *dict) {
642
643 char *space = strchr(value, ' ');
644 @@ -4467,7 +4467,7 @@ void uwsgi_opt_add_regexp_dyn_dict(char
645
646 char *regexp = uwsgi_concat2n(value, space - value, "", 0);
647
648 - if (uwsgi_regexp_build(regexp, &new_udd->pattern, &new_udd->pattern_extra)) {
649 + if (uwsgi_regexp_build(regexp, &new_udd->pattern)) {
650 exit(1);
651 }
652
653 --- a/uwsgi.h
654 +++ b/uwsgi.h
655 @@ -438,8 +438,26 @@ struct uwsgi_lock_ops {
656 #define uwsgi_wait_read_req(x) uwsgi.wait_read_hook(x->fd, uwsgi.socket_timeout) ; x->switches++
657 #define uwsgi_wait_write_req(x) uwsgi.wait_write_hook(x->fd, uwsgi.socket_timeout) ; x->switches++
658
659 -#ifdef UWSGI_PCRE
660 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
661 +#ifdef UWSGI_PCRE2
662 +
663 +#define PCRE2_CODE_UNIT_WIDTH 8
664 +#include <pcre2.h>
665 +#define PCRE_OVECTOR_BYTESIZE(n) (n+1)*2
666 +
667 +typedef pcre2_code uwsgi_pcre;
668 +
669 +#else
670 +
671 #include <pcre.h>
672 +#define PCRE_OVECTOR_BYTESIZE(n) (n+1)*3
673 +
674 +typedef struct {
675 + pcre *p;
676 + pcre_extra *extra;
677 +} uwsgi_pcre;
678 +
679 +#endif
680 #endif
681
682 struct uwsgi_dyn_dict {
683 @@ -455,9 +473,8 @@ struct uwsgi_dyn_dict {
684 struct uwsgi_dyn_dict *prev;
685 struct uwsgi_dyn_dict *next;
686
687 -#ifdef UWSGI_PCRE
688 - pcre *pattern;
689 - pcre_extra *pattern_extra;
690 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
691 + uwsgi_pcre *pattern;
692 #endif
693
694 };
695 @@ -468,11 +485,10 @@ struct uwsgi_hook {
696 struct uwsgi_hook *next;
697 };
698
699 -#ifdef UWSGI_PCRE
700 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
701 struct uwsgi_regexp_list {
702
703 - pcre *pattern;
704 - pcre_extra *pattern_extra;
705 + uwsgi_pcre *pattern;
706
707 uint64_t custom;
708 char *custom_str;
709 @@ -1089,11 +1105,11 @@ struct uwsgi_plugin {
710 void (*post_uwsgi_fork) (int);
711 };
712
713 -#ifdef UWSGI_PCRE
714 -int uwsgi_regexp_build(char *, pcre **, pcre_extra **);
715 -int uwsgi_regexp_match(pcre *, pcre_extra *, char *, int);
716 -int uwsgi_regexp_match_ovec(pcre *, pcre_extra *, char *, int, int *, int);
717 -int uwsgi_regexp_ovector(pcre *, pcre_extra *);
718 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
719 +int uwsgi_regexp_build(char *, uwsgi_pcre **);
720 +int uwsgi_regexp_match(uwsgi_pcre *, const char *, int);
721 +int uwsgi_regexp_match_ovec(uwsgi_pcre *, const char *, int, int *, int);
722 +int uwsgi_regexp_ovector(const uwsgi_pcre *);
723 char *uwsgi_regexp_apply_ovec(char *, int, char *, int, int *, int);
724
725 int uwsgi_regexp_match_pattern(char *pattern, char *str);
726 @@ -1182,8 +1198,7 @@ struct uwsgi_spooler {
727
728 struct uwsgi_route {
729
730 - pcre *pattern;
731 - pcre_extra *pattern_extra;
732 + uwsgi_pcre *pattern;
733
734 char *orig_route;
735
736 @@ -1292,15 +1307,14 @@ struct uwsgi_alarm_fd {
737
738 struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int, char *, size_t, char *, size_t);
739
740 -#ifdef UWSGI_PCRE
741 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
742 struct uwsgi_alarm_ll {
743 struct uwsgi_alarm_instance *alarm;
744 struct uwsgi_alarm_ll *next;
745 };
746
747 struct uwsgi_alarm_log {
748 - pcre *pattern;
749 - pcre_extra *pattern_extra;
750 + uwsgi_pcre *pattern;
751 int negate;
752 struct uwsgi_alarm_ll *alarms;
753 struct uwsgi_alarm_log *next;
754 @@ -2234,7 +2248,7 @@ struct uwsgi_server {
755 struct uwsgi_string_list *requested_log_encoders;
756 struct uwsgi_string_list *requested_log_req_encoders;
757
758 -#ifdef UWSGI_PCRE
759 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
760 int pcre_jit;
761 struct uwsgi_regexp_list *log_drain_rules;
762 struct uwsgi_regexp_list *log_filter_rules;
763 @@ -2316,7 +2330,7 @@ struct uwsgi_server {
764 int static_gzip_all;
765 struct uwsgi_string_list *static_gzip_dir;
766 struct uwsgi_string_list *static_gzip_ext;
767 -#ifdef UWSGI_PCRE
768 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
769 struct uwsgi_regexp_list *static_gzip;
770 #endif
771
772 @@ -2715,7 +2729,7 @@ struct uwsgi_server {
773 int ssl_sessions_timeout;
774 struct uwsgi_cache *ssl_sessions_cache;
775 char *ssl_tmp_dir;
776 -#ifdef UWSGI_PCRE
777 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
778 struct uwsgi_regexp_list *sni_regexp;
779 #endif
780 struct uwsgi_string_list *sni;
781 @@ -3584,7 +3598,7 @@ void uwsgi_shutdown_all_sockets(void);
782 void uwsgi_close_all_unshared_sockets(void);
783
784 struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **, char *);
785 -#ifdef UWSGI_PCRE
786 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
787 struct uwsgi_regexp_list *uwsgi_regexp_custom_new_list(struct uwsgi_regexp_list **, char *, char *);
788 #define uwsgi_regexp_new_list(x, y) uwsgi_regexp_custom_new_list(x, y, NULL);
789 #endif
790 @@ -3838,7 +3852,7 @@ void uwsgi_opt_add_addr_list(char *, cha
791 void uwsgi_opt_add_string_list_custom(char *, char *, void *);
792 void uwsgi_opt_add_dyn_dict(char *, char *, void *);
793 void uwsgi_opt_binary_append_data(char *, char *, void *);
794 -#ifdef UWSGI_PCRE
795 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
796 void uwsgi_opt_pcre_jit(char *, char *, void *);
797 void uwsgi_opt_add_regexp_dyn_dict(char *, char *, void *);
798 void uwsgi_opt_add_regexp_list(char *, char *, void *);
799 --- a/.github/workflows/compile-test.yml
800 +++ b/.github/workflows/compile-test.yml
801 @@ -9,6 +9,10 @@ on:
802 jobs:
803 build:
804
805 + strategy:
806 + matrix:
807 + libpcre: [libpcre3-dev, libpcre2-dev]
808 +
809 runs-on: ubuntu-20.04
810
811 steps:
812 @@ -20,7 +24,7 @@ jobs:
813 run: |
814 sudo apt update -qq
815 sudo apt install --no-install-recommends -qqyf python3.8-dev \
816 - libxml2-dev libpcre3-dev libcap2-dev \
817 + libxml2-dev ${{ matrix.libpcre }} libcap2-dev \
818 libargon2-0-dev libsodium-dev \
819 php7.4-dev libphp7.4-embed \
820 liblua5.1-0-dev ruby2.7-dev \
821 --- a/.github/workflows/test.yml
822 +++ b/.github/workflows/test.yml
823 @@ -21,7 +21,7 @@ jobs:
824 run: |
825 sudo apt update -qq
826 sudo apt install --no-install-recommends -qqyf python${{ matrix.python-version }}-dev \
827 - libpcre3-dev libjansson-dev libcap2-dev \
828 + libpcre2-dev libjansson-dev libcap2-dev \
829 curl check
830 - name: Install distutils
831 if: contains(fromJson('["3.6","3.7","3.8","3.9","3.10","3.11"]'), matrix.python-version)
832 --- a/plugins/php/php_plugin.c
833 +++ b/plugins/php/php_plugin.c
834 @@ -16,7 +16,7 @@ struct uwsgi_php {
835 struct uwsgi_string_list *index;
836 struct uwsgi_string_list *set;
837 struct uwsgi_string_list *append_config;
838 -#ifdef UWSGI_PCRE
839 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
840 struct uwsgi_regexp_list *app_bypass;
841 #endif
842 struct uwsgi_string_list *vars;
843 @@ -63,7 +63,7 @@ struct uwsgi_option uwsgi_php_options[]
844 {"php-fallback", required_argument, 0, "run the specified php script when the requested one does not exist", uwsgi_opt_set_str, &uphp.fallback, 0},
845 {"php-fallback2", required_argument, 0, "run the specified php script relative to the document root when the requested one does not exist", uwsgi_opt_set_str, &uphp.fallback2, 0},
846 {"php-fallback-qs", required_argument, 0, "php-fallback with QUERY_STRING set", uwsgi_opt_set_str, &uphp.fallback_qs, 0},
847 -#ifdef UWSGI_PCRE
848 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
849 {"php-app-bypass", required_argument, 0, "if the regexp matches the uri the --php-app is bypassed", uwsgi_opt_add_regexp_list, &uphp.app_bypass, 0},
850 #endif
851 {"php-var", required_argument, 0, "add/overwrite a CGI variable at each request", uwsgi_opt_add_string_list, &uphp.vars, 0},
852 @@ -810,10 +810,14 @@ int uwsgi_php_request(struct wsgi_reques
853 wsgi_req->document_root_len = strlen(wsgi_req->document_root);
854
855 if (uphp.app) {
856 -#ifdef UWSGI_PCRE
857 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
858 struct uwsgi_regexp_list *bypass = uphp.app_bypass;
859 while (bypass) {
860 +#ifdef UWSGI_PCRE2
861 + if (uwsgi_regexp_match(bypass->pattern, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
862 +#else
863 if (uwsgi_regexp_match(bypass->pattern, bypass->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
864 +#endif
865 goto oldstyle;
866 }
867 bypass = bypass->next;
868 @@ -849,7 +853,7 @@ appready:
869 goto secure2;
870 }
871
872 -#ifdef UWSGI_PCRE
873 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
874 oldstyle:
875 #endif
876
877 --- a/core/config.c
878 +++ b/core/config.c
879 @@ -314,7 +314,7 @@ int uwsgi_logic_opt_if_not_hostname(char
880 return 0;
881 }
882
883 -#ifdef UWSGI_PCRE
884 +#if defined(UWSGI_PCRE) || defined(UWSGI_PCRE2)
885 int uwsgi_logic_opt_if_hostname_match(char *key, char *value) {
886 if (uwsgi_regexp_match_pattern(uwsgi.logic_opt_data, uwsgi.hostname)) {
887 add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);