exr: fix out of bounds read in get_code
[ffmpeg.git] / libavcodec / libvorbisdec.c
index c56be29..ecf690a 100644 (file)
@@ -25,7 +25,6 @@
 #include "internal.h"
 
 typedef struct OggVorbisDecContext {
-    AVFrame frame;
     vorbis_info vi;                     /**< vorbis_info used during init   */
     vorbis_dsp_state vd;                /**< DSP state used for analysis    */
     vorbis_block vb;                    /**< vorbis_block used for analysis */
@@ -33,20 +32,22 @@ typedef struct OggVorbisDecContext {
     ogg_packet op;                      /**< ogg packet                     */
 } OggVorbisDecContext;
 
+static int oggvorbis_decode_close(AVCodecContext *avccontext);
+
 static int oggvorbis_decode_init(AVCodecContext *avccontext) {
     OggVorbisDecContext *context = avccontext->priv_data ;
     uint8_t *p= avccontext->extradata;
-    int i, hsizes[3];
+    int i, hsizes[3], ret;
     unsigned char *headers[3], *extradata = avccontext->extradata;
 
-    vorbis_info_init(&context->vi) ;
-    vorbis_comment_init(&context->vc) ;
-
     if(! avccontext->extradata_size || ! p) {
         av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
-        return -1;
+        return AVERROR(EINVAL);
     }
 
+    vorbis_info_init(&context->vi) ;
+    vorbis_comment_init(&context->vc) ;
+
     if(p[0] == 0 && p[1] == 30) {
         for(i = 0; i < 3; i++){
             hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
@@ -66,7 +67,8 @@ static int oggvorbis_decode_init(AVCodecContext *avccontext) {
             if(offset >= avccontext->extradata_size - 1) {
                 av_log(avccontext, AV_LOG_ERROR,
                        "vorbis header sizes damaged\n");
-                return -1;
+                ret = AVERROR_INVALIDDATA;
+                goto error;
             }
             hsizes[i] += *p;
             offset++;
@@ -84,7 +86,8 @@ static int oggvorbis_decode_init(AVCodecContext *avccontext) {
     } else {
         av_log(avccontext, AV_LOG_ERROR,
                "vorbis initial header len is wrong: %d\n", *p);
-        return -1;
+        ret = AVERROR_INVALIDDATA;
+        goto error;
     }
 
     for(i=0; i<3; i++){
@@ -93,7 +96,8 @@ static int oggvorbis_decode_init(AVCodecContext *avccontext) {
         context->op.packet = headers[i];
         if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
             av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
-            return -1;
+            ret = AVERROR_INVALIDDATA;
+            goto error;
         }
     }
 
@@ -106,6 +110,10 @@ static int oggvorbis_decode_init(AVCodecContext *avccontext) {
     vorbis_block_init(&context->vd, &context->vb);
 
     return 0 ;
+
+  error:
+    oggvorbis_decode_close(avccontext);
+    return ret;
 }
 
 
@@ -131,6 +139,7 @@ static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
                         int *got_frame_ptr, AVPacket *avpkt)
 {
     OggVorbisDecContext *context = avccontext->priv_data ;
+    AVFrame *frame = data;
     float **pcm ;
     ogg_packet *op= &context->op;
     int samples, total_samples, total_bytes;
@@ -142,12 +151,10 @@ static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
         return 0;
     }
 
-    context->frame.nb_samples = 8192*4;
-    if ((ret = ff_get_buffer(avccontext, &context->frame)) < 0) {
-        av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n");
+    frame->nb_samples = 8192*4;
+    if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0)
         return ret;
-    }
-    output = (int16_t *)context->frame.data[0];
+    output = (int16_t *)frame->data[0];
 
 
     op->packet = avpkt->data;
@@ -172,9 +179,8 @@ static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
         vorbis_synthesis_read(&context->vd, samples) ;
     }
 
-    context->frame.nb_samples = total_samples;
-    *got_frame_ptr   = 1;
-    *(AVFrame *)data = context->frame;
+    frame->nb_samples = total_samples;
+    *got_frame_ptr   = total_samples > 0;
     return avpkt->size;
 }
 
@@ -182,6 +188,8 @@ static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
 static int oggvorbis_decode_close(AVCodecContext *avccontext) {
     OggVorbisDecContext *context = avccontext->priv_data ;
 
+    vorbis_block_clear(&context->vb);
+    vorbis_dsp_clear(&context->vd);
     vorbis_info_clear(&context->vi) ;
     vorbis_comment_clear(&context->vc) ;
 
@@ -191,12 +199,12 @@ static int oggvorbis_decode_close(AVCodecContext *avccontext) {
 
 AVCodec ff_libvorbis_decoder = {
     .name           = "libvorbis",
+    .long_name      = NULL_IF_CONFIG_SMALL("libvorbis"),
     .type           = AVMEDIA_TYPE_AUDIO,
     .id             = AV_CODEC_ID_VORBIS,
     .priv_data_size = sizeof(OggVorbisDecContext),
     .init           = oggvorbis_decode_init,
     .decode         = oggvorbis_decode_frame,
     .close          = oggvorbis_decode_close,
-    .capabilities   = CODEC_CAP_DELAY,
-    .long_name      = NULL_IF_CONFIG_SMALL("libvorbis"),
+    .capabilities   = AV_CODEC_CAP_DELAY,
 };