]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
config.c: Fix inconsistent pointer logic in ast_variable_update.
authorNaveen Albert <asterisk@phreaknet.org>
Fri, 7 Mar 2025 01:53:50 +0000 (20:53 -0500)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Tue, 11 Mar 2025 13:28:45 +0000 (13:28 +0000)
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

main/config.c

index df67717e22b4500fc9cdfe45f051e28a20c4e17a..10798bad141f3f9d878190a8e445050b15794c97 100644 (file)
@@ -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,