diff --git a/libavformat/iff.c b/libavformat/iff.c index 10d2f2ff28..569ce617cf 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -2,6 +2,7 @@ * IFF (.iff) file demuxer * Copyright (c) 2008 Jaikrishnan Menon * Copyright (c) 2010 Peter Ross + * Copyright (c) 2010 Sebastian Vater * * This file is part of FFmpeg. * @@ -72,6 +73,7 @@ typedef enum { } bitmap_compression_type; typedef struct { + uint64_t body_pos; uint32_t body_size; uint32_t sent_bytes; uint32_t audio_frame_count; @@ -107,7 +109,6 @@ static int iff_read_header(AVFormatContext *s, ByteIOContext *pb = s->pb; AVStream *st; uint32_t chunk_id, data_size; - int padding, done = 0; int compression = -1; char *buf; @@ -120,27 +121,34 @@ static int iff_read_header(AVFormatContext *s, // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = get_le32(pb); - while(!done && !url_feof(pb)) { + while(!url_feof(pb)) { + uint64_t orig_pos; chunk_id = get_le32(pb); data_size = get_be32(pb); - padding = data_size & 1; + orig_pos = url_ftell(pb); switch(chunk_id) { case ID_VHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + + if (data_size < 14) + return AVERROR_INVALIDDATA; url_fskip(pb, 12); st->codec->sample_rate = get_be16(pb); + if (data_size >= 16) { url_fskip(pb, 1); compression = get_byte(pb); - url_fskip(pb, 4); + } break; case ID_BODY: + iff->body_pos = url_ftell(pb); iff->body_size = data_size; - done = 1; break; case ID_CHAN: + if (data_size < 4) + return AVERROR_INVALIDDATA; st->codec->channels = (get_be32(pb) < 6) ? 1 : 2; break; @@ -155,16 +163,21 @@ static int iff_read_header(AVFormatContext *s, case ID_BMHD: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + if (data_size <= 8) + return AVERROR_INVALIDDATA; st->codec->width = get_be16(pb); st->codec->height = get_be16(pb); url_fskip(pb, 4); // x, y offset st->codec->bits_per_coded_sample = get_byte(pb); + if (data_size >= 11) { url_fskip(pb, 1); // masking compression = get_byte(pb); + } + if (data_size >= 16) { url_fskip(pb, 3); // paddding, transparent st->sample_aspect_ratio.num = get_byte(pb); st->sample_aspect_ratio.den = get_byte(pb); - url_fskip(pb, 4); // source page width, height + } break; case ID_ANNO: @@ -175,13 +188,13 @@ static int iff_read_header(AVFormatContext *s, buf[data_size] = 0; av_metadata_set2(&s->metadata, "comment", buf, AV_METADATA_DONT_STRDUP_VAL); break; - - default: - url_fseek(pb, data_size + padding, SEEK_CUR); - break; } + + url_fskip(pb, data_size - (url_ftell(pb) - orig_pos) + (data_size & 1)); } + url_fseek(pb, iff->body_pos, SEEK_SET); + switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: av_set_pts_info(st, 32, 1, st->codec->sample_rate);