diff options
| -rw-r--r-- | ChangeLog | 8 | ||||
| -rw-r--r-- | compat/strtoll.c | 9 | ||||
| -rw-r--r-- | compat/strtoul.c | 57 | ||||
| -rw-r--r-- | compat/strtoull.c | 6 | 
4 files changed, 66 insertions, 14 deletions
| @@ -1,3 +1,11 @@ +2002-02-23  Don Porter  <dgp@users.sourceforge.net> + +	* compat/strtoull.c (strtoull): +	* compat/strtoll.c (strtoll): +	* compat/strtoul.c (strtoul): Fixed failure to handle leading +	sign symbols '+' and '-' and '0X' and raise overflow errors. +	[Bug 440916]  Also corrects prototype and errno problems. +  2002-02-23  Mo DeJong  <supermo@bayarea.net>  	* configure: Regen. diff --git a/compat/strtoll.c b/compat/strtoll.c index 2ae6b0a..ca00fd0 100644 --- a/compat/strtoll.c +++ b/compat/strtoll.c @@ -9,7 +9,7 @@   * See the file "license.terms" for information on usage and redistribution   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * - * RCS: @(#) $Id: strtoll.c,v 1.4 2002/02/22 09:04:48 dkf Exp $ + * RCS: @(#) $Id: strtoll.c,v 1.5 2002/02/24 02:53:25 dgp Exp $   */  #include "tcl.h" @@ -22,7 +22,7 @@  /*   *----------------------------------------------------------------------   * - * strtol -- + * strtoll --   *   *	Convert an ASCII string into an integer.   * @@ -39,7 +39,11 @@   *----------------------------------------------------------------------   */ +#if TCL_WIDE_INT_IS_LONG +long long +#else  Tcl_WideInt +#endif  strtoll(string, endPtr, base)      CONST char *string;		/* String of ASCII digits, possibly  				 * preceded by white space.  For bases @@ -72,6 +76,7 @@ strtoll(string, endPtr, base)       * Check for a sign.       */ +    errno = 0;      if (*p == '-') {  	p += 1;  	uwResult = strtoull(p, endPtr, base); diff --git a/compat/strtoul.c b/compat/strtoul.c index e31299d..ddb1682 100644 --- a/compat/strtoul.c +++ b/compat/strtoul.c @@ -9,10 +9,11 @@   * See the file "license.terms" for information on usage and redistribution   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * - * RCS: @(#) $Id: strtoul.c,v 1.3 2002/02/15 23:42:12 kennykb Exp $ + * RCS: @(#) $Id: strtoul.c,v 1.4 2002/02/24 02:53:25 dgp Exp $   */ -#include <ctype.h> +#include "tclInt.h" +#include "tclPort.h"  /*   * The table below is used to convert from ASCII digits to a @@ -53,7 +54,7 @@ static char cvtIn[] = {  unsigned long int  strtoul(string, endPtr, base) -    char *string;		/* String of ASCII digits, possibly +    CONST char *string;		/* String of ASCII digits, possibly  				 * preceded by white space.  For bases  				 * greater than 10, either lower- or  				 * upper-case digits may be used. @@ -67,10 +68,12 @@ strtoul(string, endPtr, base)  				 * else means decimal.  				 */  { -    register char *p; +    register CONST char *p;      register unsigned long int result = 0;      register unsigned digit;      int anyDigits = 0; +    int negative=0; +    int overflow=0;      /*       * Skip any leading blanks. @@ -80,6 +83,14 @@ strtoul(string, endPtr, base)      while (isspace(*p)) {  	p += 1;      } +    if (*p == '-') { +        negative = 1; +        p += 1; +    } else { +        if (*p == '+') { +            p += 1; +        } +    }      /*       * If no base was provided, pick one from the leading characters @@ -90,7 +101,7 @@ strtoul(string, endPtr, base)      {  	if (*p == '0') {  	    p += 1; -	    if (*p == 'x') { +	    if ((*p == 'x') || (*p == 'X')) {  		p += 1;  		base = 16;  	    } else { @@ -111,7 +122,7 @@ strtoul(string, endPtr, base)  	 * Skip a leading "0x" from hex numbers.  	 */ -	if ((p[0] == '0') && (p[1] == 'x')) { +	if ((p[0] == '0') && ((p[1] == 'x') || (p[1] == 'X'))) {  	    p += 2;  	}      } @@ -122,24 +133,33 @@ strtoul(string, endPtr, base)       */      if (base == 8) { +	unsigned long maxres = ULONG_MAX >> 3;  	for ( ; ; p += 1) {  	    digit = *p - '0';  	    if (digit > 7) {  		break;  	    } -	    result = (result << 3) + digit; +	    if (result > maxres) { overflow = 1; } +	    result = (result << 3); +	    if (digit > (ULONG_MAX - result)) { overflow = 1; } +	    result += digit;  	    anyDigits = 1;  	}      } else if (base == 10) { +	unsigned long maxres = ULONG_MAX / 10;  	for ( ; ; p += 1) {  	    digit = *p - '0';  	    if (digit > 9) {  		break;  	    } -	    result = (10*result) + digit; +	    if (result > maxres) { overflow = 1; } +	    result *= 10; +	    if (digit > (ULONG_MAX - result)) { overflow = 1; } +	    result += digit;  	    anyDigits = 1;  	}      } else if (base == 16) { +	unsigned long maxres = ULONG_MAX >> 4;  	for ( ; ; p += 1) {  	    digit = *p - '0';  	    if (digit > ('z' - '0')) { @@ -149,10 +169,14 @@ strtoul(string, endPtr, base)  	    if (digit > 15) {  		break;  	    } -	    result = (result << 4) + digit; +	    if (result > maxres) { overflow = 1; } +	    result = (result << 4); +	    if (digit > (ULONG_MAX - result)) { overflow = 1; } +	    result += digit;  	    anyDigits = 1;  	}      } else if ( base >= 2 && base <= 36 ) { +	unsigned long maxres = ULONG_MAX / base;  	for ( ; ; p += 1) {  	    digit = *p - '0';  	    if (digit > ('z' - '0')) { @@ -162,7 +186,10 @@ strtoul(string, endPtr, base)  	    if (digit >= ( (unsigned) base )) {  		break;  	    } -	    result = result*base + digit; +	    if (result > maxres) { overflow = 1; } +	    result *= base; +	    if (digit > (ULONG_MAX - result)) { overflow = 1; } +	    result += digit;  	    anyDigits = 1;  	}      } @@ -176,8 +203,16 @@ strtoul(string, endPtr, base)      }      if (endPtr != 0) { -	*endPtr = p; +	/* unsafe, but required by the strtoul prototype */ +	*endPtr = (char *) p;      } +    if (overflow) { +	errno = ERANGE; +	return ULONG_MAX; +    }  +    if (negative) { +	return -result; +    }      return result;  } diff --git a/compat/strtoull.c b/compat/strtoull.c index 9544d71..00eca3c 100644 --- a/compat/strtoull.c +++ b/compat/strtoull.c @@ -9,7 +9,7 @@   * See the file "license.terms" for information on usage and redistribution   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * - * RCS: @(#) $Id: strtoull.c,v 1.4 2002/02/22 09:04:48 dkf Exp $ + * RCS: @(#) $Id: strtoull.c,v 1.5 2002/02/24 02:53:25 dgp Exp $   */  #include "tcl.h" @@ -54,7 +54,11 @@ static char cvtIn[] = {   *----------------------------------------------------------------------   */ +#if TCL_WIDE_INT_IS_LONG +unsigned long long +#else  Tcl_WideUInt +#endif  strtoull(string, endPtr, base)      CONST char *string;		/* String of ASCII digits, possibly  				 * preceded by white space.  For bases | 
