From 33f58c3616d2870d3861da68217ef9d05cc5047a Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 1 Aug 2012 16:10:08 -0400 Subject: idcin: check for integer overflow when calling av_get_packet() chunk_size is unsigned 32-bit, but av_get_packet() takes a signed int as the packet size. --- libavformat/idcin.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libavformat/idcin.c') diff --git a/libavformat/idcin.c b/libavformat/idcin.c index 7a0042b4a1..93ba721d11 100644 --- a/libavformat/idcin.c +++ b/libavformat/idcin.c @@ -278,6 +278,10 @@ static int idcin_read_packet(AVFormatContext *s, } chunk_size = avio_rl32(pb); + if (chunk_size < 4 || chunk_size > INT_MAX - 4) { + av_log(s, AV_LOG_ERROR, "invalid chunk size: %u\n", chunk_size); + return AVERROR_INVALIDDATA; + } /* skip the number of decoded bytes (always equal to width * height) */ avio_skip(pb, 4); chunk_size -= 4; -- cgit v1.2.1 From 5d0450461ff729be5f531d333d29754155e406c5 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 1 Aug 2012 17:16:58 -0400 Subject: idcin: better error handling Add some additional checks for EOF and print error messages on an incomplete header or packet. FATE reference updated for id-cin-video due to the demuxer no longer returning a partial video packet at EOF. --- libavformat/idcin.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'libavformat/idcin.c') diff --git a/libavformat/idcin.c b/libavformat/idcin.c index 93ba721d11..87117eba91 100644 --- a/libavformat/idcin.c +++ b/libavformat/idcin.c @@ -147,6 +147,7 @@ static int idcin_read_header(AVFormatContext *s) AVStream *st; unsigned int width, height; unsigned int sample_rate, bytes_per_sample, channels; + int ret; /* get the 5 header parameters */ width = avio_rl32(pb); @@ -155,6 +156,11 @@ static int idcin_read_header(AVFormatContext *s) bytes_per_sample = avio_rl32(pb); channels = avio_rl32(pb); + if (s->pb->eof_reached) { + av_log(s, AV_LOG_ERROR, "incomplete header\n"); + return s->pb->error ? s->pb->error : AVERROR_EOF; + } + if (av_image_check_size(width, height, 0, s) < 0) return AVERROR_INVALIDDATA; if (sample_rate > 0) { @@ -192,9 +198,13 @@ static int idcin_read_header(AVFormatContext *s) /* load up the Huffman tables into extradata */ st->codec->extradata_size = HUFFMAN_TABLE_SIZE; st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE); - if (avio_read(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE) != - HUFFMAN_TABLE_SIZE) + ret = avio_read(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE); + if (ret < 0) { + return ret; + } else if (ret != HUFFMAN_TABLE_SIZE) { + av_log(s, AV_LOG_ERROR, "incomplete header\n"); return AVERROR(EIO); + } if (idcin->audio_present) { idcin->audio_present = 1; @@ -251,7 +261,7 @@ static int idcin_read_packet(AVFormatContext *s, uint32_t palette[256]; if (s->pb->eof_reached) - return AVERROR(EIO); + return s->pb->error ? s->pb->error : AVERROR_EOF; if (idcin->next_chunk_is_video) { command = avio_rl32(pb); @@ -259,8 +269,13 @@ static int idcin_read_packet(AVFormatContext *s, return AVERROR(EIO); } else if (command == 1) { /* trigger a palette change */ - if (avio_read(pb, palette_buffer, 768) != 768) + ret = avio_read(pb, palette_buffer, 768); + if (ret < 0) { + return ret; + } else if (ret != 768) { + av_log(s, AV_LOG_ERROR, "incomplete packet\n"); return AVERROR(EIO); + } /* scale the palette as necessary */ palette_scale = 2; for (i = 0; i < 768; i++) @@ -277,6 +292,10 @@ static int idcin_read_packet(AVFormatContext *s, } } + if (s->pb->eof_reached) { + av_log(s, AV_LOG_ERROR, "incomplete packet\n"); + return s->pb->error ? s->pb->error : AVERROR_EOF; + } chunk_size = avio_rl32(pb); if (chunk_size < 4 || chunk_size > INT_MAX - 4) { av_log(s, AV_LOG_ERROR, "invalid chunk size: %u\n", chunk_size); @@ -288,6 +307,10 @@ static int idcin_read_packet(AVFormatContext *s, ret= av_get_packet(pb, pkt, chunk_size); if (ret < 0) return ret; + else if (ret != chunk_size) { + av_log(s, AV_LOG_ERROR, "incomplete packet\n"); + return AVERROR(EIO); + } if (command == 1) { uint8_t *pal; -- cgit v1.2.1