]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
mp3dec: Fix possible endless loop.
authorAndre Noll <maan@systemlinux.org>
Wed, 17 Aug 2011 17:08:17 +0000 (19:08 +0200)
committerAndre Noll <maan@systemlinux.org>
Thu, 18 Aug 2011 20:14:47 +0000 (22:14 +0200)
If the header of the last frame of a (corrupt) mp3 file can be decoded
but the rest of the frame can not, the mp3 decoder may end up in a
busy loop.

Fix this by performing the same check as for errors during header
decode. This adds some code duplication but as we are late in the
release cycle, let's go for the minimal fix for now.

error.h
mp3dec_filter.c

diff --git a/error.h b/error.h
index a56faf544534557cf96e9e434acfa696a2bf7c3e..306546d6c89bfdd2ee80832ed4c71b655bdf7b05 100644 (file)
--- a/error.h
+++ b/error.h
@@ -318,6 +318,7 @@ extern const char **para_errlist[];
        PARA_ERROR(MAD_FRAME_DECODE, "mad frame decode error"), \
        PARA_ERROR(MP3DEC_SYNTAX, "syntax error in mp3dec config"), \
        PARA_ERROR(MP3DEC_EOF, "mp3dec: end of file"), \
+       PARA_ERROR(MP3DEC_CORRUPT, "too many corrupt frames"), \
 
 
 #define FILTER_ERRORS \
index 6982f264a8d866970cc80e960d79628a41c74101..3ad9025e327ee9b81c935036296223d7bf91488f 100644 (file)
@@ -74,6 +74,8 @@ static void mp3dec_close(struct filter_node *fn)
        fn->private_data = NULL;
 }
 
+#define MP3DEC_MAX_FRAME 8192
+
 static void mp3dec_post_select(__a_unused struct sched *s, struct task *t)
 {
        struct filter_node *fn = container_of(t, struct filter_node, task);
@@ -99,7 +101,7 @@ next_buffer:
         * other buffer tree nodes a chance to run. This is necessary to avoid
         * buffer underruns on slow machines.
         */
-       len = PARA_MIN(len, (size_t)8192);
+       len = PARA_MIN(len, (size_t)MP3DEC_MAX_FRAME);
        mad_stream_buffer(&pmd->stream, (unsigned char *)inbuffer, len);
 next_frame:
        ret = mad_header_decode(&pmd->frame.header, &pmd->stream);
@@ -112,12 +114,14 @@ next_frame:
                                goto err;
                        }
                        fn->min_iqs += 100;
+                       ret = -E_MP3DEC_CORRUPT;
+                       if (fn->min_iqs > MP3DEC_MAX_FRAME)
+                               goto err;
                }
                if (loaded == 0)
                        goto next_buffer;
                return;
        }
-       fn->min_iqs = 0;
        pmd->sample_rate = pmd->frame.header.samplerate;
        pmd->channels = MAD_NCHANNELS(&pmd->frame.header);
 decode:
@@ -126,15 +130,24 @@ decode:
                ret = handle_decode_error(pmd);
                if (ret < 0)
                        goto err;
-               mad_stream_sync(&pmd->stream);
-               if (pmd->stream.error == MAD_ERROR_BUFLEN)
+               ret = mad_stream_sync(&pmd->stream);
+               if (pmd->stream.error == MAD_ERROR_BUFLEN) {
+                       ret = -E_MP3DEC_EOF;
+                       if (len == iqs && btr_no_parent(btrn))
+                               goto err;
+                       fn->min_iqs += 100;
+                       ret = -E_MP3DEC_CORRUPT;
+                       if (fn->min_iqs > MP3DEC_MAX_FRAME)
+                               goto err;
                        return;
+               }
                if (pmd->stream.error != MAD_ERROR_BADDATAPTR)
                        goto decode;
                used = used_mad_buffer_bytes(&pmd->stream, len);
                btr_consume(btrn, used);
                return;
        }
+       fn->min_iqs = 0;
        mad_synth_frame(&pmd->synth, &pmd->frame);
        outbuffer = para_malloc(pmd->synth.pcm.length * 2 * pmd->channels);
        loaded = 0;