patch courtesy of Todd Kirby:
authorMike Melanson <mike@multimedia.cx>
Sat, 10 Apr 2004 15:09:46 +0000 (15:09 +0000)
committerMike Melanson <mike@multimedia.cx>
Sat, 10 Apr 2004 15:09:46 +0000 (15:09 +0000)
* Fixes a small memory leak in read_rle_sgi()
* Remove temp buffer in read_rle_sgi(). Write rle data directly to image
buffer.
* Adds sanity check to read_rle_sgi() to insure decoded rle data row
equals image width.

Originally committed as revision 2993 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/sgi.c

index 89ef721..13ca98e 100644 (file)
@@ -86,9 +86,7 @@ static int read_uncompressed_sgi(const SGIInfo *si,
         AVPicture *pict, ByteIOContext *f)
 {
     int x, y, z, chan_offset, ret = 0;
-    uint8_t *dest_row, *tmp_row = NULL;
-
-    tmp_row = av_malloc(si->xsize);
+    uint8_t *dest_row;
 
     /* skip header */ 
     url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
@@ -108,28 +106,23 @@ static int read_uncompressed_sgi(const SGIInfo *si,
         for (y = si->ysize - 1; y >= 0; y--) {
             dest_row = pict->data[0] + (y * si->xsize * si->zsize);
 
-            if (!get_buffer(f, tmp_row, si->xsize)) {
-                ret = -1;
-                goto cleanup;
-            }
             for (x = 0; x < si->xsize; x++) {
-                dest_row[chan_offset] = tmp_row[x]
+                dest_row[chan_offset] = get_byte(f)
                 dest_row += si->zsize;
             }
         }
     }
 
-cleanup:
-    av_free(tmp_row);
     return ret;
 }
 
 
 /* expand an rle row into a channel */
-static void expand_rle_row(unsigned char *optr, unsigned char *iptr, 
+static int expand_rle_row(ByteIOContext *f, unsigned char *optr,
         int chan_offset, int pixelstride)
 {
     unsigned char pixel, count;
+    int length = 0;
  
 #ifndef WORDS_BIGENDIAN
     /* rgba -> bgra for rgba32 on little endian cpus */
@@ -141,22 +134,23 @@ static void expand_rle_row(unsigned char *optr, unsigned char *iptr,
     optr += chan_offset;
 
     while (1) {
-        pixel = *iptr++;
+        pixel = get_byte(f);
 
         if (!(count = (pixel & 0x7f))) {
-            return;
+            return length;
         }
         if (pixel & 0x80) {
             while (count--) {
-                *optr = *iptr;
+                *optr = get_byte(f);
+                length++;
                 optr += pixelstride;
-                iptr++;
             }
         } else {
-            pixel = *iptr++;
+            pixel = get_byte(f);
 
             while (count--) {
                 *optr = pixel;
+                length++;
                 optr += pixelstride;
             }
         }
@@ -168,18 +162,16 @@ static void expand_rle_row(unsigned char *optr, unsigned char *iptr,
 static int read_rle_sgi(const SGIInfo *sgi_info, 
         AVPicture *pict, ByteIOContext *f)
 {
-    uint8_t *dest_row, *rle_data = NULL;
-    unsigned long *start_table, *length_table;
+    uint8_t *dest_row;
+    unsigned long *start_table;
     int y, z, xsize, ysize, zsize, tablen; 
-    long start_offset, run_length;
+    long start_offset;
     int ret = 0;
 
     xsize = sgi_info->xsize;
     ysize = sgi_info->ysize;
     zsize = sgi_info->zsize;
 
-    rle_data = av_malloc(xsize);
-
     /* skip header */ 
     url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);
 
@@ -187,40 +179,35 @@ static int read_rle_sgi(const SGIInfo *sgi_info,
     tablen = ysize * zsize * sizeof(long);
 
     start_table = (unsigned long *)av_malloc(tablen);
-    length_table = (unsigned long *)av_malloc(tablen);
 
     if (!get_buffer(f, (uint8_t *)start_table, tablen)) {
-        ret = -1;
+        ret = AVERROR_IO;
         goto fail;
     }
 
-    if (!get_buffer(f, (uint8_t *)length_table, tablen)) {
-        ret = -1;
-        goto fail;
-    }
+    /* skip run length table */ 
+    url_fseek(f, tablen, SEEK_CUR);
 
     for (z = 0; z < zsize; z++) {
         for (y = 0; y < ysize; y++) {
             dest_row = pict->data[0] + (ysize - 1 - y) * (xsize * zsize);
 
             start_offset = BE_32(&start_table[y + z * ysize]);
-            run_length = BE_32(&length_table[y + z * ysize]);
 
-            /* don't seek if already in the correct spot */
+            /* don't seek if already at the next rle start offset */
             if (url_ftell(f) != start_offset) {
                 url_fseek(f, start_offset, SEEK_SET);
             }
 
-            get_buffer(f, rle_data, run_length);
-            
-            expand_rle_row(dest_row, rle_data, z, zsize);
+            if (expand_rle_row(f, dest_row, z, zsize) != xsize) {
+              ret =  AVERROR_INVALIDDATA;
+              goto fail;
+            }
         }
     }
 
 fail:
     av_free(start_table);
-    av_free(length_table);
-    av_free(rle_data);
 
     return ret;
 }