about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-10-23 01:54:14 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-10-23 01:54:14 +0000
commita27c4500441553250de3338af151685d59840675 (patch)
tree9ec1cf5e5deb85ff212351ce66831b156073e41f
parentc1047e659a222fadacd513aa495a6f1cda5a89a4 (diff)
downloadnetpbm-mirror-a27c4500441553250de3338af151685d59840675.tar.gz
netpbm-mirror-a27c4500441553250de3338af151685d59840675.tar.xz
netpbm-mirror-a27c4500441553250de3338af151685d59840675.zip
Fix arithmetic overflow on -channel, crash with -channel on verbatim SGI image
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1338 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--converter/other/sgitopnm.c129
1 files changed, 65 insertions, 64 deletions
diff --git a/converter/other/sgitopnm.c b/converter/other/sgitopnm.c
index 63814fdb..86744638 100644
--- a/converter/other/sgitopnm.c
+++ b/converter/other/sgitopnm.c
@@ -15,8 +15,11 @@
 ** 29Jan94: first version
 ** 08Feb94: minor bugfix
 ** 29Jul00: added -channel option (smar@reptiles.org)
+** 19Oct10: added checks for artihmetic overflows
+**          fixed problem with -channel on verbatim sgi images (afu)
 */
 #include <unistd.h>
+#include <limits.h>
 #include "mallocvar.h"
 #include "pnm.h"
 #include "sgi.h"
@@ -39,23 +42,18 @@ static void readerr ARGS((FILE *f));
 static const char *
 compression_name(char compr);
 static void       read_bytes ARGS((FILE *ifp, int n, char *buf));
-static Header *   read_header ARGS((FILE *ifp, int channel));
+static Header *   read_header ARGS((FILE *ifp, int outChannel, int verbose));
 static TabEntry * read_table ARGS((FILE *ifp, int tablen));
-static ScanLine * read_channels ARGS((FILE *ifp, Header *head, TabEntry *table, short (*func) ARGS((FILE *)), int ochan ));
-static void       image_to_pnm ARGS((Header *head, ScanLine *image, xelval maxval, int channel));
+static ScanLine * read_channels ARGS((FILE *ifp, Header *head, TabEntry *table, int outChannel ));
+static void       image_to_pnm ARGS((Header *head, ScanLine *image, xelval maxval, int outChannel));
 static void       rle_decompress ARGS((ScanElem *src, int srclen, ScanElem *dest, int destlen));
 
 #define WORSTCOMPR(x)   (2*(x) + 2)
 
 
-static short verbose = 0;
-
-
 
 int
-main(argc, argv)
-    int argc;
-    char *argv[];
+main(int argc, char *argv[])
 {
     FILE *ifp;
     int argn;
@@ -64,7 +62,8 @@ main(argc, argv)
     ScanLine *image;
     Header *head;
     pixval maxval;
-    int channel = -1;
+    long int outChannel = -1;
+    int verbose = 0;
 
     pnm_init(&argc, argv);
 
@@ -84,8 +83,8 @@ main(argc, argv)
                 pm_usage(usage);
 
             s = argv[argn];
-            channel = strtol(argv[argn], &s, 10);
-            if( s == argv[argn] || channel < 0)
+            outChannel = strtol(argv[argn], &s, 10);
+            if( s == argv[argn] || outChannel < 0)
                 pm_usage(usage);
         }
         else
@@ -103,33 +102,29 @@ main(argc, argv)
     if( argn != argc )
         pm_usage(usage);
 
-    head = read_header(ifp, channel);
+    head = read_header(ifp, outChannel, verbose);
     maxval = head->pixmax - head->pixmin;
     if( maxval > PNM_OVERALLMAXVAL )
         pm_error("Maximum sample value in input image (%d) is too large.  "
                  "This program's limit is %d.",
                  maxval, PNM_OVERALLMAXVAL);
-    if (channel >= head->zsize)
+    if (outChannel >= head->zsize)
         pm_error("channel out of range - only %d channels in image",
             head->zsize);
     if( head->storage != STORAGE_VERBATIM )
         table = read_table(ifp, head->ysize * head->zsize);
-    if( head->bpc == 1 )
-        image = read_channels(ifp, head, table, get_byte_as_short, channel);
-    else
-        image = read_channels(ifp, head, table, get_big_short, channel);
-
-    image_to_pnm(head, image, (xelval)maxval, channel);
+ 
+    image = read_channels(ifp, head, table, outChannel);
     pm_close(ifp);
+ 
+    image_to_pnm(head, image, (xelval)maxval, outChannel);
 
     exit(0);
 }
 
 
 static Header *
-read_header(ifp, channel)
-    FILE *ifp;
-    int channel;
+read_header(FILE * const ifp, int const outChannel, int const verbose)
 {
     Header *head;
 
@@ -142,8 +137,13 @@ read_header(ifp, channel)
     head->xsize     = get_big_short(ifp);
     head->ysize     = get_big_short(ifp);
     head->zsize     = get_big_short(ifp);
+    if(head->zsize > 256)
+      pm_error("Too many channels in input image: %u",
+	       (unsigned int) head->zsize );
     head->pixmin    = get_big_long(ifp);
     head->pixmax    = get_big_long(ifp);
+    if(head->pixmin >= head->pixmax)
+      pm_error("Invalid sgi image header: pixmin larger than pixmax");   
     read_bytes(ifp, 4, head->dummy1);
     read_bytes(ifp, 80, head->name);
     head->colormap  = get_big_long(ifp);
@@ -177,7 +177,7 @@ read_header(ifp, channel)
                 case 3:
                     break;
                 default:
-                    if (channel < 0)
+                    if (outChannel < 0)
                         pm_message("%d-channel image, using only first 3 channels", head->zsize);
                     break;
             }
@@ -198,9 +198,7 @@ read_header(ifp, channel)
 
 
 static TabEntry *
-read_table(ifp, tablen)
-    FILE *ifp;
-    int tablen;
+read_table(FILE * const ifp, int const tablen)
 {
     TabEntry *table;
     int i;
@@ -218,23 +216,21 @@ read_table(ifp, tablen)
 
 
 static ScanLine *
-read_channels(ifp, head, table, func, ochan)
-    FILE *ifp;
-    Header *head;
-    TabEntry *table;
-    short (*func) ARGS((FILE *));
-    int ochan;
+read_channels(FILE *        const ifp,
+              Header *      const head,
+              TabEntry *    const table, 
+              int           const outChannel) 
 {
     ScanLine *image;
     ScanElem *temp;
     int channel, maxchannel, sgi_index, i;
     long offset, length;
 
-    if (ochan < 0) {
+    if (outChannel < 0) {
         maxchannel = (head->zsize < 3) ? head->zsize : 3;
         MALLOCARRAY_NOFAIL(image, head->ysize * maxchannel);
     } else {
-        maxchannel = ochan + 1;
+        maxchannel = outChannel + 1;
         MALLOCARRAY_NOFAIL(image, head->ysize);
     }
     if ( table ) 
@@ -243,16 +239,16 @@ read_channels(ifp, head, table, func, ochan)
     for( channel = 0; channel < maxchannel;  channel++ ) {
         unsigned int row;
         for( row = 0; row < head->ysize; row++ ) {
-            int iindex;
+            unsigned long int iindex;
 
             sgi_index = channel * head->ysize + row;
-            iindex = (ochan < 0) ? sgi_index : row;
-            if (ochan < 0 || ochan == channel)
+            iindex = (outChannel < 0) ? sgi_index : row;
+            if (outChannel < 0 || outChannel == channel)
                 MALLOCARRAY_NOFAIL(image[iindex], head->xsize);
 
             if( table ) {
-                if (channel < ochan)
-                    continue;
+                if (channel < outChannel)
+                  continue;
 
                 offset = table[sgi_index].start;
                 length = table[sgi_index].length;
@@ -263,12 +259,24 @@ read_channels(ifp, head, table, func, ochan)
                     pm_error("seek error for offset %ld", offset);
 
                 for( i = 0; i < length; i++ )
-                    temp[i] = (*func)(ifp);
+                    if( head->bpc == 1 )
+                       temp[i] = get_byte_as_short(ifp);
+		    else
+                       temp[i] = get_big_short(ifp);
                 rle_decompress(temp, length, image[iindex], head->xsize);
             }
             else {
                 for( i = 0; i < head->xsize; i++ )
-                    image[iindex][i] = (*func)(ifp);
+		  {
+		    ScanElem p;
+                    if( head->bpc == 1 )
+                      p = get_byte_as_short(ifp);
+		    else
+                      p = get_big_short(ifp);
+
+                    if (channel == -1 || channel ==outChannel)
+		      image[iindex][i] = p;
+		  }
             }
         }
     }
@@ -280,7 +288,10 @@ read_channels(ifp, head, table, func, ochan)
 
 
 static void
-image_to_pnm(Header *head, ScanLine *image, xelval maxval, int channel)
+image_to_pnm(Header   * const head,
+             ScanLine * const image,
+             xelval     const maxval,
+             int        const channel)
 {
     int col, row, format;
     xel *pnmrow = pnm_allocrow(head->xsize);
@@ -316,11 +327,10 @@ image_to_pnm(Header *head, ScanLine *image, xelval maxval, int channel)
 
 
 static void
-rle_decompress(src, srcleft, dest, destleft)
-    ScanElem *src;
-    int srcleft;
-    ScanElem *dest;
-    int destleft;
+rle_decompress(ScanElem * src,
+               int        srcleft,
+               ScanElem * dest,
+               int        destleft)
 {
     int count;
     unsigned char el;
@@ -358,8 +368,7 @@ rle_decompress(src, srcleft, dest, destleft)
 /* basic I/O functions, taken from ilbmtoppm.c */
 
 static short
-get_big_short(ifp)
-    FILE *ifp;
+get_big_short(FILE * const ifp)
 {
     short s;
 
@@ -370,8 +379,7 @@ get_big_short(ifp)
 }
 
 static long
-get_big_long(ifp)
-    FILE *ifp;
+get_big_long(FILE * const ifp)
 {
     long l;
 
@@ -382,8 +390,7 @@ get_big_long(ifp)
 }
 
 static unsigned char
-get_byte(ifp)
-    FILE* ifp;
+get_byte(FILE * const ifp)
 {
     int i;
 
@@ -396,8 +403,7 @@ get_byte(ifp)
 
 
 static void
-readerr(f)
-    FILE *f;
+readerr(FILE * const f)
 {
     if( ferror(f) )
         pm_error("read error");
@@ -407,10 +413,7 @@ readerr(f)
 
 
 static void
-read_bytes(ifp, n, buf)
-    FILE *ifp;
-    int n;
-    char *buf;
+read_bytes(FILE * const ifp, int const n, char * const buf)
 {
     int r;
 
@@ -421,15 +424,14 @@ read_bytes(ifp, n, buf)
 
 
 static short
-get_byte_as_short(ifp)
-    FILE *ifp;
+get_byte_as_short(FILE * const ifp)
 {
     return (short)get_byte(ifp);
 }
 
 
 static const char *
-compression_name(char compr)
+compression_name(char const compr)
 {
     switch( compr ) {
         case STORAGE_VERBATIM:
@@ -440,4 +442,3 @@ compression_name(char compr)
             return "unknown";
     }
 }
-