[vlc-commits] audio_filter: fix heap write overflow (fix #17879)

Francois Cartegnie git at videolan.org
Tue Jan 24 12:05:46 CET 2017


vlc/vlc-2.2 | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Jan 24 11:21:15 2017 +0100| [184257c6b62082e4116210fe80e7ed021812373b] | committer: Francois Cartegnie

audio_filter: fix heap write overflow (fix #17879)

backport of 74d460175f7b83aa0a92cb82cf5607aede42b195

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=184257c6b62082e4116210fe80e7ed021812373b
---

 modules/audio_filter/stereo_widen.c | 71 ++++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 29 deletions(-)

diff --git a/modules/audio_filter/stereo_widen.c b/modules/audio_filter/stereo_widen.c
index 796468a..9cc652a 100644
--- a/modules/audio_filter/stereo_widen.c
+++ b/modules/audio_filter/stereo_widen.c
@@ -41,15 +41,13 @@ static int paramCallback( vlc_object_t *, char const *, vlc_value_t ,
 
 struct filter_sys_t
 {
-    float *pf_begin;    /* circular buffer to store samples */
+    float *pf_ringbuf;  /* circular buffer to store samples */
     float *pf_write;    /* where to write current sample    */
-    int   i_len;        /* delay in number of samples       */
+    size_t i_len;       /* delay in number of samples       */
     float f_delay;      /* delay in milliseconds            */
     float f_feedback;
     float f_crossfeed;
     float f_dry_mix;
-    bool  b_free_buf;   /* used if callback to delay fails to       *
-                         * allocate buffer, then dont free it twice */
 };
 
 #define HELP_TEXT N_("This filter enhances the stereo effect by "\
@@ -82,7 +80,8 @@ vlc_module_begin ()
     set_capability( "audio filter", 0 )
     set_callbacks( Open, Close )
 
-    add_float( "delay", 20, DELAY_TEXT, DELAY_LONGTEXT, true )
+    add_float_with_range( "delay", 20, 1, 100,
+        DELAY_TEXT, DELAY_LONGTEXT, true )
     add_float_with_range( "feedback", 0.3, 0.0, 0.9,
         FEEDBACK_TEXT, FEEDBACK_LONGTEXT, true )
     add_float_with_range( "crossfeed", 0.3, 0.0, 0.8,
@@ -94,6 +93,25 @@ vlc_module_end ()
 /*****************************************************************************
  * Open: Allocate buffer
  *****************************************************************************/
+static int MakeRingBuffer( float **pp_buffer, size_t *pi_buffer,
+                           float **pp_write, float f_delay, unsigned i_rate )
+{
+    const size_t i_size = (2 * (size_t)(1 + f_delay * i_rate / 1000));
+
+    if( unlikely(SIZE_MAX / sizeof(float) < i_size) )
+        return VLC_EGENERIC;
+
+    float *p_realloc = realloc( *pp_buffer, i_size * sizeof(float) );
+    if( !p_realloc )
+        return VLC_ENOMEM;
+
+    memset( p_realloc, 0, i_size * sizeof(float) );
+    *pp_write = *pp_buffer = p_realloc;
+    *pi_buffer = i_size;
+
+    return VLC_SUCCESS;
+}
+
 static int Open( vlc_object_t *obj )
 {
     filter_t *p_filter  = (filter_t *)obj;
@@ -123,20 +141,19 @@ static int Open( vlc_object_t *obj )
     CREATE_VAR( f_dry_mix, "dry-mix" )
 
     /* Compute buffer length and allocate space */
-    p_sys->i_len = 2 * p_sys->f_delay * p_filter->fmt_in.audio.i_rate / 1000;
-    p_sys->pf_begin = calloc( p_sys->i_len + 2, sizeof(float) );
-    if( unlikely(!p_sys->pf_begin) )
+    p_sys->pf_ringbuf = NULL;
+    p_sys->i_len = 0;
+    if( MakeRingBuffer( &p_sys->pf_ringbuf, &p_sys->i_len, &p_sys->pf_write,
+                        p_sys->f_delay, p_filter->fmt_in.audio.i_rate ) != VLC_SUCCESS )
     {
         free( p_sys );
         return VLC_ENOMEM;
     }
-    p_sys->b_free_buf = true;
-    p_sys->pf_write = p_sys->pf_begin;
+
     p_filter->pf_audio_filter = Filter;
     return VLC_SUCCESS;
 }
 
-
 /*****************************************************************************
  * Filter: process each sample
  *****************************************************************************/
@@ -150,8 +167,8 @@ static block_t *Filter( filter_t *p_filter, block_t *p_block )
     {
         pf_read = p_sys->pf_write + 2;
         /* if at end of buffer put read ptr at begin */
-        if( pf_read > p_sys->pf_begin + p_sys->i_len )
-            pf_read = p_sys->pf_begin;
+        if( pf_read >= p_sys->pf_ringbuf + p_sys->i_len )
+            pf_read = p_sys->pf_ringbuf;
 
         float left  = p_out[0];
         float right = p_out[1];
@@ -160,14 +177,12 @@ static block_t *Filter( filter_t *p_filter, block_t *p_block )
                         - p_sys->f_feedback * pf_read[1];
         *(p_out++) = p_sys->f_dry_mix * right - p_sys->f_crossfeed * left
                         - p_sys->f_feedback * pf_read[0];
-        p_sys->pf_write[0] = left ;
-        p_sys->pf_write[1] = right;
+        *(p_sys->pf_write++) = left ;
+        *(p_sys->pf_write++) = right;
 
         /* if at end of buffer place pf_write at begin */
-        if( p_sys->pf_write  == p_sys->pf_begin + p_sys->i_len )
-            p_sys->pf_write  =  p_sys->pf_begin;
-        else
-            p_sys->pf_write += 2;
+        if( p_sys->pf_write  == p_sys->pf_ringbuf + p_sys->i_len )
+            p_sys->pf_write  =  p_sys->pf_ringbuf;
     }
 
     return p_block;
@@ -189,8 +204,8 @@ static void Close( vlc_object_t *obj )
     DEL_VAR( "crossfeed" );
     DEL_VAR( "dry-mix" );
     var_Destroy( p_filter, "delay" );
-    if( p_sys->b_free_buf )
-        free( p_sys->pf_begin );
+
+    free( p_sys->pf_ringbuf );
     free( p_sys );
 }
 
@@ -210,16 +225,14 @@ static int paramCallback( vlc_object_t *p_this, char const *psz_var,
 
     if( !strcmp( psz_var, "delay" ) )
     {
-        p_sys->f_delay = newval.f_float;
-        /* Free previous buffer and allocate new circular buffer */
-        free( p_sys->pf_begin );
-        p_sys->i_len = 2 * p_sys->f_delay * p_filter->fmt_in.audio.i_rate /1000;
-        p_sys->pf_begin = calloc( p_sys->i_len + 2, sizeof(float) );
-        if( unlikely(!p_sys->pf_begin) )
+        if( MakeRingBuffer( &p_sys->pf_ringbuf, &p_sys->i_len, &p_sys->pf_write,
+                            newval.f_float, p_filter->fmt_in.audio.i_rate ) != VLC_SUCCESS )
         {
-            p_sys->b_free_buf = false;
             msg_Dbg( p_filter, "Couldnt allocate buffer for delay" );
-            Close( p_this );
+        }
+        else
+        {
+            p_sys->f_delay = newval.f_float;
         }
     }
     else if( !strcmp( psz_var, "feedback" ) )



More information about the vlc-commits mailing list