summaryrefslogtreecommitdiff
path: root/libavformat/iff.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/iff.c')
-rw-r--r--libavformat/iff.c33
1 files changed, 23 insertions, 10 deletions
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 <realityman@gmx.net>
* Copyright (c) 2010 Peter Ross <pross@xvid.org>
+ * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
*
* 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);