summaryrefslogtreecommitdiffstats
path: root/generic/tclStrToD.c
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2007-04-23 17:34:05 (GMT)
committerKevin B Kenny <kennykb@acm.org>2007-04-23 17:34:05 (GMT)
commit401efde7b4d67a1ca4b84373795ec67ccd785306 (patch)
tree2797649b1f689dcf56aa42cd39b149ed9ceb4476 /generic/tclStrToD.c
parent076e6b32aa2f08565a146e877bd3197bc027b3a4 (diff)
downloadtcl-401efde7b4d67a1ca4b84373795ec67ccd785306.zip
tcl-401efde7b4d67a1ca4b84373795ec67ccd785306.tar.gz
tcl-401efde7b4d67a1ca4b84373795ec67ccd785306.tar.bz2
* generic/tclEnv.c (ReplaceString): Clear memory correctly when
growing the cache to avoid reads of uninitialised data. * generic/tclStrToD.c (AccumulateDecimalDigit): Fixed a mistake where we'd run beyond the end of the 'pow10_wide' array if a number begins with a string of more than 'maxpow10_wide' zeroes. Both these issues reported under [Bug 1705778] - detected with the existing test suite, no new regression tests required.
Diffstat (limited to 'generic/tclStrToD.c')
-rwxr-xr-xgeneric/tclStrToD.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c
index afcf7eb..dc19855 100755
--- a/generic/tclStrToD.c
+++ b/generic/tclStrToD.c
@@ -14,7 +14,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclStrToD.c,v 1.29 2007/04/16 13:36:35 dkf Exp $
+ * RCS: @(#) $Id: tclStrToD.c,v 1.30 2007/04/23 17:34:07 kennykb Exp $
*
*----------------------------------------------------------------------
*/
@@ -1182,32 +1182,42 @@ AccumulateDecimalDigit(
* to this digit. */
{
int i, n;
+ Tcl_WideUInt w;
/*
- * Check if the number still fits in a wide.
+ * Try wide multiplication first
*/
- if (!bignumFlag && *wideRepPtr!=0 && ((numZeros >= maxpow10_wide) ||
- *wideRepPtr > ((~(Tcl_WideUInt)0)-digit)/pow10_wide[numZeros+1])) {
- /*
- * Oops, it's overflowed, have to allocate a bignum.
- */
-
- TclBNInitBignumFromWideUInt (bignumRepPtr, *wideRepPtr);
- bignumFlag = 1;
+ if (!bignumFlag) {
+ w = *wideRepPtr;
+ if (w == 0) {
+ /*
+ * There's no need to multiply if the multiplicand is zero.
+ */
+ *wideRepPtr = digit;
+ return 0;
+ } else if (numZeros >= maxpow10_wide
+ || w > ((~(Tcl_WideUInt)0)-digit)/pow10_wide[numZeros+1]) {
+ /*
+ * Wide multiplication will overflow. Expand the
+ * number to a bignum and fall through into the bignum case.
+ */
+
+ TclBNInitBignumFromWideUInt (bignumRepPtr, w);
+ } else {
+ /*
+ * Wide multiplication.
+ */
+ *wideRepPtr = w * pow10_wide[numZeros+1] + digit;
+ return 0;
+ }
}
/*
- * Multiply the number by 10**numZeros+1 and add in the new digit.
+ * Bignum multiplication.
*/
- if (!bignumFlag) {
- /*
- * Wide multiplication.
- */
-
- *wideRepPtr = *wideRepPtr * pow10_wide[numZeros+1] + digit;
- } else if (numZeros < log10_DIGIT_MAX) {
+ if (numZeros < log10_DIGIT_MAX) {
/*
* Up to about 8 zeros - single digit multiplication.
*/
@@ -1240,7 +1250,7 @@ AccumulateDecimalDigit(
mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr);
}
- return bignumFlag;
+ return 1;
}
/*