X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmp3dec.c;h=3725d6717cb155fcca712ccdd4dbfe4e06db2ca1;hb=8cd1323103d3a287eeba5cac32e00cd7314c02bd;hp=c76b21ebd644c79b5163b08243c334e5d81428a3;hpb=d61849f0b7f0bde408a14e477453673ebec39739;p=ffmpeg diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index c76b21ebd64..3725d6717cb 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -57,6 +57,11 @@ typedef struct { int is_cbr; } MP3DecContext; +enum CheckRet { + CHECK_WRONG_HEADER = -1, + CHECK_SEEK_FAILED = -2, +}; + static int check(AVIOContext *pb, int64_t pos, uint32_t *header); /* mp3 read */ @@ -326,7 +331,7 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) st->duration = av_rescale_q(mp3->frames, (AVRational){spf, c.sample_rate}, st->time_base); if (mp3->header_filesize && mp3->frames && !mp3->is_cbr) - st->codec->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf); + st->codecpar->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf); return 0; } @@ -343,8 +348,8 @@ static int mp3_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_MP3; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_MP3; st->need_parsing = AVSTREAM_PARSE_FULL_RAW; st->start_time = 0; @@ -375,17 +380,30 @@ static int mp3_read_header(AVFormatContext *s) ffio_ensure_seekback(s->pb, i + 1024 + 4); frame_size = check(s->pb, off + i, &header); if (frame_size > 0) { - avio_seek(s->pb, off, SEEK_SET); + ret = avio_seek(s->pb, off, SEEK_SET); + if (ret < 0) + return ret; ffio_ensure_seekback(s->pb, i + 1024 + frame_size + 4); - if (check(s->pb, off + i + frame_size, &header2) >= 0 && + ret = check(s->pb, off + i + frame_size, &header2); + if (ret >= 0 && (header & SAME_HEADER_MASK) == (header2 & SAME_HEADER_MASK)) { - av_log(s, AV_LOG_INFO, "Skipping %d bytes of junk at %"PRId64".\n", i, off); - avio_seek(s->pb, off + i, SEEK_SET); + av_log(s, i > 0 ? AV_LOG_INFO : AV_LOG_VERBOSE, "Skipping %d bytes of junk at %"PRId64".\n", i, off); + ret = avio_seek(s->pb, off + i, SEEK_SET); + if (ret < 0) + return ret; break; + } else if (ret == CHECK_SEEK_FAILED) { + av_log(s, AV_LOG_ERROR, "Invalid frame size (%d): Could not seek to %"PRId64".\n", frame_size, off + i + frame_size); + return AVERROR(EINVAL); } + } else if (frame_size == CHECK_SEEK_FAILED) { + av_log(s, AV_LOG_ERROR, "Failed to read frame size: Could not seek to %"PRId64".\n", (int64_t) (i + 1024 + frame_size + 4)); + return AVERROR(EINVAL); } - avio_seek(s->pb, off, SEEK_SET); + ret = avio_seek(s->pb, off, SEEK_SET); + if (ret < 0) + return ret; } // the seek index is relative to the end of the xing vbr headers @@ -427,16 +445,21 @@ static int mp3_read_packet(AVFormatContext *s, AVPacket *pkt) static int check(AVIOContext *pb, int64_t pos, uint32_t *ret_header) { int64_t ret = avio_seek(pb, pos, SEEK_SET); + uint8_t header_buf[4]; unsigned header; MPADecodeHeader sd; if (ret < 0) - return ret; + return CHECK_SEEK_FAILED; - header = avio_rb32(pb); + ret = avio_read(pb, &header_buf[0], 4); + if (ret < 0) + return CHECK_SEEK_FAILED; + + header = AV_RB32(&header_buf[0]); if (ff_mpa_check_header(header) < 0) - return -1; + return CHECK_WRONG_HEADER; if (avpriv_mpegaudio_decode_header(&sd, header) == 1) - return -1; + return CHECK_WRONG_HEADER; if (ret_header) *ret_header = header; @@ -468,8 +491,14 @@ static int64_t mp3_sync(AVFormatContext *s, int64_t target_pos, int flags) for(j=0; jpb, pos, NULL); - if(ret < 0) - break; + if(ret < 0) { + if (ret == CHECK_WRONG_HEADER) { + break; + } else if (ret == CHECK_SEEK_FAILED) { + av_log(s, AV_LOG_ERROR, "Could not seek to %"PRId64".\n", pos); + return AVERROR(EINVAL); + } + } if ((target_pos - pos)*dir <= 0 && abs(MIN_VALID/2-j) < score) { candidate = pos; score = abs(MIN_VALID/2-j);