summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2002-02-24 02:53:25 (GMT)
committerdgp <dgp@users.sourceforge.net>2002-02-24 02:53:25 (GMT)
commita0211643722bd3be1a1b6a97595bfc96720edb98 (patch)
tree6218488a2214453fe2c2ddca22777e70958184f2
parentf21907fb023f9ce87e222745ee167b897e08a98b (diff)
downloadtcl-a0211643722bd3be1a1b6a97595bfc96720edb98.zip
tcl-a0211643722bd3be1a1b6a97595bfc96720edb98.tar.gz
tcl-a0211643722bd3be1a1b6a97595bfc96720edb98.tar.bz2
* 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.
-rw-r--r--ChangeLog8
-rw-r--r--compat/strtoll.c9
-rw-r--r--compat/strtoul.c57
-rw-r--r--compat/strtoull.c6
4 files changed, 66 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 9578534..679c257 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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