X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fape.c;h=df39e37532d10a141bba0e3802d3bd75ff8dede3;hb=67235dfa1d2b4bab2c8015e5b8e43ea63a681892;hp=72fca5dd468cb985131fe590914f5b7e8085be30;hpb=3edff185abfdd089b88ecc5770e5f6a963055a97;p=ffmpeg diff --git a/libavformat/ape.c b/libavformat/ape.c index 72fca5dd468..df39e37532d 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -152,15 +152,15 @@ static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) #endif } -static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) +static int ape_read_header(AVFormatContext * s) { AVIOContext *pb = s->pb; APEContext *ape = s->priv_data; AVStream *st; uint32_t tag; int i; - int total_blocks; - int64_t pts; + int total_blocks, final_size = 0; + int64_t pts, file_size; /* Skip any leading junk such as id3v2 tags */ ape->junklength = avio_tell(pb); @@ -289,8 +289,17 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos; ape->frames[i].skip = (ape->frames[i].pos - ape->frames[0].pos) & 3; } - ape->frames[ape->totalframes - 1].size = ape->finalframeblocks * 4; ape->frames[ape->totalframes - 1].nblocks = ape->finalframeblocks; + /* calculate final packet size from total file size, if available */ + file_size = avio_size(pb); + if (file_size > 0) { + final_size = file_size - ape->frames[ape->totalframes - 1].pos - + ape->wavtaillength; + final_size -= final_size & 3; + } + if (file_size <= 0 || final_size <= 0) + final_size = ape->finalframeblocks * 8; + ape->frames[ape->totalframes - 1].size = final_size; for (i = 0; i < ape->totalframes; i++) { if(ape->frames[i].skip){ @@ -326,7 +335,6 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) st->codec->channels = ape->channels; st->codec->sample_rate = ape->samplerate; st->codec->bits_per_coded_sample = ape->bps; - st->codec->frame_size = MAC_SUBFRAME_SIZE; st->nb_frames = ape->totalframes; st->start_time = 0; @@ -357,11 +365,12 @@ static int ape_read_packet(AVFormatContext * s, AVPacket * pkt) uint32_t extra_size = 8; if (url_feof(s->pb)) - return AVERROR(EIO); - if (ape->currentframe > ape->totalframes) - return AVERROR(EIO); + return AVERROR_EOF; + if (ape->currentframe >= ape->totalframes) + return AVERROR_EOF; - avio_seek (s->pb, ape->frames[ape->currentframe].pos, SEEK_SET); + if (avio_seek(s->pb, ape->frames[ape->currentframe].pos, SEEK_SET) < 0) + return AVERROR(EIO); /* Calculate how many blocks there are in this frame */ if (ape->currentframe == (ape->totalframes - 1)) @@ -369,6 +378,14 @@ static int ape_read_packet(AVFormatContext * s, AVPacket * pkt) else nblocks = ape->blocksperframe; + if (ape->frames[ape->currentframe].size <= 0 || + ape->frames[ape->currentframe].size > INT_MAX - extra_size) { + av_log(s, AV_LOG_ERROR, "invalid packet size: %d\n", + ape->frames[ape->currentframe].size); + ape->currentframe++; + return AVERROR(EIO); + } + if (av_new_packet(pkt, ape->frames[ape->currentframe].size + extra_size) < 0) return AVERROR(ENOMEM); @@ -406,6 +423,8 @@ static int ape_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp if (index < 0) return -1; + if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0) + return -1; ape->currentframe = index; return 0; }