From: Naveen Albert Date: Fri, 7 Mar 2025 01:53:50 +0000 (-0500) Subject: config.c: Fix inconsistent pointer logic in ast_variable_update. X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=f0f220b36944dbedc713b1205c9d7d48968a5b36;p=thirdparty%2Fasterisk.git config.c: Fix inconsistent pointer logic in ast_variable_update. Commit 3cab4e7ab4a3ae483430d5f5e8fa167d02a8128c introduced a regression by causing the wrong pointers to be used in certain (more complex) cases. We now take care to ensure the exact same pointers are used as before that commit, and simplify by eliminating the unnecessary second for loop. Resolves: #1147 --- diff --git a/main/config.c b/main/config.c index df67717e22..10798bad14 100644 --- a/main/config.c +++ b/main/config.c @@ -1645,41 +1645,51 @@ int ast_variable_delete(struct ast_category *category, const char *variable, con int ast_variable_update(struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object) { - struct ast_variable *cur, *prev=NULL, *newer=NULL, *matchvar = NULL; + struct ast_variable *cur, *prev = NULL, *newer = NULL; + struct ast_variable *matchcur = NULL, *matchprev = NULL; + /* Find the last match. See comments in ast_variable_retrieve, + * but this ensures updating config sections that inherit from + * templates works properly. */ for (cur = category->root; cur; prev = cur, cur = cur->next) { - if (strcasecmp(cur->name, variable) || - (!ast_strlen_zero(match) && strcasecmp(cur->value, match))) + if (strcasecmp(cur->name, variable) || (!ast_strlen_zero(match) && strcasecmp(cur->value, match))) { + /* Not the same variable, + * or its value doesn't match. */ continue; - matchvar = cur; + } + matchprev = prev; + matchcur = cur; } - for (cur = category->root; cur; prev = cur, cur = cur->next) { - if (cur != matchvar) { - continue; - } - if (!(newer = ast_variable_new(variable, value, cur->file))) - return -1; + if (!matchcur) { + /* Could not find variable to update */ + return -1; + } - ast_variable_move(newer, cur); - newer->object = newer->object || object; + /* Restore pointers from the matching var */ + prev = matchprev; + cur = matchcur; - /* Replace the old node in the list with the new node. */ - newer->next = cur->next; - if (prev) - prev->next = newer; - else - category->root = newer; - if (category->last == cur) - category->last = newer; + if (!(newer = ast_variable_new(variable, value, cur->file))) { + return -1; + } - ast_variable_destroy(cur); + ast_variable_move(newer, cur); + newer->object = newer->object || object; - return 0; + /* Replace the old node in the list with the new node. */ + newer->next = cur->next; + if (prev) { + prev->next = newer; + } else { + category->root = newer; + } + if (category->last == cur) { + category->last = newer; } - /* Could not find variable to update */ - return -1; + ast_variable_destroy(cur); + return 0; } struct ast_category *ast_category_delete(struct ast_config *config,