config: bug: Fix SEGV in ast_category_insert when matching category isn't found
authorGeorge Joseph <george.joseph@fairview5.com>
Thu, 18 Sep 2014 14:46:12 +0000 (14:46 +0000)
committerGeorge Joseph <george.joseph@fairview5.com>
Thu, 18 Sep 2014 14:46:12 +0000 (14:46 +0000)
If you call ast_category_insert with a match category that doesn't exist, the
list traverse runs out of 'next' categories and you get a SEGV.  This patch
adds check for the end-of-list condition and changes the signature to return
an int for success/failure indication instead of a void.

The only consumer of this function is manager and it was also changed to use
the return value.

Tested by: George Joseph
Review: https://reviewboard.asterisk.org/r/3993/
........

Merged revisions 423276 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 423277 from http://svn.asterisk.org/svn/asterisk/branches/11
........

Merged revisions 423278 from http://svn.asterisk.org/svn/asterisk/branches/12
........

Merged revisions 423279 from http://svn.asterisk.org/svn/asterisk/branches/13

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@423280 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/config.h
main/config.c
main/manager.c

index 2579ef2..541fea4 100644 (file)
@@ -675,8 +675,11 @@ void ast_category_append(struct ast_config *config, struct ast_category *cat);
  * \details
  * This function is used to insert a new category above another category
  * matching the match parameter.
+ *
+ * \retval 0 if succeeded
+ * \retval -1 if NULL parameters or match category was not found
  */
-void ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match);
+int ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match);
 int ast_category_delete(struct ast_config *cfg, const char *category);
 
 /*!
index 622d6ed..55c40a9 100644 (file)
@@ -783,24 +783,28 @@ void ast_category_append(struct ast_config *config, struct ast_category *categor
        config->current = category;
 }
 
-void ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match)
+int ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match)
 {
        struct ast_category *cur_category;
 
-       if (!cat || !match)
-               return;
+       if (!config || !cat || !match) {
+               return -1;
+       }
        if (!strcasecmp(config->root->name, match)) {
                cat->next = config->root;
                config->root = cat;
-               return;
+               return 0;
        }
-       for (cur_category = config->root; cur_category; cur_category = cur_category->next) {
+       for (cur_category = config->root; cur_category && cur_category->next;
+               cur_category = cur_category->next) {
                if (!strcasecmp(cur_category->next->name, match)) {
                        cat->next = cur_category->next;
                        cur_category->next = cat;
-                       break;
+                       return 0;
                }
        }
+
+       return -1;
 }
 
 static void ast_destroy_template_list(struct ast_category *cat)
index 6545a51..9744ab6 100644 (file)
@@ -3321,7 +3321,11 @@ static enum error_type handle_updates(struct mansession *s, const struct message
                        if (ast_strlen_zero(match)) {
                                ast_category_append(cfg, category);
                        } else {
-                               ast_category_insert(cfg, category, match);
+                               if (ast_category_insert(cfg, category, match)) {
+                                       result = FAILURE_NEWCAT;
+                                       ast_category_destroy(category);
+                                       break;
+                               }
                        }
                } else if (!strcasecmp(action, "renamecat")) {
                        if (ast_strlen_zero(value)) {