exr: fix out of bounds read in get_code
[ffmpeg.git] / libavcodec / libvorbisdec.c
index 99fb83a..ecf690a 100644 (file)
@@ -32,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);
@@ -65,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++;
@@ -83,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++){
@@ -92,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;
         }
     }
 
@@ -105,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;
 }
 
 
@@ -143,10 +152,8 @@ static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
     }
 
     frame->nb_samples = 8192*4;
-    if ((ret = ff_get_buffer(avccontext, frame)) < 0) {
-        av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n");
+    if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0)
         return ret;
-    }
     output = (int16_t *)frame->data[0];
 
 
@@ -173,7 +180,7 @@ static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
     }
 
     frame->nb_samples = total_samples;
-    *got_frame_ptr   = 1;
+    *got_frame_ptr   = total_samples > 0;
     return avpkt->size;
 }
 
@@ -181,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) ;
 
@@ -190,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,
 };