]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
It was possible for a reference to a frame which was part of a freed DSP to still be
authorMark Michelson <mmichelson@digium.com>
Thu, 17 Apr 2008 16:28:03 +0000 (16:28 +0000)
committerMark Michelson <mmichelson@digium.com>
Thu, 17 Apr 2008 16:28:03 +0000 (16:28 +0000)
referenced, leading to memory corruption and eventual crashes. This code change ensures
that the dsp is freed when we are finished with the frame. This change is very similar
to a change Russell made with translators back a month or so ago.

(closes issue #11999)
Reported by: destiny6628
Patches:
      11999.patch uploaded by putnopvut (license 60)
Tested by: destiny6628, victoryure

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

include/asterisk/frame.h
main/dsp.c
main/frame.c

index 9165b34e8a83a85b9ac3e56d676f67dc1debfc1e..30686efdea341aa693ded86da72f0ba5841db472 100644 (file)
@@ -131,6 +131,10 @@ enum {
         *  The translator can not be free'd if the frame inside of it still has
         *  this flag set. */
        AST_FRFLAG_FROM_TRANSLATOR = (1 << 1),
+       /*! This frame came from a dsp and is still the original frame.
+        *  The dsp cannot be free'd if the frame inside of it still has
+        *  this flag set. */
+       AST_FRFLAG_FROM_DSP = (1 << 2),
 };
 
 /*! \brief Data structure associated with a single frame of data
index 4ec1a826566cffa531b744c6eea68a5dec034bb2..3caf65027e2b990b4fe3052d2cfa67a668eb9b66 100644 (file)
@@ -1486,6 +1486,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                memset(&dsp->f, 0, sizeof(dsp->f));
                dsp->f.frametype = AST_FRAME_NULL;
                ast_frfree(af);
+               ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
                return &dsp->f;
        }
        if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
@@ -1494,7 +1495,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                dsp->f.frametype = AST_FRAME_CONTROL;
                dsp->f.subclass = AST_CONTROL_BUSY;
                ast_frfree(af);
-               ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
+               ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
                return &dsp->f;
        }
        if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
@@ -1516,6 +1517,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                                        if (chan)
                                                ast_queue_frame(chan, af);
                                        ast_frfree(af);
+                                       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
                                        return &dsp->f;
                                }
                        } else {
@@ -1542,6 +1544,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                                                        ast_queue_frame(chan, af);
                                                ast_frfree(af);
                                        }
+                                       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
                                        return &dsp->f;
                                } else {
                                        memset(&dsp->f, 0, sizeof(dsp->f));
@@ -1559,6 +1562,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                                        if (chan)
                                                ast_queue_frame(chan, af);
                                        ast_frfree(af);
+                                       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
                                        return &dsp->f;
                                }
                        }
@@ -1575,6 +1579,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                                        if (chan)
                                                ast_queue_frame(chan, af);
                                        ast_frfree(af);
+                                       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
                                        return &dsp->f;
                                }
                        } else {
@@ -1588,6 +1593,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                                        if (chan)
                                                ast_queue_frame(chan, af);
                                        ast_frfree(af);
+                                       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
                                        return &dsp->f;
                                }
                        }
@@ -1658,6 +1664,17 @@ void ast_dsp_set_features(struct ast_dsp *dsp, int features)
 
 void ast_dsp_free(struct ast_dsp *dsp)
 {
+       if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
+               /* If this flag is still set, that means that the dsp's destruction 
+                * been torn down, while we still have a frame out there being used.
+                * When ast_frfree() gets called on that frame, this ast_trans_pvt
+                * will get destroyed, too. */
+
+               /* Set the magic hint that this has been requested to be destroyed. */
+               dsp->freqcount = -1;
+
+               return;
+       }
        free(dsp);
 }
 
@@ -1786,3 +1803,17 @@ int ast_dsp_get_tcount(struct ast_dsp *dsp)
 {
        return dsp->tcount;
 }
+
+void ast_dsp_frame_freed(struct ast_frame *fr)
+{
+       struct ast_dsp *dsp;
+
+       ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
+
+       dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
+
+       if (dsp->freqcount != -1)
+               return;
+       
+       ast_dsp_free(dsp);
+}
index 5c4613f4d23832f984401cb1c7782618a14969a5..d2240efb01b4f6d656adac37b0dec266b5a34b6b 100644 (file)
@@ -321,6 +321,8 @@ void ast_frame_free(struct ast_frame *fr, int cache)
 {
        if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR))
                ast_translate_frame_freed(fr);
+       else if (ast_test_flag(fr, AST_FRFLAG_FROM_DSP))
+               ast_dsp_frame_freed(fr);
 
        if (!fr->mallocd)
                return;
@@ -370,6 +372,7 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
        void *newdata;
 
        ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
+       ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
 
        if (!(fr->mallocd & AST_MALLOCD_HDR)) {
                /* Allocate a new header if needed */