mpegaudiodecheader: check the header in avpriv_mpegaudio_decode_header

Almost all the places from which this function is called already check
the header manually and in the two that don't (the mp3 muxer) the check
should not cause any problems.
pull/172/head
Anton Khirnov 9 years ago
parent cea1eef25c
commit 955aec3c7c
  1. 7
      libavcodec/libmp3lame.c
  2. 20
      libavcodec/mpegaudiodec_template.c
  3. 9
      libavcodec/mpegaudiodecheader.c
  4. 12
      libavformat/mp3dec.c
  5. 5
      libavformat/mp3enc.c

@ -239,11 +239,12 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
if (s->buffer_index < 4) if (s->buffer_index < 4)
return 0; return 0;
h = AV_RB32(s->buffer); h = AV_RB32(s->buffer);
if (ff_mpa_check_header(h) < 0) {
ret = avpriv_mpegaudio_decode_header(&hdr, h);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Invalid mp3 header at start of buffer\n"); av_log(avctx, AV_LOG_ERROR, "Invalid mp3 header at start of buffer\n");
return AVERROR_BUG; return AVERROR_BUG;
} } else if (ret) {
if (avpriv_mpegaudio_decode_header(&hdr, h)) {
av_log(avctx, AV_LOG_ERROR, "free format output not supported\n"); av_log(avctx, AV_LOG_ERROR, "free format output not supported\n");
return -1; return -1;
} }

@ -1631,12 +1631,12 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr,
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
header = AV_RB32(buf); header = AV_RB32(buf);
if (ff_mpa_check_header(header) < 0) {
ret = avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Header missing\n"); av_log(avctx, AV_LOG_ERROR, "Header missing\n");
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} } else if (ret == 1) {
if (avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header) == 1) {
/* free format: prepare to compute frame size */ /* free format: prepare to compute frame size */
s->frame_size = -1; s->frame_size = -1;
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
@ -1706,12 +1706,11 @@ static int decode_frame_adu(AVCodecContext *avctx, void *data,
// Get header and restore sync word // Get header and restore sync word
header = AV_RB32(buf) | 0xffe00000; header = AV_RB32(buf) | 0xffe00000;
if (ff_mpa_check_header(header) < 0) { // Bad header, discard frame ret = avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Invalid frame header\n"); av_log(avctx, AV_LOG_ERROR, "Invalid frame header\n");
return AVERROR_INVALIDDATA; return ret;
} }
avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header);
/* update codec info */ /* update codec info */
avctx->sample_rate = s->sample_rate; avctx->sample_rate = s->sample_rate;
avctx->channels = s->nb_channels; avctx->channels = s->nb_channels;
@ -1903,11 +1902,10 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
} }
header = (AV_RB32(buf) & 0x000fffff) | s->syncword; // patch header header = (AV_RB32(buf) & 0x000fffff) | s->syncword; // patch header
if (ff_mpa_check_header(header) < 0) // Bad header, discard block ret = avpriv_mpegaudio_decode_header((MPADecodeHeader *)m, header);
if (ret < 0) // Bad header, discard block
break; break;
avpriv_mpegaudio_decode_header((MPADecodeHeader *)m, header);
if (ch + m->nb_channels > avctx->channels || if (ch + m->nb_channels > avctx->channels ||
s->coff[fr] + m->nb_channels > avctx->channels) { s->coff[fr] + m->nb_channels > avctx->channels) {
av_log(avctx, AV_LOG_ERROR, "frame channel count exceeds codec " av_log(avctx, AV_LOG_ERROR, "frame channel count exceeds codec "

@ -36,6 +36,12 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header)
{ {
int sample_rate, frame_size, mpeg25, padding; int sample_rate, frame_size, mpeg25, padding;
int sample_rate_index, bitrate_index; int sample_rate_index, bitrate_index;
int ret;
ret = ff_mpa_check_header(header);
if (ret < 0)
return ret;
if (header & (1<<20)) { if (header & (1<<20)) {
s->lsf = (header & (1<<19)) ? 0 : 1; s->lsf = (header & (1<<19)) ? 0 : 1;
mpeg25 = 0; mpeg25 = 0;
@ -116,9 +122,6 @@ int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_r
{ {
MPADecodeHeader s1, *s = &s1; MPADecodeHeader s1, *s = &s1;
if (ff_mpa_check_header(head) != 0)
return -1;
if (avpriv_mpegaudio_decode_header(s, head) != 0) { if (avpriv_mpegaudio_decode_header(s, head) != 0) {
return -1; return -1;
} }

@ -275,14 +275,16 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
MPADecodeHeader c; MPADecodeHeader c;
int vbrtag_size = 0; int vbrtag_size = 0;
MP3DecContext *mp3 = s->priv_data; MP3DecContext *mp3 = s->priv_data;
int ret;
ffio_init_checksum(s->pb, ff_crcA001_update, 0); ffio_init_checksum(s->pb, ff_crcA001_update, 0);
v = avio_rb32(s->pb); v = avio_rb32(s->pb);
if(ff_mpa_check_header(v) < 0)
return -1;
if (avpriv_mpegaudio_decode_header(&c, v) == 0) ret = avpriv_mpegaudio_decode_header(&c, v);
if (ret < 0)
return ret;
else if (ret == 0)
vbrtag_size = c.frame_size; vbrtag_size = c.frame_size;
if(c.layer != 3) if(c.layer != 3)
return -1; return -1;
@ -388,8 +390,8 @@ static int check(AVIOContext *pb, int64_t pos, int64_t *out_pos)
header = avio_rb32(pb); header = avio_rb32(pb);
if (ff_mpa_check_header(header) < 0 ||
avpriv_mpegaudio_decode_header(&mh, header)) if (avpriv_mpegaudio_decode_header(&mh, header))
break; break;
out_pos[i] = off; out_pos[i] = off;
} }

@ -306,11 +306,12 @@ static int mp3_write_audio_packet(AVFormatContext *s, AVPacket *pkt)
if (mp3->xing_offset && pkt->size >= 4) { if (mp3->xing_offset && pkt->size >= 4) {
MPADecodeHeader c; MPADecodeHeader c;
int ret;
uint32_t h; uint32_t h;
h = AV_RB32(pkt->data); h = AV_RB32(pkt->data);
if (ff_mpa_check_header(h) == 0) { ret = avpriv_mpegaudio_decode_header(&c, h);
avpriv_mpegaudio_decode_header(&c, h); if (ret >= 0) {
if (!mp3->initial_bitrate) if (!mp3->initial_bitrate)
mp3->initial_bitrate = c.bit_rate; mp3->initial_bitrate = c.bit_rate;
if ((c.bit_rate == 0) || (mp3->initial_bitrate != c.bit_rate)) if ((c.bit_rate == 0) || (mp3->initial_bitrate != c.bit_rate))

Loading…
Cancel
Save