]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
main/app.c: Memory corruption from early format destruction. 96/4796/1
authorRichard Mudgett <rmudgett@digium.com>
Tue, 10 Jan 2017 19:11:20 +0000 (13:11 -0600)
committerRichard Mudgett <rmudgett@digium.com>
Tue, 24 Jan 2017 20:04:51 +0000 (14:04 -0600)
* make_silence() created a malloced silence slin frame without adding a
slin format ref.  When the frame is destroyed it will unref the slin
format that never had a ref added.  Memory corruption is expected to
follow.

* Simplified and fixed counting the number of samples in a frame list for
make_silence().

* Eliminated an unnecessary RAII_VAR associated with the make_silence()
frame.

Change-Id: I47de3f9b92635b7f8b4d72309444d6c0aee6f747

main/app.c

index d5e331472d8f6bdce741cd0f61b6cb87f807d927..53b97cdda8fa49cad2700536b002f51d748c0115 100644 (file)
@@ -1424,22 +1424,20 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
        size_t size;
        size_t datalen;
        size_t samples = 0;
-       struct ast_frame *next;
 
        if (!orig) {
                return NULL;
        }
+       do {
+               if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+                       ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
+                       return NULL;
+               }
 
-       if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
-               ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
-               return NULL;
-       }
-
-       for (next = AST_LIST_NEXT(orig, frame_list);
-                orig;
-                orig = next, next = orig ? AST_LIST_NEXT(orig, frame_list) : NULL) {
                samples += orig->samples;
-       }
+
+               orig = AST_LIST_NEXT(orig, frame_list);
+       } while (orig);
 
        ast_verb(4, "Silencing %zu samples\n", samples);
 
@@ -1457,7 +1455,7 @@ static struct ast_frame *make_silence(const struct ast_frame *orig)
        silence->samples = samples;
        silence->datalen = datalen;
 
-       silence->subclass.format = ast_format_slin;
+       silence->subclass.format = ao2_bump(ast_format_slin);
 
        return silence;
 }
@@ -1663,14 +1661,13 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
                                        /* It's all good */
                                        res = 0;
                                } else {
-                                       RAII_VAR(struct ast_frame *, silence, NULL, ast_frame_dtor);
+                                       struct ast_frame *silence = NULL;
                                        struct ast_frame *orig = f;
 
                                        if (muted) {
                                                silence = make_silence(orig);
                                                if (!silence) {
-                                                       ast_log(LOG_WARNING,
-                                                               "Error creating silence\n");
+                                                       ast_log(LOG_WARNING, "Error creating silence\n");
                                                        break;
                                                }
                                                f = silence;
@@ -1681,6 +1678,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
                                                }
                                                res = ast_writestream(others[x], f);
                                        }
+                                       ast_frame_dtor(silence);
                                        f = orig;
                                }