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 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 = &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) { 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