From: Andre Noll Date: Wed, 17 Aug 2011 17:08:17 +0000 (+0200) Subject: mp3dec: Fix possible endless loop. X-Git-Tag: v0.4.8~1 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=08d3a77eaeb04981d225a6938404f8ac901407b4;ds=sidebyside mp3dec: Fix possible endless loop. 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. --- diff --git a/error.h b/error.h index a56faf54..306546d6 100644 --- 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 \ diff --git a/mp3dec_filter.c b/mp3dec_filter.c index 6982f264..3ad9025e 100644 --- a/mp3dec_filter.c +++ b/mp3dec_filter.c @@ -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;