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.
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(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"), \
fn->private_data = NULL;
}
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);
static void mp3dec_post_select(__a_unused struct sched *s, struct task *t)
{
struct filter_node *fn = container_of(t, struct filter_node, task);
* other buffer tree nodes a chance to run. This is necessary to avoid
* buffer underruns on slow machines.
*/
* 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);
mad_stream_buffer(&pmd->stream, (unsigned char *)inbuffer, len);
next_frame:
ret = mad_header_decode(&pmd->frame.header, &pmd->stream);
goto err;
}
fn->min_iqs += 100;
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;
}
}
if (loaded == 0)
goto next_buffer;
return;
}
pmd->sample_rate = pmd->frame.header.samplerate;
pmd->channels = MAD_NCHANNELS(&pmd->frame.header);
decode:
pmd->sample_rate = pmd->frame.header.samplerate;
pmd->channels = MAD_NCHANNELS(&pmd->frame.header);
decode:
ret = handle_decode_error(pmd);
if (ret < 0)
goto err;
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;
if (pmd->stream.error != MAD_ERROR_BADDATAPTR)
goto decode;
used = used_mad_buffer_bytes(&pmd->stream, len);
btr_consume(btrn, used);
return;
}
if (pmd->stream.error != MAD_ERROR_BADDATAPTR)
goto decode;
used = used_mad_buffer_bytes(&pmd->stream, len);
btr_consume(btrn, used);
return;
}
mad_synth_frame(&pmd->synth, &pmd->frame);
outbuffer = para_malloc(pmd->synth.pcm.length * 2 * pmd->channels);
loaded = 0;
mad_synth_frame(&pmd->synth, &pmd->frame);
outbuffer = para_malloc(pmd->synth.pcm.length * 2 * pmd->channels);
loaded = 0;