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 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 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 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