- added integer overflow checks to many memory allocation calls
authorTony Cook <tony@develop=help.com>
Mon, 5 Dec 2005 03:23:08 +0000 (03:23 +0000)
committerTony Cook <tony@develop=help.com>
Mon, 5 Dec 2005 03:23:08 +0000 (03:23 +0000)
13 files changed:
Changes
bmp.c
convert.c
datatypes.c
draw.c
error.c
fills.c
filters.c
font.c
img16.c
palimg.c
t/t021sixteen.t
t/t023palette.t

diff --git a/Changes b/Changes
index 7d4d7fd..f34a3f2 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1206,6 +1206,7 @@ Revision history for Perl extension Imager.
   - more examples
   - add AUTHOR, REVISION.
 - add smoke test for nearest_color filter
+- added integer overflow checks to many memory allocation calls
 
 =================================================================
 
diff --git a/bmp.c b/bmp.c
index 2e55f52..b4e92e0 100644 (file)
--- a/bmp.c
+++ b/bmp.c
@@ -413,6 +413,7 @@ write_1bit_data(io_glue *ig, i_img *im) {
   unsigned char *out;
   int line_size = (im->xsize+7) / 8;
   int x, y;
+  int unpacked_size;
 
   /* round up to nearest multiple of four */
   line_size = (line_size + 3) / 4 * 4;
@@ -420,10 +421,18 @@ write_1bit_data(io_glue *ig, i_img *im) {
   if (!write_bmphead(ig, im, 1, line_size * im->ysize))
     return 0;
 
-  line = mymalloc(im->xsize + 8);
+  /* this shouldn't be an issue, but let's be careful */
+  unpacked_size = im->xsize + 8;
+  if (unpacked_size < im->xsize) {
+    i_push_error(0, "integer overflow during memory allocation");
+    return 0;
+  }
+  line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
   memset(line + im->xsize, 0, 8);
-  
-  packed = mymalloc(line_size);
+
+  /* size allocated here is always much smaller than xsize, hence
+     can't overflow int */
+  packed = mymalloc(line_size); /* checked 29jun05 tonyc */
   memset(packed, 0, line_size);
   
   for (y = im->ysize-1; y >= 0; --y) {
@@ -474,6 +483,7 @@ write_4bit_data(io_glue *ig, i_img *im) {
   unsigned char *out;
   int line_size = (im->xsize+1) / 2;
   int x, y;
+  int unpacked_size;
 
   /* round up to nearest multiple of four */
   line_size = (line_size + 3) / 4 * 4;
@@ -481,10 +491,18 @@ write_4bit_data(io_glue *ig, i_img *im) {
   if (!write_bmphead(ig, im, 4, line_size * im->ysize))
     return 0;
 
-  line = mymalloc(im->xsize + 2);
+  /* this shouldn't be an issue, but let's be careful */
+  unpacked_size = im->xsize + 2;
+  if (unpacked_size < im->xsize) {
+    i_push_error(0, "integer overflow during memory allocation");
+    return 0;
+  }
+  line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
   memset(line + im->xsize, 0, 2);
   
-  packed = mymalloc(line_size);
+  /* size allocated here is always much smaller than xsize, hence
+     can't overflow int */
+  packed = mymalloc(line_size); /* checked 29jun05 tonyc */
   memset(packed, 0, line_size);
   
   for (y = im->ysize-1; y >= 0; --y) {
@@ -522,6 +540,7 @@ write_8bit_data(io_glue *ig, i_img *im) {
   i_palidx *line;
   int line_size = im->xsize;
   int y;
+  int unpacked_size;
 
   /* round up to nearest multiple of four */
   line_size = (line_size + 3) / 4 * 4;
@@ -529,7 +548,13 @@ write_8bit_data(io_glue *ig, i_img *im) {
   if (!write_bmphead(ig, im, 8, line_size * im->ysize))
     return 0;
 
-  line = mymalloc(im->xsize + 4);
+  /* this shouldn't be an issue, but let's be careful */
+  unpacked_size = im->xsize + 4;
+  if (unpacked_size < im->xsize) {
+    i_push_error(0, "integer overflow during memory allocation");
+    return 0;
+  }
+  line = mymalloc(unpacked_size); /* checked 29jun05 tonyc */
   memset(line + im->xsize, 0, 4);
   
   for (y = im->ysize-1; y >= 0; --y) {
@@ -565,13 +590,20 @@ write_24bit_data(io_glue *ig, i_img *im) {
   unsigned char *samples;
   int y;
   int line_size = 3 * im->xsize;
+
+  /* just in case we implement a direct format with 2bytes/pixel
+     (unlikely though) */
+  if (line_size / 3 != im->xsize) {
+    i_push_error(0, "integer overflow during memory allocation");
+    return 0;
+  }
   
   line_size = (line_size + 3) / 4 * 4;
   
   if (!write_bmphead(ig, im, 24, line_size * im->ysize))
     return 0;
   chans = im->channels >= 3 ? bgr_chans : grey_chans;
-  samples = mymalloc(line_size);
+  samples = mymalloc(line_size); /* checked 29jun05 tonyc */
   memset(samples, 0, line_size);
   for (y = im->ysize-1; y >= 0; --y) {
     i_gsamp(im, 0, im->xsize, y, samples, chans, 3);
@@ -646,6 +678,15 @@ read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
     return NULL;
   }
 
+  if (xsize + 8 < xsize) { /* if there was overflow */
+    /* we check with 8 because we allocate that much for the decoded 
+       line buffer */
+    i_push_error(0, "integer overflow during memory allocation");
+    return NULL;
+  }
+
+  /* if xsize+7 is ok then (xsize+7)/8 will be and the minor
+     adjustments below won't make it overflow */
   line_size = (line_size+3) / 4 * 4;
 
   if (ysize > 0) {
@@ -697,8 +738,8 @@ read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   
   i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
 
-  packed = mymalloc(line_size);
-  line = mymalloc(xsize+8);
+  packed = mymalloc(line_size); /* checked 29jun05 tonyc */
+  line = mymalloc(xsize+8); /* checked 29jun05 tonyc */
   while (y != lasty) {
     if (ig->readcb(ig, packed, line_size) != line_size) {
       myfree(packed);
@@ -751,6 +792,8 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   int size, i;
   long base_offset;
 
+  /* line_size is going to be smaller than xsize in most cases (and
+     when it's not, xsize is itself small), and hence not overflow */
   line_size = (line_size+3) / 4 * 4;
 
   if (ysize > 0) {
@@ -802,10 +845,11 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   }
   
   if (line_size < 260)
-    packed = mymalloc(260);
+    packed = mymalloc(260); /* checked 29jun05 tonyc */
   else
-    packed = mymalloc(line_size);
-  line = mymalloc(xsize+1);
+    packed = mymalloc(line_size); /* checked 29jun05 tonyc */
+  /* xsize won't approach MAXINT */
+  line = mymalloc(xsize+1); /* checked 29jun05 tonyc */
   if (compression == BI_RGB) {
     i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
     while (y != lasty) {
@@ -930,6 +974,10 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   long base_offset;
 
   line_size = (line_size+3) / 4 * 4;
+  if (line_size < xsize) { /* if it overflowed (unlikely, but check) */
+    i_push_error(0, "integer overflow during memory allocation");
+    return NULL;
+  }
 
   if (ysize > 0) {
     y = ysize-1;
@@ -978,7 +1026,7 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
     }
   }
   
-  line = mymalloc(line_size);
+  line = mymalloc(line_size); /* checked 29jun05 tonyc */
   if (compression == BI_RGB) {
     i_tags_add(&im->tags, "bmp_compression_name", 0, "BI_RGB", -1, 0);
     while (y != lasty) {
@@ -1191,7 +1239,7 @@ read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
     i_push_error(0, "integer overflow calculating buffer size");
     return NULL;
   }
-  line = mymalloc(bytes);
+  line = mymalloc(bytes); /* checked 29jun05 tonyc */
   while (y != lasty) {
     p = line;
     for (x = 0; x < xsize; ++x) {
index c3bf132..6d92fbb 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -68,8 +68,9 @@ i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan) {
     }
     if (im->bits == i_8_bits && src->bits == i_8_bits) {
       i_color *vals;
-      
-      vals = mymalloc(sizeof(i_color) * src->xsize);
+
+      /* we can always allocate a single scanline of i_color */
+      vals = mymalloc(sizeof(i_color) * src->xsize); /* checked 04Jul05 tonyc */
       for (y = 0; y < src->ysize; ++y) {
         i_glin(src, 0, src->xsize, y, vals);
         for (x = 0; x < src->xsize; ++x) {
@@ -97,8 +98,10 @@ i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan) {
     }
     else {
       i_fcolor *vals;
-      
-      vals = mymalloc(sizeof(i_fcolor) * src->xsize);
+
+      /* we can always allocate a single scanline of i_fcolor 
+         for a >8 image */
+      vals = mymalloc(sizeof(i_fcolor) * src->xsize); /* checked 4Jul05 tonyc */
       for (y = 0; y < src->ysize; ++y) {
         i_glinf(src, 0, src->xsize, y, vals);
         for (x = 0; x < src->xsize; ++x) {
@@ -142,7 +145,8 @@ i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan) {
     /* just translate the color table */
     count = i_colorcount(src);
     outcount = i_colorcount(im);
-    colors = mymalloc(count * sizeof(i_color));
+    /* color table allocated for image, so it must fit */
+    colors = mymalloc(count * sizeof(i_color)); /* check 04Jul05 tonyc */
     i_getcolors(src, 0, colors, count);
     for (index = 0; index < count; ++index) {
       for (j = 0; j < outchan; ++j) {
@@ -171,7 +175,10 @@ i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan) {
       i_addcolors(im, colors, count-outcount);
     }
     /* and copy the indicies */
-    vals = mymalloc(sizeof(i_palidx) * im->xsize);
+    /* i_palidx is always unsigned char and will never be bigger than short
+       and since a line of 4-byte i_colors can fit then a line of i_palidx
+       will fit */
+    vals = mymalloc(sizeof(i_palidx) * im->xsize); /* checked 4jul05 tonyc */
     for (y = 0; y < im->ysize; ++y) {
       i_gpal(src, 0, im->xsize, y, vals);
       i_ppal(im, 0, im->xsize, y, vals);
index 2afdc9a..cc93044 100644 (file)
 struct i_bitmap*
 btm_new(int xsize,int ysize) {
   int i;
+  int bytes;
   struct i_bitmap *btm;
-  btm=(struct i_bitmap*)mymalloc(sizeof(struct i_bitmap));
-  btm->data=(char*)mymalloc((xsize*ysize+8)/8);
+  btm=(struct i_bitmap*)mymalloc(sizeof(struct i_bitmap)); /* checked 4jul05 tonyc */
+  bytes = (xsize*ysize+8)/8;
+  if (bytes * 8 / ysize < xsize-1) { /* this is kind of rough */
+    fprintf(stderr, "Integer overflow allocating bitmap %d x %d", xsize, ysize);
+    exit(3);
+  }
+  btm->data=(char*)mymalloc(bytes); /* checked 4jul05 tonyc */
   btm->xsize=xsize;
   btm->ysize=ysize;
   for(i=0;i<(xsize*ysize+8)/8;i++) btm->data[i]=0; /* Is this always needed */
@@ -56,11 +62,11 @@ btm_set(struct i_bitmap *btm,int x,int y) {
 struct llink *
 llink_new(struct llink* p,int size) {
   struct llink *l;
-  l       = mymalloc(sizeof(struct llink));
+  l       = mymalloc(sizeof(struct llink)); /* checked 4jul05 tonyc */
   l->n    = NULL;
   l->p    = p;
   l->fill = 0;
-  l->data = mymalloc(size);
+  l->data = mymalloc(size); /* checked 4jul05 tonyc - depends on caller to llist_push */
   return l;
 }
 
@@ -97,7 +103,7 @@ llist_llink_push(struct llist *lst, struct llink *lnk,void *data) {
 struct llist *
 llist_new(int multip, int ssize) {
   struct llist *l;
-  l         = mymalloc(sizeof(struct llist));
+  l         = mymalloc(sizeof(struct llist)); /* checked 4jul05 tonyc */
   l->h      = NULL;
   l->t      = NULL;
   l->multip = multip;
@@ -198,7 +204,7 @@ octt_new() {
   int i;
   struct octt *t;
   
-  t=(struct octt*)mymalloc(sizeof(struct octt));
+  t=(struct octt*)mymalloc(sizeof(struct octt)); /* checked 4jul05 tonyc */
   for(i=0;i<8;i++) t->t[i]=NULL;
   t->cnt=0;
   return t;
diff --git a/draw.c b/draw.c
index d7426e2..6cca0a0 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -8,9 +8,16 @@
 void
 i_mmarray_cr(i_mmarray *ar,int l) {
   int i;
+  int alloc_size;
 
   ar->lines=l;
-  ar->data=mymalloc(sizeof(minmax)*l);
+  alloc_size = sizeof(minmax) * l;
+  /* check for overflow */
+  if (alloc_size / l != sizeof(minmax)) {
+    fprintf(stderr, "overflow calculating memory allocation");
+    exit(3);
+  }
+  ar->data=mymalloc(alloc_size); /* checked 5jul05 tonyc */
   for(i=0;i<l;i++) { ar->data[i].max=-1; ar->data[i].min=MAXINT; }
 }
 
@@ -51,10 +58,10 @@ void
 i_mmarray_render_fill(i_img *im,i_mmarray *ar,i_fill_t *fill) {
   int x, w, y;
   if (im->bits == i_8_bits && fill->fill_with_color) {
-    i_color *line = mymalloc(sizeof(i_color) * im->xsize);
+    i_color *line = mymalloc(sizeof(i_color) * im->xsize); /* checked 5jul05 tonyc */
     i_color *work = NULL;
     if (fill->combine)
-      work = mymalloc(sizeof(i_color) * im->xsize);
+      work = mymalloc(sizeof(i_color) * im->xsize); /* checked 5jul05 tonyc */
     for(y=0;y<ar->lines;y++) {
       if (ar->data[y].max!=-1) {
         x = ar->data[y].min;
@@ -77,10 +84,10 @@ i_mmarray_render_fill(i_img *im,i_mmarray *ar,i_fill_t *fill) {
       myfree(work);
   }
   else {
-    i_fcolor *line = mymalloc(sizeof(i_fcolor) * im->xsize);
+    i_fcolor *line = mymalloc(sizeof(i_fcolor) * im->xsize); /* checked 5jul05 tonyc */
     i_fcolor *work = NULL;
     if (fill->combinef)
-      work = mymalloc(sizeof(i_fcolor) * im->xsize);
+      work = mymalloc(sizeof(i_fcolor) * im->xsize); /* checked 5jul05 tonyc */
     for(y=0;y<ar->lines;y++) {
       if (ar->data[y].max!=-1) {
         x = ar->data[y].min;
@@ -492,11 +499,21 @@ i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
   mm_log((1,"i_box_cfill(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,fill 0x%x)\n",im,x1,y1,x2,y2,fill));
 
   ++x2;
+  if (x1 < 0)
+    x1 = 0;
+  if (y1 < 0) 
+    y1 = 0;
+  if (x2 > im->xsize) 
+    x2 = im->xsize;
+  if (y2 >= im->ysize)
+    y2 = im->ysize-1;
+  if (x1 >= x2 || y1 > y2)
+    return;
   if (im->bits == i_8_bits && fill->fill_with_color) {
-    i_color *line = mymalloc(sizeof(i_color) * (x2 - x1));
+    i_color *line = mymalloc(sizeof(i_color) * (x2 - x1)); /* checked 5jul05 tonyc */
     i_color *work = NULL;
     if (fill->combine)
-      work = mymalloc(sizeof(i_color) * (x2-x1));
+      work = mymalloc(sizeof(i_color) * (x2-x1)); /* checked 5jul05 tonyc */
     while (y1 <= y2) {
       if (fill->combine) {
         i_glin(im, x1, x2, y1, line);
@@ -514,9 +531,9 @@ i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
       myfree(work);
   }
   else {
-    i_fcolor *line = mymalloc(sizeof(i_fcolor) * (x2 - x1));
+    i_fcolor *line = mymalloc(sizeof(i_fcolor) * (x2 - x1)); /* checked 5jul05 tonyc */
     i_fcolor *work;
-    work = mymalloc(sizeof(i_fcolor) * (x2 - x1));
+    work = mymalloc(sizeof(i_fcolor) * (x2 - x1)); /* checked 5jul05 tonyc */
 
     while (y1 <= y2) {
       if (fill->combine) {
@@ -894,8 +911,8 @@ i_bezier_multi(i_img *im,int l,double *x,double *y,i_color *val) {
   int n=l-1;
   double itr,ccoef;
 
-
-  bzcoef=mymalloc(sizeof(double)*l);
+  /* this is the same size as the x and y arrays, so shouldn't overflow */
+  bzcoef=mymalloc(sizeof(double)*l); /* checked 5jul05 tonyc */
   for(k=0;k<l;k++) bzcoef[k]=perm(n,k);
   ICL_info(val);
 
@@ -926,16 +943,6 @@ i_bezier_multi(i_img *im,int l,double *x,double *y,i_color *val) {
   myfree(bzcoef);
 }
 
-
-
-
-
-
-
-
-
-
-
 /* Flood fill 
 
    REF: Graphics Gems I. page 282+
@@ -983,7 +990,7 @@ static
 struct stack_element*
 crdata(int left,int right,int dadl,int dadr,int y, int dir) {
   struct stack_element *ste;
-  ste              = mymalloc(sizeof(struct stack_element));
+  ste              = mymalloc(sizeof(struct stack_element)); /* checked 5jul05 tonyc */
   ste->myLx        = left;
   ste->myRx        = right;
   ste->dadLx       = dadl;
@@ -1231,10 +1238,11 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
   btm = i_flood_fill_low(im, seedx, seedy, &bxmin, &bxmax, &bymin, &bymax);
 
   if (im->bits == i_8_bits && fill->fill_with_color) {
-    i_color *line = mymalloc(sizeof(i_color) * (bxmax - bxmin));
+    /* bxmax/bxmin are inside the image, hence this won't overflow */
+    i_color *line = mymalloc(sizeof(i_color) * (bxmax - bxmin)); /* checked 5jul05 tonyc */
     i_color *work = NULL;
     if (fill->combine)
-      work = mymalloc(sizeof(i_color) * (bxmax - bxmin));
+      work = mymalloc(sizeof(i_color) * (bxmax - bxmin)); /* checked 5jul05 tonyc */
 
     for(y=bymin; y<=bymax; y++) {
       x = bxmin;
@@ -1266,10 +1274,11 @@ i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
       myfree(work);
   }
   else {
-    i_fcolor *line = mymalloc(sizeof(i_fcolor) * (bxmax - bxmin));
+    /* bxmax/bxmin are inside the image, hence this won't overflow */
+    i_fcolor *line = mymalloc(sizeof(i_fcolor) * (bxmax - bxmin)); /* checked 5jul05 tonyc */
     i_fcolor *work = NULL;
     if (fill->combinef)
-      work = mymalloc(sizeof(i_fcolor) * (bxmax - bxmin));
+      work = mymalloc(sizeof(i_fcolor) * (bxmax - bxmin)); /* checked 5jul05 tonyc */
     
     for(y=bymin;y<=bymax;y++) {
       x = bxmin;
diff --git a/error.c b/error.c
index b1e87d3..9876ac6 100644 (file)
--- a/error.c
+++ b/error.c
@@ -95,7 +95,9 @@ void i_set_argv0(char const *name) {
   char *dupl;
   if (!name)
     return;
-  dupl = mymalloc(strlen(name)+1);
+  /* if the user has an existing string of MAXINT length then
+     the system is broken anyway */
+  dupl = mymalloc(strlen(name)+1); /* check 17jul05 tonyc */
   strcpy(dupl, name);
   if (argv0)
     myfree(argv0);
@@ -222,9 +224,11 @@ void i_push_error(int code, char const *msg) {
   if (error_space[error_sp] < size) {
     if (error_stack[error_sp].msg)
       myfree(error_stack[error_sp].msg);
-    /* memory allocated on the following line is only ever release when 
+    /* memory allocated on the following line is only ever released when 
        we need a bigger string */
-    error_stack[error_sp].msg = mymalloc(size);
+    /* size is size (len+1) of an existing string, overflow would mean
+       the system is broken anyway */
+    error_stack[error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
     error_space[error_sp] = size;
   }
   strcpy(error_stack[error_sp].msg, msg);
@@ -270,6 +274,9 @@ void i_push_errorf(int code, char const *fmt, ...) {
   va_end(ap);
 }
 
+#ifdef IMAGER_I_FAILED
+#error "This isn't used and is untested"
+
 /*
 =item i_failed(char const *msg)
 
@@ -326,6 +333,8 @@ int i_failed(int code, char const *msg) {
   return 0;
 }
 
+#endif
+
 /*
 =back
 
diff --git a/fills.c b/fills.c
index ed2a205..e075c53 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -220,7 +220,7 @@ If combine is non-zero then alpha values will be combined.
 i_fill_t *
 i_new_fill_solidf(i_fcolor *c, int combine) {
   int ch;
-  i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
+  i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
   
   if (combine) {
     *fill = base_solid_fill_comb;
@@ -249,7 +249,7 @@ If combine is non-zero then alpha values will be combined.
 i_fill_t *
 i_new_fill_solid(i_color *c, int combine) {
   int ch;
-  i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t));
+  i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
 
   if (combine) {
     *fill = base_solid_fill_comb;
@@ -484,7 +484,7 @@ Create an image based fill.
 */
 i_fill_t *
 i_new_fill_image(i_img *im, double *matrix, int xoff, int yoff, int combine) {
-  struct i_fill_image_t *fill = mymalloc(sizeof(*fill));
+  struct i_fill_image_t *fill = mymalloc(sizeof(*fill)); /* checked 14jul05 tonyc */
 
   fill->base.fill_with_color = fill_image;
   fill->base.fill_with_fcolor = fill_imagef;
@@ -599,7 +599,7 @@ i_fill_t *
 i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg, 
                 int combine, int hatch, unsigned char *cust_hatch,
                 int dx, int dy) {
-  i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t));
+  i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t)); /* checked 14jul05 tonyc */
 
   fill->base.fill_with_color = fill_hatch;
   fill->base.fill_with_fcolor = fill_hatchf;
index 2523de5..dfd12ca 100644 (file)
--- a/filters.c
+++ b/filters.c
@@ -937,6 +937,7 @@ i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
   int channels = im->channels;
   int xsize    = im->xsize;
   int ysize    = im->ysize;
+  int bytes;
 
   float *fdist;
 
@@ -947,7 +948,20 @@ i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
     ICL_info(&ival[p]);
   }
 
-  fdist = mymalloc( sizeof(float) * num );
+  /* on the systems I have sizeof(float) == sizeof(int) and thus
+     this would be same size as the arrays xo and yo point at, but this
+     may not be true for other systems
+
+     since the arrays here are caller controlled, I assume that on
+     overflow is a programming error rather than an end-user error, so
+     calling exit() is justified.
+  */
+  bytes = sizeof(float) * num;
+  if (bytes / num != sizeof(float)) {
+    fprintf(stderr, "integer overflow calculating memory allocation");
+    exit(1);
+  }
+  fdist = mymalloc( bytes ); /* checked 14jul05 tonyc */
   
   for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
     float cs = 0;
@@ -1047,6 +1061,72 @@ i_nearest_color_foo(i_img *im, int num, int *xo, int *yo, i_color *ival, int dme
   }
 }
 
+/*
+=item i_nearest_color(im, num, xo, yo, oval, dmeasure)
+
+This wasn't document - quoth Addi:
+
+  An arty type of filter
+
+FIXME: check IRC logs for actual text.
+
+Inputs:
+
+=over
+
+=item *
+
+i_img *im - image to render on.
+
+=item *
+
+int num - number of points/colors in xo, yo, oval
+
+=item *
+
+int *xo - array of I<num> x positions
+
+=item *
+
+int *yo - array of I<num> y positions
+
+=item *
+
+i_color *oval - array of I<num> colors
+
+xo, yo, oval correspond to each other, the point xo[i], yo[i] has a
+color something like oval[i], at least closer to that color than other
+points.
+
+=item *
+
+int dmeasure - how we measure the distance from some point P(x,y) to
+any (xo[i], yo[i]).
+
+Valid values are:
+
+=over
+
+=item 0
+
+euclidean distance: sqrt((x2-x1)**2 + (y2-y1)**2)
+
+=item 1
+
+square of euclidean distance: ((x2-x1)**2 + (y2-y1)**2)
+
+=item 2
+
+manhattan distance: max((y2-y1)**2, (x2-x1)**2)
+
+=back
+
+An invalid value causes an error exit (the program is aborted).
+
+=back
+
+=cut
+ */
 void
 i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasure) {
   i_color *ival;
@@ -1058,7 +1138,7 @@ i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasur
   int ysize    = im->ysize;
   int *cmatch;
 
-  mm_log((1,"i_nearest_color(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
+  mm_log((1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
 
   tval   = mymalloc( sizeof(float)*num*im->channels );
   ival   = mymalloc( sizeof(i_color)*num );
@@ -1120,12 +1200,13 @@ i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasur
     c1 = 1.0-c2;
     
     for(ch = 0; ch<im->channels; ch++) 
-      tval[midx*im->channels + ch] = c1*tval[midx*im->channels + ch] + c2 * (float) val.channel[ch];
+      tval[midx*im->channels + ch] = 
+        c1*tval[midx*im->channels + ch] + c2 * (float) val.channel[ch];
   
-    
   }
 
-  for(p = 0; p<num; p++) for(ch = 0; ch<im->channels; ch++) ival[p].channel[ch] = tval[p*im->channels + ch];
+  for(p = 0; p<num; p++) for(ch = 0; ch<im->channels; ch++)
+    ival[p].channel[ch] = tval[p*im->channels + ch];
 
   i_nearest_color_foo(im, num, xo, yo, ival, dmeasure);
 }
diff --git a/font.c b/font.c
index 6046d7a..9564257 100644 (file)
--- a/font.c
+++ b/font.c
@@ -461,7 +461,8 @@ Sets *outlen to the number of bytes used in the output string.
 
 static char *
 t1_from_utf8(char const *in, int len, int *outlen) {
-  char *out = mymalloc(len+1);
+  /* at this point len is from a perl SV, so can't approach MAXINT */
+  char *out = mymalloc(len+1); /* checked 5Nov05 tonyc */
   char *p = out;
   unsigned long c;
 
@@ -992,7 +993,7 @@ i_tt_new(char *fontname) {
   
   /* allocate memory for the structure */
   
-  handle = mymalloc( sizeof(TT_Fonthandle) );
+  handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */
 
   /* load the typeface */
   error = TT_Open_Face( engine, fontname, &handle->face );
@@ -1082,10 +1083,15 @@ i_tt_init_raster_map( TT_Raster_Map* bit, int width, int height, int smooth ) {
     bit->cols  = ( bit->width + 7 ) / 8;    /* convert to # of bytes     */
     bit->size  = bit->rows * bit->cols;     /* number of bytes in buffer */
   }
+
+  if (bit->size / bit->rows != bit->cols) {
+    m_fatal(0, "Integer overflow calculating bitmap size (%d, %d)\n",
+            bit->width, bit->rows);
+  }
   
   mm_log((1,"i_tt_init_raster_map: bit->width %d, bit->cols %d, bit->rows %d, bit->size %d)\n", bit->width, bit->cols, bit->rows, bit->size ));
 
-  bit->bitmap = (void *) mymalloc( bit->size );
+  bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */
   if ( !bit->bitmap ) m_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size );
 }
 
diff --git a/img16.c b/img16.c
index 92f998c..5db8172 100644 (file)
--- a/img16.c
+++ b/img16.c
@@ -143,7 +143,7 @@ Creates a new 16-bit per sample image.
 =cut
 */
 i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
-  int bytes;
+  int bytes, line_bytes;
   mm_log((1,"i_img_16_new(x %d, y %d, ch %d)\n", x, y, ch));
 
   if (x < 1 || y < 1) {
@@ -160,6 +160,15 @@ i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
     return NULL;
   }
   
+  /* basic assumption: we can always allocate a buffer representing a
+     line from the image, otherwise we're going to have trouble
+     working with the image */
+  line_bytes = sizeof(i_fcolor) * x;
+  if (line_bytes / x != sizeof(i_fcolor)) {
+    i_push_error(0, "integer overflow calculating scanline allocation");
+    return NULL;
+  }
+
   *im = IIM_base_16bit_direct;
   i_tags_new(&im->tags);
   im->xsize = x;
index 886697b..f586f4e 100644 (file)
--- a/palimg.c
+++ b/palimg.c
@@ -84,7 +84,7 @@ Currently 0 < maxpal <= 256
 */
 i_img *i_img_pal_new_low(i_img *im, int x, int y, int channels, int maxpal) {
   i_img_pal_ext *palext;
-  int bytes;
+  int bytes, line_bytes;
 
   i_clear_error();
   if (maxpal < 1 || maxpal > 256) {
@@ -101,7 +101,16 @@ i_img *i_img_pal_new_low(i_img *im, int x, int y, int channels, int maxpal) {
   }
   bytes = sizeof(i_palidx) * x * y;
   if (bytes / y / sizeof(i_palidx) != x) {
-    i_push_errorf(0, "integer overflow calculating image allocation");
+    i_push_error(0, "integer overflow calculating image allocation");
+    return NULL;
+  }
+
+  /* basic assumption: we can always allocate a buffer representing a
+     line from the image, otherwise we're going to have trouble
+     working with the image */
+  line_bytes = sizeof(i_color) * x;
+  if (line_bytes / x != sizeof(i_color)) {
+    i_push_error(0, "integer overflow calculating scanline allocation");
     return NULL;
   }
 
index e8904e1..598c815 100644 (file)
@@ -1,7 +1,7 @@
 #!perl -w
 use strict;
 use lib 't';
-use Test::More tests => 83;
+use Test::More tests => 85;
 
 BEGIN { use_ok(Imager=>qw(:all :handy)) }
 
@@ -132,6 +132,17 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/,
 
     cmp_ok(Imager->errstr, '=~', qr/integer overflow/,
            "check the error message");
+
+    # check we can allocate a scanline, unlike double images the scanline
+    # in the image itself is smaller than a line of i_fcolor
+    # divide by 2 to get to int range, by 2 for 2 bytes/pixel, by 3 to 
+    # fit the image allocation in, but for the floats to overflow
+    my $dim4 = $uint_range / 2 / 2 / 3;
+    my $im_o = Imager->new(xsize=>$dim4, ysize=>1, channels=>1, bits=>16);
+    is($im_o, undef, "integer overflow check - scanline");
+    cmp_ok(Imager->errstr, '=~',
+           qr/integer overflow calculating scanline allocation/,
+           "check error message");
   }
 }
 
index 3157821..6b08196 100644 (file)
@@ -2,7 +2,7 @@
 # some of this is tested in t01introvert.t too
 use strict;
 use lib 't';
-use Test::More tests => 62;
+use Test::More tests => 64;
 BEGIN { use_ok("Imager"); }
 
 my $img = Imager->new(xsize=>50, ysize=>50, type=>'paletted');
@@ -139,7 +139,7 @@ cmp_ok(Imager->errstr, '=~', qr/Channels must be positive and <= 4/,
   use Config;
  SKIP:
   {
-    skip("don't want to allocate 4Gb", 8)
+    skip("don't want to allocate 4Gb", 10)
       unless $Config{intsize} == 4;
 
     my $uint_range = 256 ** $Config{intsize};
@@ -164,13 +164,23 @@ cmp_ok(Imager->errstr, '=~', qr/Channels must be positive and <= 4/,
     $im_b = Imager->new(xsize=>$dim3, ysize=>$dim3, channels=>3, type=>'paletted');
     is($im_b, undef, "integer overflow check - 3 channel");
     
-    $im_b = Imager->new(xisze=>$dim3, ysize=>1, channels=>3, type=>'paletted');
+    $im_b = Imager->new(xsize=>$dim3, ysize=>1, channels=>3, type=>'paletted');
     ok($im_b, "but same width ok");
-    $im_b = Imager->new(xisze=>1, ysize=>$dim3, channels=>3, type=>'paletted');
+    $im_b = Imager->new(xsize=>1, ysize=>$dim3, channels=>3, type=>'paletted');
     ok($im_b, "but same height ok");
 
     cmp_ok(Imager->errstr, '=~', qr/integer overflow/,
            "check the error message");
+
+    # test the scanline allocation check
+    # divide by 2 to get int range, by 3 so that the image (one byte/pixel)
+    # doesn't integer overflow, but the scanline of i_color (4/pixel) does
+    my $dim4 = $uint_range / 2 / 3;
+    my $im_o = Imager->new(xsize=>$dim4, ysize=>1, channels=>3, type=>'paletted');
+    is($im_o, undef, "integer overflow check - scanline size");
+    cmp_ok(Imager->errstr, '=~', 
+           qr/integer overflow calculating scanline allocation/,
+           "check error message");
   }
 }