From 5029e78f39fab61f2972184077bef71b994fbbda Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 25 Aug 2021 11:21:07 -0400 Subject: [PATCH] config_options: Handle ACO arrays correctly in generated XML docs. There are 3 separate changes here but they are all closely related: * Only try to set matchfield attributes on 'field' nodes * We need to adjust how we treat the category pointer based on the value of the category_match, to avoid memory corruption. We now generate a regex-like string when match types other than ACO_WHITELIST and ACO_BLACKLIST are used. * Switch app_agent_pool from ACO_BLACKLIST_ARRAY to ACO_BLACKLIST_EXACT since we only have one category we need to ignore, not two. ASTERISK-29614 #close Change-Id: I7be7bdb1bb9814f942bc6bb4fdd0a55a7b7efe1e --- apps/app_agent_pool.c | 10 ++------ main/config_options.c | 60 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c index e83750abf4..e0df4a4f77 100644 --- a/apps/app_agent_pool.c +++ b/apps/app_agent_pool.c @@ -456,17 +456,11 @@ struct agents_cfg { struct ao2_container *agents; }; -static const char *agent_type_blacklist[] = { - "general", - "agents", - NULL, -}; - static struct aco_type agent_type = { .type = ACO_ITEM, .name = "agent-id", - .category_match = ACO_BLACKLIST_ARRAY, - .category = (const char *)agent_type_blacklist, + .category_match = ACO_BLACKLIST_EXACT, + .category = "general", .item_alloc = agent_cfg_alloc, .item_find = agent_cfg_find, .item_offset = offsetof(struct agents_cfg, agents), diff --git a/main/config_options.c b/main/config_options.c index cbd762235d..c59a8b5806 100644 --- a/main/config_options.c +++ b/main/config_options.c @@ -1037,6 +1037,45 @@ static char *complete_config_option(const char *module, const char *option, cons return NULL; } +/*! \internal + * \brief Generate a category match string suitable for display in 'config show help' + */ +static struct ast_str *derive_category_text(enum aco_category_op category_match, const char *category) +{ + struct ast_str *s = ast_str_create(128); + + if (!s) { + return NULL; + } + + switch (category_match) { + case ACO_WHITELIST_ARRAY: + case ACO_BLACKLIST_ARRAY: { + size_t i; + const char **matches = (const char **) category; + ast_str_append(&s, 0, "^("); + for (i = 0; matches[i]; i++) { + ast_str_append(&s, 0, "%s%s", + i ? "|" : "", + matches[i]); + } + ast_str_append(&s, 0, ")$"); + break; + } + case ACO_WHITELIST_EXACT: + case ACO_BLACKLIST_EXACT: + ast_str_set(&s, 0, "^%s$", category); + break; + case ACO_WHITELIST: + case ACO_BLACKLIST: + default: + ast_str_set(&s, 0, "%s", category); + break; + } + + return s; +} + /* Define as 0 if we want to allow configurations to be registered without * documentation */ @@ -1051,6 +1090,7 @@ static int xmldoc_update_config_type(const char *module, const char *name, const RAII_VAR(struct ast_xml_doc_item *, config_info, ao2_find(xmldocs, module, OBJ_KEY), ao2_cleanup); struct ast_xml_doc_item *config_type; struct ast_xml_node *type, *syntax, *matchinfo, *tmp; + struct ast_str *derived_category = NULL; /* If we already have a syntax element, bail. This isn't an error, since we may unload a module which * has updated the docs and then load it again. */ @@ -1083,7 +1123,12 @@ static int xmldoc_update_config_type(const char *module, const char *name, const return XMLDOC_STRICT ? -1 : 0; } - ast_xml_set_text(tmp, category); + derived_category = derive_category_text(category_match, category); + if (derived_category) { + ast_xml_set_text(tmp, ast_str_buffer(derived_category)); + ast_free(derived_category); + } + switch (category_match) { case ACO_WHITELIST: case ACO_WHITELIST_EXACT: @@ -1097,14 +1142,15 @@ static int xmldoc_update_config_type(const char *module, const char *name, const break; } - if (!ast_strlen_zero(matchfield) && !(tmp = ast_xml_new_child(matchinfo, "field"))) { - ast_log(LOG_WARNING, "Could not add %s attribute for type '%s' in module '%s'\n", matchfield, name, module); - return XMLDOC_STRICT ? -1 : 0; + if (!ast_strlen_zero(matchfield)) { + if (!(tmp = ast_xml_new_child(matchinfo, "field"))) { + ast_log(LOG_WARNING, "Could not add %s attribute for type '%s' in module '%s'\n", matchfield, name, module); + return XMLDOC_STRICT ? -1 : 0; + } + ast_xml_set_attribute(tmp, "name", matchfield); + ast_xml_set_text(tmp, matchvalue); } - ast_xml_set_attribute(tmp, "name", matchfield); - ast_xml_set_text(tmp, matchvalue); - if (!config_info || !(config_type = find_xmldoc_type(config_info, name))) { ast_log(LOG_WARNING, "Could not obtain XML documentation item for config type %s\n", name); return XMLDOC_STRICT ? -1 : 0;