Package: vlc
Version: 2.1.4-1
Severity: important
Tags: patch

Dear Maintainer,

in modules/codec/avcodec/audio.c one finds:
    AVFrame frame;
    memset( &frame, 0, sizeof( frame ) );

According to the documentation of libavutil this is wrong:
"sizeof(AVFrame) is not a part of the public ABI, so new fields may be added to the end with a minor bump."

This code will crash, when used with a different AVFrame at runtime than was available at compile-time.

The attached patch fixes this problem.

Best regards,
Andreas
Description: Fix the use of AVFrame
 AVFrame is not guaranteed to be ABI stable, i.e. new fields can be
 added at any time.
 Therefore it must be allocated with av_frame_alloc to avoid crashes.

Author: Andreas Cadhalpun <andreas.cadhal...@googlemail.com>
Last-Update: <2014-07-28>

--- vlc-2.1.4.orig/modules/codec/avcodec/audio.c
+++ vlc-2.1.4/modules/codec/avcodec/audio.c
@@ -225,6 +225,7 @@ block_t * DecodeAudio ( decoder_t *p_dec
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     AVCodecContext *ctx = p_sys->p_context;
+    AVFrame *frame = NULL;
 
     if( !pp_block || !*pp_block )
         return NULL;
@@ -271,8 +272,7 @@ block_t * DecodeAudio ( decoder_t *p_dec
         p_block->i_flags |= BLOCK_FLAG_PRIVATE_REALLOCATED;
     }
 
-    AVFrame frame;
-    memset( &frame, 0, sizeof( frame ) );
+    frame = av_frame_alloc();
 
     for( int got_frame = 0; !got_frame; )
     {
@@ -284,7 +284,7 @@ block_t * DecodeAudio ( decoder_t *p_dec
         pkt.data = p_block->p_buffer;
         pkt.size = p_block->i_buffer;
 
-        int used = avcodec_decode_audio4( ctx, &frame, &got_frame, &pkt );
+        int used = avcodec_decode_audio4( ctx, frame, &got_frame, &pkt );
         if( used < 0 )
         {
             msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
@@ -320,7 +320,7 @@ block_t * DecodeAudio ( decoder_t *p_dec
     }
 
     /* NOTE WELL: Beyond this point, p_block now refers to the DECODED block */
-    p_block = frame.opaque;
+    p_block = frame->opaque;
     SetupOutputFormat( p_dec, true );
 
     /* Silent unwanted samples */
@@ -336,10 +336,10 @@ block_t * DecodeAudio ( decoder_t *p_dec
         block_Release( p_block );
         if( av_sample_fmt_is_planar( ctx->sample_fmt )
          && ctx->channels > AV_NUM_DATA_POINTERS )
-            free( frame.extended_data );
+            free( frame->extended_data );
         return NULL;
     }
-    assert( p_block->i_nb_samples >= (unsigned)frame.nb_samples );
+    assert( p_block->i_nb_samples >= (unsigned)frame->nb_samples );
     assert( p_block->i_nb_samples == p_buffer->i_nb_samples );
     p_block->i_buffer = p_buffer->i_buffer; /* drop buffer padding */
 
@@ -348,13 +348,13 @@ block_t * DecodeAudio ( decoder_t *p_dec
     {
         const void *planes[ctx->channels];
         for( int i = 0; i < ctx->channels; i++)
-            planes[i] = frame.extended_data[i];
+            planes[i] = frame->extended_data[i];
 
-        aout_Interleave( p_buffer->p_buffer, planes, frame.nb_samples,
+        aout_Interleave( p_buffer->p_buffer, planes, frame->nb_samples,
                          ctx->channels, p_dec->fmt_out.audio.i_format );
 
         if( ctx->channels > AV_NUM_DATA_POINTERS )
-            free( frame.extended_data );
+            free( frame->extended_data );
         block_Release( p_block );
         p_block = p_buffer;
     }
@@ -364,7 +364,7 @@ block_t * DecodeAudio ( decoder_t *p_dec
     if (p_sys->b_extract)
     {   /* TODO: do not drop channels... at least not here */
         p_buffer = block_Alloc( p_dec->fmt_out.audio.i_bytes_per_frame
-                                * frame.nb_samples );
+                                * frame->nb_samples );
         if( unlikely(p_buffer == NULL) )
         {
             block_Release( p_block );
@@ -373,21 +373,23 @@ block_t * DecodeAudio ( decoder_t *p_dec
         aout_ChannelExtract( p_buffer->p_buffer,
                              p_dec->fmt_out.audio.i_channels,
                              p_block->p_buffer, ctx->channels,
-                             frame.nb_samples, p_sys->pi_extraction,
+                             frame->nb_samples, p_sys->pi_extraction,
                              p_dec->fmt_out.audio.i_bitspersample );
         block_Release( p_block );
         p_block = p_buffer;
     }
 
-    p_block->i_nb_samples = frame.nb_samples;
-    p_block->i_buffer = frame.nb_samples
+    p_block->i_nb_samples = frame->nb_samples;
+    p_block->i_buffer = frame->nb_samples
                         * p_dec->fmt_out.audio.i_bytes_per_frame;
     p_block->i_pts = date_Get( &p_sys->end_date );
-    p_block->i_length = date_Increment( &p_sys->end_date, frame.nb_samples )
+    p_block->i_length = date_Increment( &p_sys->end_date, frame->nb_samples )
                         - p_block->i_pts;
     return p_block;
 
 end:
+    if ( frame != NULL )
+        av_frame_free(&frame);
     block_Release(p_block);
     *pp_block = NULL;
     return NULL;

Reply via email to