diff options
author | dgp <dgp@users.sourceforge.net> | 2009-06-02 17:55:31 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2009-06-02 17:55:31 (GMT) |
commit | 4f4ab1cb58f917d60d2691c635d1f5230da1ea3c (patch) | |
tree | 11b497c2a2ec50badeb5a580e147d1d7bb3124aa /generic/tclExecute.c | |
parent | 6a8a48fbf869b897b9d2ecc86c8e5c760325f7a9 (diff) | |
download | tcl-4f4ab1cb58f917d60d2691c635d1f5230da1ea3c.zip tcl-4f4ab1cb58f917d60d2691c635d1f5230da1ea3c.tar.gz tcl-4f4ab1cb58f917d60d2691c635d1f5230da1ea3c.tar.bz2 |
* generic/tclExecute.c: Corrected implementations and selection
logic of the INST_EXPON instruction to fix [Bug 2798543].
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r-- | generic/tclExecute.c | 105 |
1 files changed, 64 insertions, 41 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index c1b13b5..f6d3930 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclExecute.c,v 1.369.2.8 2009/05/06 20:16:55 dgp Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.369.2.9 2009/06/02 17:55:31 dgp Exp $ */ #include "tclInt.h" @@ -466,7 +466,8 @@ static Tcl_ObjType dictIteratorType = { * signed integer */ -static const long MaxBase32[7] = {46340, 1290, 215, 73, 35, 21, 14}; +static const long MaxBase32[] = {46340, 1290, 215, 73, 35, 21, 14}; +static const size_t MaxBase32Size = sizeof(MaxBase32)/sizeof(long); /* * Table giving 3, 4, ..., 11, raised to the powers 9, 10, ..., as far as they @@ -477,6 +478,7 @@ static const long MaxBase32[7] = {46340, 1290, 215, 73, 35, 21, 14}; static const unsigned short Exp32Index[] = { 0, 11, 18, 23, 26, 29, 31, 32, 33 }; +static const size_t Exp32IndexSize = sizeof(Exp32Index)/sizeof(unsigned short); static const long Exp32Value[] = { 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467, 262144, 1048576, 4194304, @@ -485,6 +487,7 @@ static const long Exp32Value[] = { 40353607, 282475249, 1977326743, 134217728, 1073741824, 387420489, 1000000000 }; +static const size_t Exp32ValueSize = sizeof(Exp32Value)/sizeof(long); #endif /* LONG_MAX == 0x7fffffff -- 32 bit machine */ @@ -495,7 +498,8 @@ static const long Exp32Value[] = { * Tcl_WideInt. */ -static Tcl_WideInt MaxBaseWide[15]; +static Tcl_WideInt MaxBase64[15]; +static const size_t MaxBase64Size = 15; /* *Table giving 3, 4, ..., 13 raised to powers greater than 16 when the @@ -505,6 +509,7 @@ static Tcl_WideInt MaxBaseWide[15]; static const unsigned short Exp64Index[] = { 0, 23, 38, 49, 57, 63, 67, 70, 72, 74, 75, 76 }; +static const size_t Exp64IndexSize = sizeof(Exp64Index)/sizeof(unsigned short); static const Tcl_WideInt Exp64Value[] = { (Tcl_WideInt)243*243*243*3*3, (Tcl_WideInt)243*243*243*3*3*3, @@ -583,6 +588,7 @@ static const Tcl_WideInt Exp64Value[] = { (Tcl_WideInt)248832*248832*248832*12*12, (Tcl_WideInt)371293*371293*371293*13*13 }; +static const size_t Exp64ValueSize = sizeof(Exp64Value)/sizeof(Tcl_WideInt); #endif @@ -680,7 +686,7 @@ InitByteCodeExecution( * without overflowing a Tcl_WideInt */ - for (i = 2; i <= 16; ++i) { + for (i = 2; i - 2 < MaxBase64Size; ++i) { /* * Compute an initial guess in floating point. */ @@ -699,10 +705,14 @@ InitByteCodeExecution( if (x == 1) { break; } +/* +fprintf(stdout, "Adjust %d: %lld to %lld\n", i, w, w-1); +fflush(stdout); +*/ --w; } - MaxBaseWide[i-2] = w; + MaxBase64[i - 2] = w; } #endif } @@ -5598,8 +5608,10 @@ TclExecuteByteCode( /* TODO: Attempts to re-use unshared operands on stack. */ if (*pc == INST_EXPON) { long l1 = 0, l2 = 0; - Tcl_WideInt w1; int oddExponent = 0, negativeExponent = 0; +#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) + Tcl_WideInt w1; +#endif if (type2 == TCL_NUMBER_LONG) { l2 = *((const long *) ptr2); @@ -5645,9 +5657,11 @@ TclExecuteByteCode( } } + if (type1 == TCL_NUMBER_LONG) { + l1 = *((const long *)ptr1); + } if (negativeExponent) { if (type1 == TCL_NUMBER_LONG) { - l1 = *((const long *)ptr1); switch (l1) { case 0: /* @@ -5684,7 +5698,6 @@ TclExecuteByteCode( } if (type1 == TCL_NUMBER_LONG) { - l1 = *((const long *)ptr1); switch (l1) { case 0: /* @@ -5709,14 +5722,23 @@ TclExecuteByteCode( NEXT_INST_F(1, 2, 1); } } - if (type2 == TCL_NUMBER_BIG) { + /* + * We refuse to accept exponent arguments that exceed + * one mp_digit which means the max exponent value is + * 2**28-1 = 0x0fffffff = 268435455, which fits into + * a signed 32 bit int which is within the range of the + * long int type. This means any numeric Tcl_Obj value + * not using TCL_NUMBER_LONG type must hold a value larger + * than we accept. + */ + if (type2 != TCL_NUMBER_LONG) { Tcl_SetObjResult(interp, Tcl_NewStringObj("exponent too large", -1)); result = TCL_ERROR; goto checkForCatch; } - if (type1 == TCL_NUMBER_LONG && type2 == TCL_NUMBER_LONG) { + if (type1 == TCL_NUMBER_LONG) { if (l1 == 2) { /* * Reduce small powers of 2 to shifts. @@ -5737,6 +5759,7 @@ TclExecuteByteCode( NEXT_INST_F(1, 2, 1); } #endif + goto overflow; } if (l1 == -2) { int signum = oddExponent ? -1 : 1; @@ -5760,10 +5783,12 @@ TclExecuteByteCode( NEXT_INST_F(1, 2, 1); } #endif + goto overflow; } #if (LONG_MAX == 0x7fffffff) - if (l2 <= 8 && - l1 <= MaxBase32[l2-2] && l1 >= -MaxBase32[l2-2]) { + if (l2 - 2 < MaxBase32Size + && l1 <= MaxBase32[l2 - 2] + && l1 >= -MaxBase32[l2 - 2]) { /* * Small powers of 32-bit integers. */ @@ -5806,12 +5831,12 @@ TclExecuteByteCode( TRACE(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); } - if (l1 >= 3 && - ((unsigned long) l1 < (sizeof(Exp32Index) - / sizeof(unsigned short)) - 1)) { - unsigned short base = Exp32Index[l1-3] - + (unsigned short) l2 - 9; - if (base < Exp32Index[l1-2]) { + if (l1 - 3 >= 0 && l1 - 2 < Exp32IndexSize + && l2 - 2 < Exp32ValueSize + MaxBase32Size) { + + unsigned short base = Exp32Index[l1 - 3] + + (unsigned short) (l2 - 2 - MaxBase32Size); + if (base < Exp32Index[l1 - 2]) { /* * 32-bit number raised to intermediate power, done by * table lookup. @@ -5828,12 +5853,11 @@ TclExecuteByteCode( NEXT_INST_F(1, 1, 0); } } - if (-l1 >= 3 - && (unsigned long)(-l1) < (sizeof(Exp32Index) - / sizeof(unsigned short)) - 1) { - unsigned short base - = Exp32Index[-l1-3] + (unsigned short) l2 - 9; - if (base < Exp32Index[-l1-2]) { + if (-l1 - 3 >= 0 && -l1 - 2 < Exp32IndexSize + && l2 - 2 < Exp32ValueSize + MaxBase32Size) { + unsigned short base = Exp32Index[-l1 - 3] + + (unsigned short) (l2 - 2 - MaxBase32Size); + if (base < Exp32Index[-l1 - 2]) { long lResult = (oddExponent) ? -Exp32Value[base] : Exp32Value[base]; @@ -5855,6 +5879,7 @@ TclExecuteByteCode( } #endif } +#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) if (type1 == TCL_NUMBER_LONG) { w1 = l1; #ifndef NO_WIDE_TYPE @@ -5862,11 +5887,11 @@ TclExecuteByteCode( w1 = *((const Tcl_WideInt*) ptr1); #endif } else { - w1 = 0; + goto overflow; } -#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) - if (w1 != 0 && type2 == TCL_NUMBER_LONG && l2 <= 16 - && w1 <= MaxBaseWide[l2-2] && w1 >= -MaxBaseWide[l2-2]) { + if (l2 - 2 <= MaxBase64Size + && w1 <= MaxBase64[l2 - 2] + && w1 >= -MaxBase64[l2 - 2]) { /* * Small powers of integers whose result is wide. */ @@ -5956,14 +5981,12 @@ TclExecuteByteCode( * Handle cases of powers > 16 that still fit in a 64-bit word by * doing table lookup. */ + if (w1 - 3 >= 0 && w1 - 2 < Exp64IndexSize + && l2 - 2 < Exp64ValueSize + MaxBase64Size) { + unsigned short base = Exp64Index[w1 - 3] + + (unsigned short) (l2 - 2 - MaxBase64Size); - if (w1 >= 3 && - (Tcl_WideUInt) w1 < (sizeof(Exp64Index) - / sizeof(unsigned short)) - 1) { - unsigned short base = - Exp64Index[w1-3] + (unsigned short) l2 - 17; - - if (base < Exp64Index[w1-2]) { + if (base < Exp64Index[w1 - 2]) { /* * 64-bit number raised to intermediate power, done by * table lookup. @@ -5980,13 +6003,13 @@ TclExecuteByteCode( NEXT_INST_F(1, 1, 0); } } - if (-w1 >= 3 && - (Tcl_WideUInt) (-w1) < (sizeof(Exp64Index) - / sizeof(unsigned short)) - 1) { - unsigned short base = - Exp64Index[-w1-3] + (unsigned short) l2 - 17; - if (base < Exp64Index[-w1-2]) { + if (-w1 - 3 >= 0 && -w1 - 2 < Exp64IndexSize + && l2 - 2 < Exp64ValueSize + MaxBase64Size) { + unsigned short base = Exp64Index[-w1 - 3] + + (unsigned short) (l2 - 2 - MaxBase64Size); + + if (base < Exp64Index[-w1 - 2]) { Tcl_WideInt wResult = (oddExponent) ? -Exp64Value[base] : Exp64Value[base]; /* |