changeset 1895:eb03869a10d3

Clean up the IFF reader and make it more robust.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 26 Jun 2018 03:09:01 +0300
parents 2e3f188c6bf0
children f80b2dc77c30
files tools/libgfx.c
diffstat 1 files changed, 20 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/tools/libgfx.c	Tue Jun 26 03:07:58 2018 +0300
+++ b/tools/libgfx.c	Tue Jun 26 03:09:01 2018 +0300
@@ -1401,6 +1401,7 @@
     Uint32 size;
     int count;
     char idStr[6];
+    off_t offs;
 } DMIFFChunk;
 
 
@@ -1468,20 +1469,22 @@
     }
     else
     {
+        chunk->offs = dmftell(fp);
         dmMakeIFFChunkIDStr(chunk);
         return DMERR_OK;
     }
 }
 
 
-static int dmSkipIFFChunkRest(DMResource *fp, const DMIFFChunk *chunk, const Uint32 used)
+static int dmSkipIFFChunkRest(DMResource *fp, const DMIFFChunk *chunk)
 {
-    if (chunk->size > used)
+    off_t read = dmftell(fp) - chunk->offs;
+    if (chunk->size > read)
     {
         dmMsg(4, "IFF: Skipping %d bytes (%d of %d consumed)\n",
-            chunk->size - used, used, chunk->size);
+            chunk->size - read, read, chunk->size);
 
-        if (dmfseek(fp, chunk->size - used, SEEK_CUR) != 0)
+        if (dmfseek(fp, chunk->size - read, SEEK_CUR) != 0)
         {
             return dmError(DMERR_FSEEK,
                 "IFF: Failed to skip chunk end.\n");
@@ -1581,15 +1584,13 @@
 }
 
 
-static int dmDecodeILBMBody(DMResource *fp, DMIFF *iff, DMImage *img, Uint32 *read)
+static int dmDecodeILBMBody(DMResource *fp, DMIFF *iff, DMImage *img)
 {
     Uint8 *buf;
     size_t bufLen;
     int res = DMERR_OK;
     const int nplanes = iff->bmhd.nplanes;
 
-    *read = 0;
-
     // Allocate planar decoding buffer
     bufLen = ((img->width + 15) / 16) * 2;
     if ((buf = dmMalloc(bufLen)) == NULL)
@@ -1617,8 +1618,6 @@
 
             // Decode bitplane
             dmDecodeBitPlane(dp, buf, img->width, plane);
-
-            *read += bufLen;
         }
 
         // Read mask data
@@ -1641,8 +1640,6 @@
                 if (!data)
                     dp[xc] = img->ctransp < 0 ? 0 : img->ctransp;
             }
-
-            *read += bufLen;
         }
     }
 
@@ -1652,29 +1649,18 @@
 }
 
 
-static int dmDecodePBMBody(DMResource *fp, DMIFF *iff, DMImage *img, Uint32 *read)
+static int dmDecodePBMBody(DMResource *fp, DMIFF *iff, DMImage *img)
 {
-    int res = DMERR_OK;
-
-    *read = 0;
-
-    // Decode the chunk
     for (int yc = 0; yc < img->height; yc++)
     {
-        Uint8 *dp = img->data + (yc * img->pitch);
-
-        if (!dmIFFReadOneRow(fp, iff, dp, img->width))
+        if (!dmIFFReadOneRow(fp, iff, img->data + (yc * img->pitch), img->width))
         {
-            res = dmError(DMERR_FREAD,
-                "IFF: Error in reading image row #%d.\n", yc);
-            goto error;
+            return dmError(DMERR_FREAD,
+                "IFF: Error reading PBM image row #%d.\n", yc);
         }
-
-        *read += img->width;
     }
 
-error:
-    return res;
+    return DMERR_OK;
 }
 
 
@@ -1682,7 +1668,7 @@
 {
     DMIFFChunk chunk;
     DMIFF iff;
-    Uint32 read, idsig;
+    Uint32 idsig;
     BOOL parsed = FALSE, planar;
     int res = DMERR_OK;
 
@@ -1711,6 +1697,7 @@
 
     while (!parsed && !dmfeof(fp))
     {
+        // Read chunk header
         if ((res = dmReadIFFChunkHdr(fp, &chunk)) != DMERR_OK)
             return res;
 
@@ -1756,9 +1743,6 @@
                     return dmError(DMERR_NOT_SUPPORTED,
                         "IFF: Unsupported features, refusing to load.\n");
                 }
-
-                if ((res = dmSkipIFFChunkRest(fp, &chunk, sizeof(iff.bmhd))) != DMERR_OK)
-                    return res;
                 break;
 
 
@@ -1832,16 +1816,16 @@
                 // Decode the body
                 if (planar)
                 {
-                    if ((res = dmDecodeILBMBody(fp, &iff, *pimg, &read)) != DMERR_OK)
+                    if ((res = dmDecodeILBMBody(fp, &iff, *pimg)) != DMERR_OK)
                         return res;
                 }
                 else
                 {
-                    if ((res = dmDecodePBMBody(fp, &iff, *pimg, &read)) != DMERR_OK)
+                    if ((res = dmDecodePBMBody(fp, &iff, *pimg)) != DMERR_OK)
                         return res;
                 }
 
-                if ((res = dmSkipIFFChunkRest(fp, &chunk, read)) != DMERR_OK)
+                if ((res = dmSkipIFFChunkRest(fp, &chunk)) != DMERR_OK)
                     return res;
 
                 if (iff.chCMAP.count)
@@ -1863,9 +1847,6 @@
                     return dmError(DMERR_NOT_SUPPORTED,
                         "IFF: HAM files are not supported.\n");
                 }
-
-                if ((res = dmSkipIFFChunkRest(fp, &chunk, sizeof(Uint32))) != DMERR_OK)
-                    return res;
                 break;
 
 
@@ -1883,8 +1864,8 @@
                 break;
         }
 
-        if (chunk.size & 1)
-            dmfgetc(fp);
+        if ((res = dmSkipIFFChunkRest(fp, &chunk)) != DMERR_OK)
+            return res;
     }
 
     // Set colormap after finishing