diff --git a/libavformat/rsd.c b/libavformat/rsd.c index e23c8abae5..ee0b9557de 100644 --- a/libavformat/rsd.c +++ b/libavformat/rsd.c @@ -103,13 +103,9 @@ static int rsd_read_header(AVFormatContext *s) break; case AV_CODEC_ID_ADPCM_PSX: par->block_align = 16 * par->channels; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_IMA_RAD: par->block_align = 20 * par->channels; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_IMA_WAV: if (version == 2) @@ -117,8 +113,6 @@ static int rsd_read_header(AVFormatContext *s) par->bits_per_coded_sample = 4; par->block_align = 36 * par->channels; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_THP_LE: /* RSD3GADP is mono, so only alloc enough memory @@ -128,8 +122,6 @@ static int rsd_read_header(AVFormatContext *s) if ((ret = ff_get_extradata(s, par, s->pb, 32)) < 0) return ret; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_THP: par->block_align = 8 * par->channels; @@ -142,18 +134,36 @@ static int rsd_read_header(AVFormatContext *s) avio_read(s->pb, st->codecpar->extradata + 32 * i, 32); avio_skip(s->pb, 8); } - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = (avio_size(pb) - start) / (8 * par->channels) * 14; break; case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16BE: if (version != 4) start = avio_rl32(pb); - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = (avio_size(pb) - start) / 2 / par->channels; break; } + if (start < 0) + return AVERROR_INVALIDDATA; + + if (pb->seekable & AVIO_SEEKABLE_NORMAL) { + int64_t remaining = avio_size(pb); + + if (remaining >= start && remaining - start <= INT_MAX) + switch (par->codec_id) { + case AV_CODEC_ID_ADPCM_PSX: + case AV_CODEC_ID_ADPCM_IMA_RAD: + case AV_CODEC_ID_ADPCM_IMA_WAV: + case AV_CODEC_ID_ADPCM_THP_LE: + st->duration = av_get_audio_frame_duration2(par, remaining - start); + break; + case AV_CODEC_ID_ADPCM_THP: + st->duration = (remaining - start) / (8 * par->channels) * 14; + break; + case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_S16BE: + st->duration = (remaining - start) / 2 / par->channels; + } + } avio_skip(pb, start - avio_tell(pb)); if (par->codec_id == AV_CODEC_ID_XMA2) {