about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2007-12-09 17:30:47 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2007-12-09 17:30:47 +0000
commitd97e2f3a64b09a748bb0984fba33f3595298853a (patch)
treed5f388bde91bdc4ecad19f87c757c2790801ce69 /lib
parentb4799443c85bee0e0afc1fa23e034d2253a07635 (diff)
downloadnetpbm-mirror-d97e2f3a64b09a748bb0984fba33f3595298853a.tar.gz
netpbm-mirror-d97e2f3a64b09a748bb0984fba33f3595298853a.tar.xz
netpbm-mirror-d97e2f3a64b09a748bb0984fba33f3595298853a.zip
fix overflow calculation
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@479 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib')
-rw-r--r--lib/fileio.c12
-rw-r--r--lib/libpm.c50
-rw-r--r--lib/pm.h6
-rw-r--r--lib/util/nstring.c37
-rw-r--r--lib/util/nstring.h5
5 files changed, 108 insertions, 2 deletions
diff --git a/lib/fileio.c b/lib/fileio.c
index d891b05a..300ae303 100644
--- a/lib/fileio.c
+++ b/lib/fileio.c
@@ -85,10 +85,18 @@ pm_getuint(FILE * const ifP) {
     do {
         unsigned int const digitVal = ch - '0';
 
-        if (i > INT_MAX/10 - digitVal)
+        if (i > INT_MAX/10)
             pm_error("ASCII decimal integer in file is "
                      "too large to be processed.  ");
-        i = i * 10 + digitVal;
+        
+        i *= 10;
+
+        if (i > INT_MAX - digitVal)
+            pm_error("ASCII decimal integer in file is "
+                     "too large to be processed.  ");
+
+        i += digitVal;
+
         ch = pm_getc(ifP);
     } while (ch >= '0' && ch <= '9');
 
diff --git a/lib/libpm.c b/lib/libpm.c
index 9752d622..34ef3ac4 100644
--- a/lib/libpm.c
+++ b/lib/libpm.c
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <setjmp.h>
 #include <time.h>
+#include <limits.h>
 
 #include "pm_c_util.h"
 #include "mallocvar.h"
@@ -764,3 +765,52 @@ pm_randseed(void) {
     return time(NULL) ^ getpid();
 
 }
+
+
+
+unsigned int
+pm_parse_width(const char * const arg) {
+/*----------------------------------------------------------------------------
+   Return the image width represented by the decimal ASCIIZ string
+   'arg'.  Fail if it doesn't validly represent a width or represents
+   a width that can't be conveniently used in computation.
+-----------------------------------------------------------------------------*/
+    unsigned int width;
+    const char * error;
+
+    interpret_uint(arg, &width, &error);
+
+    if (error) {
+        pm_error("'%s' is invalid as an image width.  %s", arg, error);
+        strfree(error);
+    } else {
+        if (width > INT_MAX-10)
+            pm_error("Width %u is too large for computations.", width);
+    }
+    return width;
+}
+
+
+
+unsigned int
+pm_parse_height(const char * const arg) {
+/*----------------------------------------------------------------------------
+  Same as pm_parse_width(), but for height.
+-----------------------------------------------------------------------------*/
+    unsigned int height;
+    const char * error;
+
+    interpret_uint(arg, &height, &error);
+
+    if (error) {
+        pm_error("'%s' is invalid as an image height.  %s", arg, error);
+        strfree(error);
+    } else {
+        if (height > INT_MAX-10)
+            pm_error("Height %u is too large for computations.", height);
+    }
+    return height;
+}
+
+
+
diff --git a/lib/pm.h b/lib/pm.h
index 4b4602c2..b38580ff 100644
--- a/lib/pm.h
+++ b/lib/pm.h
@@ -359,6 +359,12 @@ pm_arg0toprogname(const char arg0[]);
 unsigned int
 pm_randseed(void);
 
+unsigned int
+pm_parse_width(const char * const arg);
+
+unsigned int
+pm_parse_height(const char * const arg);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/util/nstring.c b/lib/util/nstring.c
index feb8215e..3e2da669 100644
--- a/lib/util/nstring.c
+++ b/lib/util/nstring.c
@@ -915,3 +915,40 @@ strishex(const char * const subject) {
 
     return retval;
 }
+
+
+
+void
+interpret_uint(const char *   const string,
+               unsigned int * const valueP,
+               const char **  const errorP) {
+
+    if (string[0] == '\0')
+        asprintfN(errorP, "Null string.");
+    else {
+        /* strtoul() does a bizarre thing where if the number is out
+           of range, it returns a clamped value but tells you about it
+           by setting errno = ERANGE.  If it is not out of range,
+           strtoul() leaves errno alone.
+        */
+        char * tail;
+        unsigned long ulongValue;
+        
+        errno = 0;  // So we can tell if strtoul() overflowed
+
+        ulongValue = strtoul(string, &tail, 10);
+
+        if (tail[0] != '\0')
+            asprintfN(errorP, "Non-digit stuff in string: %s", tail);
+        else if (errno == ERANGE)
+            asprintfN(errorP, "Number too large");
+        else if (ulongValue > UINT_MAX)
+            asprintfN(errorP, "Number too large");
+        else {
+            *valueP = ulongValue;
+            *errorP = NULL;
+        }
+    }
+}
+
+
diff --git a/lib/util/nstring.h b/lib/util/nstring.h
index 9d61cfa5..1e5ca4c3 100644
--- a/lib/util/nstring.h
+++ b/lib/util/nstring.h
@@ -183,6 +183,11 @@ memmemN(const void * const haystackArg,
 bool
 strishex(const char * const subject);
 
+void
+interpret_uint(const char *   const string,
+               unsigned int * const valueP,
+               const char **  const errorP);
+
 #ifdef __cplusplus
 }
 #endif