idcin: better error handling
authorJustin Ruggles <justin.ruggles@gmail.com>
Wed, 1 Aug 2012 21:16:58 +0000 (17:16 -0400)
committerJustin Ruggles <justin.ruggles@gmail.com>
Wed, 9 Jan 2013 19:49:07 +0000 (14:49 -0500)
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
tests/ref/fate/id-cin-video

index 93ba721..87117eb 100644 (file)
@@ -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;
     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);
 
     /* 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);
 
     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) {
     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);
     /* 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);
         return AVERROR(EIO);
+    }
 
     if (idcin->audio_present) {
         idcin->audio_present = 1;
 
     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)
     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);
 
     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 */
             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);
                 return AVERROR(EIO);
+            }
             /* scale the palette as necessary */
             palette_scale = 2;
             for (i = 0; i < 768; i++)
             /* 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);
         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;
         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;
 
         if (command == 1) {
             uint8_t *pal;
 
index 241cae5..f55544f 100644 (file)
 1,      78750,      78750,     1575,     6300, 0xe3bfa403
 0,         51,         51,        1,   230400, 0x488de02d
 1,      80325,      80325,     1575,     6300, 0x2c5bd9c9
 1,      78750,      78750,     1575,     6300, 0xe3bfa403
 0,         51,         51,        1,   230400, 0x488de02d
 1,      80325,      80325,     1575,     6300, 0x2c5bd9c9
-0,         52,         52,        1,   230400, 0x488de02d