diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2007-12-09 17:30:47 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2007-12-09 17:30:47 +0000 |
commit | d97e2f3a64b09a748bb0984fba33f3595298853a (patch) | |
tree | d5f388bde91bdc4ecad19f87c757c2790801ce69 /lib | |
parent | b4799443c85bee0e0afc1fa23e034d2253a07635 (diff) | |
download | netpbm-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.c | 12 | ||||
-rw-r--r-- | lib/libpm.c | 50 | ||||
-rw-r--r-- | lib/pm.h | 6 | ||||
-rw-r--r-- | lib/util/nstring.c | 37 | ||||
-rw-r--r-- | lib/util/nstring.h | 5 |
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 |