From: Timo Sirainen Date: Wed, 20 Mar 2024 12:25:54 +0000 (+0200) Subject: doveconf: Don't strip key prefix from output if it would result in conflicting wrong... X-Git-Tag: 2.4.0~637 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=16731c1a2dd8cb1455eb0726915b072f394e49f2;p=thirdparty%2Fdovecot%2Fcore.git doveconf: Don't strip key prefix from output if it would result in conflicting wrong output For example with: dict proxy { dict_name = foo dict_proxy_name = bar } If "dict_name" was shortened to just "name", it would actually be parsed as "dict_proxy_name" setting. --- diff --git a/src/config/config-parser.c b/src/config/config-parser.c index 1391afaab6..91b10c4ea4 100644 --- a/src/config/config-parser.c +++ b/src/config/config-parser.c @@ -50,6 +50,7 @@ struct config_parsed { struct config_filter_parser *const *filter_parsers; struct config_module_parser *module_parsers; ARRAY_TYPE(const_string) errors; + HASH_TABLE(const char *, const struct setting_define *) key_hash; }; ARRAY_DEFINE_TYPE(setting_parser_info_p, const struct setting_parser_info *); @@ -2380,6 +2381,26 @@ config_module_parsers_get_setting(const struct config_module_parser *module_pars return str_c(str); } +const struct setting_define * +config_parsed_key_lookup(struct config_parsed *config, const char *key) +{ + const struct config_module_parser *l; + unsigned int key_idx; + + if (hash_table_is_created(config->key_hash)) + return hash_table_lookup(config->key_hash, key); + hash_table_create(&config->key_hash, config->pool, 0, str_hash, strcmp); + + for (l = config->module_parsers; l->info != NULL; l++) { + for (key_idx = 0; l->info->defines[key_idx].key != NULL; key_idx++) { + hash_table_update(config->key_hash, + l->info->defines[key_idx].key, + &l->info->defines[key_idx]); + } + } + return hash_table_lookup(config->key_hash, key); +} + void config_parsed_free(struct config_parsed **_config) { struct config_parsed *config = *_config; @@ -2388,6 +2409,7 @@ void config_parsed_free(struct config_parsed **_config) return; *_config = NULL; + hash_table_destroy(&config->key_hash); pool_unref(&config->pool); } diff --git a/src/config/config-parser.h b/src/config/config-parser.h index 295f6b1464..a29ec3d2e6 100644 --- a/src/config/config-parser.h +++ b/src/config/config-parser.h @@ -91,6 +91,9 @@ void config_fill_set_parser(struct setting_parser_context *parser, const char * config_module_parsers_get_setting(const struct config_module_parser *module_parsers, const char *info_name, const char *key); +/* Lookup setting with the specified key. */ +const struct setting_define * +config_parsed_key_lookup(struct config_parsed *config, const char *key); void config_parsed_free(struct config_parsed **config); void config_parse_load_modules(void); diff --git a/src/config/doveconf.c b/src/config/doveconf.c index cc0013a1fc..0103c00d65 100644 --- a/src/config/doveconf.c +++ b/src/config/doveconf.c @@ -335,7 +335,29 @@ try_strip_prefix(const char **key_prefix, const char *strip_prefix, return; if (strip_prefix2 == NULL) return; - (void)str_begins(*key_prefix, strip_prefix2, key_prefix); + + const char *suffix; + if (str_begins(*key_prefix, strip_prefix2, &suffix)) { + /* Prefix isn't stripped in all situations or it would result + in wrong output. For example: + + *key_prefix = "dict_name" + strip_prefix = "dict_proxy_" + strip_prefix2 = "dict_" + suffix = "name" + + Now if we return "name", it conflicts with "dict_proxy_name" + setting. So if such conflicting setting name exists, don't + strip the prefix. + */ + const char *conflict_key = + t_strconcat(strip_prefix, t_strcut(suffix, '='), NULL); + if (config_parsed_key_lookup(config, conflict_key) == NULL) { + *key_prefix = suffix; + return; + } + + } } static void ATTR_NULL(4)