config.c: Fix potential memory corruption after [section](+).
authorRichard Mudgett <rmudgett@digium.com>
Mon, 12 Oct 2015 16:20:29 +0000 (11:20 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Mon, 12 Oct 2015 20:11:39 +0000 (15:11 -0500)
The memory corruption could happen if the [section](+) is the last section
in the file with trailing comments.  In this case process_text_line() has
left *last_cat is set to newcat and newcat is destroyed.

Change-Id: I0d1d999f553986f591becd000e7cc6ddfb978d93

main/config.c

index 5fe73b7..25bc013 100644 (file)
@@ -1647,7 +1647,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                 *              You can put a comma-separated list of categories and templates
                 *              and '!' and '+' between parentheses, with obvious meaning.
                 */
-               struct ast_category *newcat = NULL;
+               struct ast_category *newcat;
                char *catname;
 
                c = strchr(cur, ']');
@@ -1660,14 +1660,13 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                if (*c++ != '(')
                        c = NULL;
                catname = cur;
-               if (!(*cat = newcat = ast_category_new(catname,
-                               S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile),
-                               lineno))) {
+               *cat = newcat = ast_category_new(catname,
+                       S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile),
+                       lineno);
+               if (!newcat) {
                        return -1;
                }
                (*cat)->lineno = lineno;
-               *last_var = 0;
-               *last_cat = newcat;
 
                /* add comments */
                if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
@@ -1690,8 +1689,9 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                                } else if (!strcasecmp(cur, "+")) {
                                        *cat = ast_category_get(cfg, catname, NULL);
                                        if (!(*cat)) {
-                                               if (newcat)
+                                               if (newcat) {
                                                        ast_category_destroy(newcat);
+                                               }
                                                ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
                                                return -1;
                                        }
@@ -1717,8 +1717,19 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
                                }
                        }
                }
-               if (newcat)
-                       ast_category_append(cfg, *cat);
+
+               /*
+                * We need to set *last_cat to newcat here regardless.  If the
+                * category is being appended to we have no place for trailing
+                * comments on the appended category.  The appended category
+                * may be in another file or it already has trailing comments
+                * that we would then leak.
+                */
+               *last_var = NULL;
+               *last_cat = newcat;
+               if (newcat) {
+                       ast_category_append(cfg, newcat);
+               }
        } else if (cur[0] == '#') { /* A directive - #include or #exec */
                char *cur2;
                char real_inclusion_name[256];
@@ -1874,7 +1885,7 @@ set_new_variable:
                        } else if ((v = ast_variable_new(cur, ast_strip(c), S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile)))) {
                                v->lineno = lineno;
                                v->object = object;
-                               *last_cat = 0;
+                               *last_cat = NULL;
                                *last_var = v;
                                /* Put and reset comments */
                                v->blanklines = 0;
@@ -1914,8 +1925,8 @@ static struct ast_config *config_text_file_load(const char *database, const char
        struct stat statbuf;
        struct cache_file_mtime *cfmtime = NULL;
        struct cache_file_include *cfinclude;
-       struct ast_variable *last_var = 0;
-       struct ast_category *last_cat = 0;
+       struct ast_variable *last_var = NULL;
+       struct ast_category *last_cat = NULL;
        /*! Growable string buffer */
        struct ast_str *comment_buffer = NULL;  /*!< this will be a comment collector.*/
        struct ast_str *lline_buffer = NULL;    /*!< A buffer for stuff behind the ; */