diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclBasic.c | 37 | ||||
-rw-r--r-- | generic/tclExecute.c | 180 | ||||
-rw-r--r-- | generic/tclObj.c | 25 | ||||
-rw-r--r-- | generic/tclStrToD.c | 544 | ||||
-rw-r--r-- | generic/tclTestObj.c | 14 |
5 files changed, 530 insertions, 270 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c index b216e05..9f650d6 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -7675,10 +7675,16 @@ ExprIsqrtFunc( Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) sqrt(d))); } else { mp_int root; + mp_err err; - mp_init(&root); - mp_sqrt(&big, &root); + err = mp_init(&root); + if (err == MP_OKAY) { + err = mp_sqrt(&big, &root); + } mp_clear(&big); + if (err != MP_OKAY) { + return TCL_ERROR; + } Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root)); } return TCL_OK; @@ -7724,10 +7730,17 @@ ExprSqrtFunc( if ((d >= 0.0) && TclIsInfinite(d) && (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) { mp_int root; + mp_err err; - mp_init(&root); - mp_sqrt(&big, &root); + err = mp_init(&root); + if (err == MP_OKAY) { + err = mp_sqrt(&big, &root); + } mp_clear(&big); + if (err != MP_OKAY) { + mp_clear(&root); + return TCL_ERROR; + } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclBignumToDouble(&root))); mp_clear(&root); } else { @@ -7893,7 +7906,9 @@ ExprAbsFunc( } goto unChanged; } else if (l == WIDE_MIN) { - mp_init_i64(&big, l); + if (mp_init_i64(&big, l) != MP_OKAY) { + return TCL_ERROR; + } goto tooLarge; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l)); @@ -7924,7 +7939,9 @@ ExprAbsFunc( if (mp_isneg((const mp_int *) ptr)) { Tcl_GetBignumFromObj(NULL, objv[1], &big); tooLarge: - (void)mp_neg(&big, &big); + if (mp_neg(&big, &big) != MP_OKAY) { + return TCL_ERROR; + } Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big)); } else { unChanged: @@ -8260,15 +8277,19 @@ ExprRoundFunc( } if ((intPart >= (double)max) || (intPart <= (double)min)) { mp_int big; + mp_err err = MP_OKAY; if (Tcl_InitBignumFromDouble(interp, intPart, &big) != TCL_OK) { /* Infinity */ return TCL_ERROR; } if (fractPart <= -0.5) { - mp_sub_d(&big, 1, &big); + err = mp_sub_d(&big, 1, &big); } else if (fractPart >= 0.5) { - mp_add_d(&big, 1, &big); + err = mp_add_d(&big, 1, &big); + } + if (err != MP_OKAY) { + return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big)); return TCL_OK; diff --git a/generic/tclExecute.c b/generic/tclExecute.c index aa049dc..0ecdbfa 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -662,6 +662,7 @@ static const size_t Exp64ValueSize = sizeof(Exp64Value) / sizeof(Tcl_WideInt); #define DIVIDED_BY_ZERO ((Tcl_Obj *) -1) #define EXPONENT_OF_ZERO ((Tcl_Obj *) -2) #define GENERAL_ARITHMETIC_ERROR ((Tcl_Obj *) -3) +#define OUT_OF_MEMORY ((Tcl_Obj *) -4) /* * Declarations for local procedures to this file: @@ -1806,6 +1807,7 @@ TclIncrObj( ClientData ptr1, ptr2; int type1, type2; mp_int value, incr; + mp_err err; if (Tcl_IsShared(valuePtr)) { Tcl_Panic("%s called with shared object", "TclIncrObj"); @@ -1864,8 +1866,11 @@ TclIncrObj( Tcl_TakeBignumFromObj(interp, valuePtr, &value); Tcl_GetBignumFromObj(interp, incrPtr, &incr); - mp_add(&value, &incr, &value); + err = mp_add(&value, &incr, &value); mp_clear(&incr); + if (err != MP_OKAY) { + return TCL_ERROR; + } Tcl_SetBignumObj(valuePtr, &value); return TCL_OK; } @@ -6169,6 +6174,9 @@ TEBCresume( } else if (objResultPtr == GENERAL_ARITHMETIC_ERROR) { TRACE_ERROR(interp); goto gotError; + } else if (objResultPtr == OUT_OF_MEMORY) { + TRACE_APPEND(("OUT OF MEMORY\n")); + goto outOfMemory; } else if (objResultPtr == NULL) { TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); @@ -7621,6 +7629,13 @@ TEBCresume( CACHE_STACK_INFO(); goto gotError; + outOfMemory: + Tcl_SetObjResult(interp, Tcl_NewStringObj("out of memory", -1)); + DECACHE_STACK_INFO(); + Tcl_SetErrorCode(interp, "ARITH", "OUTOFMEMORY", "out of memory", NULL); + CACHE_STACK_INFO(); + goto gotError; + /* * Exponentiation of zero by negative number in an expression. Control * only reaches this point by "goto exponOfZero". @@ -8060,6 +8075,7 @@ ExecuteExtendedBinaryMathOp( Tcl_Obj *objResultPtr; int invalid, zero; long shift; + mp_err err; (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2); @@ -8121,9 +8137,14 @@ ExecuteExtendedBinaryMathOp( * Arguments are opposite sign; remainder is sum. */ - mp_init_i64(&big1, w1); - mp_add(&big2, &big1, &big2); - mp_clear(&big1); + err = mp_init_i64(&big1, w1); + if (err == MP_OKAY) { + err = mp_add(&big2, &big1, &big2); + mp_clear(&big1); + } + if (err != MP_OKAY) { + return OUT_OF_MEMORY; + } BIG_RESULT(&big2); } @@ -8136,21 +8157,27 @@ ExecuteExtendedBinaryMathOp( } Tcl_GetBignumFromObj(NULL, valuePtr, &big1); Tcl_GetBignumFromObj(NULL, value2Ptr, &big2); - mp_init(&bigResult); - mp_init(&bigRemainder); - mp_div(&big1, &big2, &bigResult, &bigRemainder); - if (!mp_iszero(&bigRemainder) && (bigRemainder.sign != big2.sign)) { + err = mp_init_multi(&bigResult, &bigRemainder, NULL); + if (err == MP_OKAY) { + err = mp_div(&big1, &big2, &bigResult, &bigRemainder); + } + if ((err == MP_OKAY) && !mp_iszero(&bigRemainder) && (bigRemainder.sign != big2.sign)) { /* * Convert to Tcl's integer division rules. */ - mp_sub_d(&bigResult, 1, &bigResult); - mp_add(&bigRemainder, &big2, &bigRemainder); + if ((mp_sub_d(&bigResult, 1, &bigResult) != MP_OKAY) + || (mp_add(&bigRemainder, &big2, &bigRemainder) != MP_OKAY)) { + return OUT_OF_MEMORY; + } } - mp_copy(&bigRemainder, &bigResult); + err = mp_copy(&bigRemainder, &bigResult); mp_clear(&bigRemainder); mp_clear(&big1); mp_clear(&big2); + if (err != MP_OKAY) { + return OUT_OF_MEMORY; + } BIG_RESULT(&bigResult); case INST_LSHIFT: @@ -8276,11 +8303,16 @@ ExecuteExtendedBinaryMathOp( Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); - mp_init(&bigResult); - if (opcode == INST_LSHIFT) { - mp_mul_2d(&big1, shift, &bigResult); - } else { - mp_signed_rsh(&big1, shift, &bigResult); + err = mp_init(&bigResult); + if (err == MP_OKAY) { + if (opcode == INST_LSHIFT) { + err = mp_mul_2d(&big1, shift, &bigResult); + } else { + err = mp_signed_rsh(&big1, shift, &bigResult); + } + } + if (err != MP_OKAY) { + return OUT_OF_MEMORY; } mp_clear(&big1); BIG_RESULT(&bigResult); @@ -8293,20 +8325,25 @@ ExecuteExtendedBinaryMathOp( Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - mp_init(&bigResult); + err = mp_init(&bigResult); - switch (opcode) { - case INST_BITAND: - mp_and(&big1, &big2, &bigResult); - break; + if (err == MP_OKAY) { + switch (opcode) { + case INST_BITAND: + err = mp_and(&big1, &big2, &bigResult); + break; - case INST_BITOR: - mp_or(&big1, &big2, &bigResult); - break; + case INST_BITOR: + err = mp_or(&big1, &big2, &bigResult); + break; - case INST_BITXOR: - mp_xor(&big1, &big2, &bigResult); - break; + case INST_BITXOR: + err = mp_xor(&big1, &big2, &bigResult); + break; + } + } + if (err != MP_OKAY) { + return OUT_OF_MEMORY; } mp_clear(&big1); @@ -8369,8 +8406,8 @@ ExecuteExtendedBinaryMathOp( } else { Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); negativeExponent = mp_isneg(&big2); - mp_mod_2d(&big2, 1, &big2); - oddExponent = !mp_iszero(&big2); + err = mp_mod_2d(&big2, 1, &big2); + oddExponent = (err == MP_OKAY) && !mp_iszero(&big2); mp_clear(&big2); } @@ -8527,8 +8564,13 @@ ExecuteExtendedBinaryMathOp( return GENERAL_ARITHMETIC_ERROR; } Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); - mp_init(&bigResult); - mp_expt_u32(&big1, (unsigned int)w2, &bigResult); + err = mp_init(&bigResult); + if (err == MP_OKAY) { + err = mp_expt_u32(&big1, (unsigned int)w2, &bigResult); + } + if (err != MP_OKAY) { + return OUT_OF_MEMORY; + } mp_clear(&big1); BIG_RESULT(&bigResult); } @@ -8675,38 +8717,44 @@ ExecuteExtendedBinaryMathOp( overflowBasic: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - mp_init(&bigResult); + err = mp_init(&bigResult); + if (err == MP_OKAY) { switch (opcode) { case INST_ADD: - mp_add(&big1, &big2, &bigResult); - break; + err = mp_add(&big1, &big2, &bigResult); + break; case INST_SUB: - mp_sub(&big1, &big2, &bigResult); - break; + err = mp_sub(&big1, &big2, &bigResult); + break; case INST_MULT: - mp_mul(&big1, &big2, &bigResult); - break; + err = mp_mul(&big1, &big2, &bigResult); + break; case INST_DIV: - if (mp_iszero(&big2)) { - mp_clear(&big1); - mp_clear(&big2); - mp_clear(&bigResult); - return DIVIDED_BY_ZERO; - } - mp_init(&bigRemainder); - mp_div(&big1, &big2, &bigResult, &bigRemainder); - /* TODO: internals intrusion */ - if (!mp_iszero(&bigRemainder) - && (bigRemainder.sign != big2.sign)) { - /* - * Convert to Tcl's integer division rules. - */ + if (mp_iszero(&big2)) { + mp_clear(&big1); + mp_clear(&big2); + mp_clear(&bigResult); + return DIVIDED_BY_ZERO; + } + err = mp_init(&bigRemainder); + if (err == MP_OKAY) { + err = mp_div(&big1, &big2, &bigResult, &bigRemainder); + } + /* TODO: internals intrusion */ + if (!mp_iszero(&bigRemainder) + && (bigRemainder.sign != big2.sign)) { + /* + * Convert to Tcl's integer division rules. + */ - mp_sub_d(&bigResult, 1, &bigResult); - mp_add(&bigRemainder, &big2, &bigRemainder); + err = mp_sub_d(&bigResult, 1, &bigResult); + if (err == MP_OKAY) { + err = mp_add(&bigRemainder, &big2, &bigRemainder); + } + } + mp_clear(&bigRemainder); + break; } - mp_clear(&bigRemainder); - break; } mp_clear(&big1); mp_clear(&big2); @@ -8727,6 +8775,7 @@ ExecuteExtendedUnaryMathOp( Tcl_WideInt w; mp_int big; Tcl_Obj *objResultPtr; + mp_err err = MP_OKAY; (void) GetNumberFromObj(NULL, valuePtr, &ptr, &type); @@ -8738,8 +8787,13 @@ ExecuteExtendedUnaryMathOp( } Tcl_TakeBignumFromObj(NULL, valuePtr, &big); /* ~a = - a - 1 */ - (void)mp_neg(&big, &big); - mp_sub_d(&big, 1, &big); + err = mp_neg(&big, &big); + if (err == MP_OKAY) { + err = mp_sub_d(&big, 1, &big); + } + if (err != MP_OKAY) { + return OUT_OF_MEMORY; + } BIG_RESULT(&big); case INST_UMINUS: switch (type) { @@ -8750,12 +8804,18 @@ ExecuteExtendedUnaryMathOp( if (w != WIDE_MIN) { WIDE_RESULT(-w); } - mp_init_i64(&big, w); + err = mp_init_i64(&big, w); + if (err != MP_OKAY) { + return OUT_OF_MEMORY; + } break; default: Tcl_TakeBignumFromObj(NULL, valuePtr, &big); } - (void)mp_neg(&big, &big); + err = mp_neg(&big, &big); + if (err != MP_OKAY) { + return OUT_OF_MEMORY; + } BIG_RESULT(&big); } diff --git a/generic/tclObj.c b/generic/tclObj.c index eb9334e..ea1360f 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -182,10 +182,7 @@ static Tcl_ThreadDataKey pendingObjDataKey; *temp = bignum; \ (objPtr)->internalRep.twoPtrValue.ptr1 = temp; \ (objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \ - } else { \ - if ((bignum).alloc > 0x7fff) { \ - mp_shrink(&(bignum)); \ - } \ + } else if (((bignum).alloc <= 0x7fff) || (mp_shrink(&(bignum))) == MP_OKAY) { \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (bignum).dp; \ (objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR( ((bignum).sign << 30) \ | ((bignum).alloc << 15) | ((bignum).used)); \ @@ -3338,14 +3335,20 @@ TclGetWideBitsFromObj( } if (objPtr->typePtr == &tclBignumType) { mp_int big; + mp_err err; Tcl_WideUInt value = 0, scratch; size_t numBytes; unsigned char *bytes = (unsigned char *) &scratch; Tcl_GetBignumFromObj(NULL, objPtr, &big); - mp_mod_2d(&big, (int) (CHAR_BIT * sizeof(Tcl_WideInt)), &big); - mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes); + err = mp_mod_2d(&big, (int) (CHAR_BIT * sizeof(Tcl_WideInt)), &big); + if (err == MP_OKAY) { + err = mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes); + } + if (err != MP_OKAY) { + return TCL_ERROR; + } while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } @@ -3585,7 +3588,9 @@ GetBignumFromObj( mp_int temp; TclUnpackBignum(objPtr, temp); - mp_init_copy(bignumValue, &temp); + if (mp_init_copy(bignumValue, &temp) != MP_OKAY) { + return TCL_ERROR; + } } else { TclUnpackBignum(objPtr, *bignumValue); /* Optimized TclFreeIntRep */ @@ -3604,8 +3609,10 @@ GetBignumFromObj( return TCL_OK; } if (objPtr->typePtr == &tclIntType) { - mp_init_i64(bignumValue, - objPtr->internalRep.wideValue); + if (mp_init_i64(bignumValue, + objPtr->internalRep.wideValue) != MP_OKAY) { + return TCL_ERROR; + } return TCL_OK; } if (objPtr->typePtr == &tclDoubleType) { diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 8939fa0..485aba7 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -303,7 +303,7 @@ static double MakeNaN(int signum, Tcl_WideUInt tag); #endif static double RefineApproximation(double approx, mp_int *exactSignificand, int exponent); -static void MulPow5(mp_int *, unsigned, mp_int *); +static mp_err MulPow5(mp_int *, unsigned, mp_int *) MP_WUR; static int NormalizeRightward(Tcl_WideUInt *); static int RequiredPrecision(Tcl_WideUInt); static void DoubleToExpAndSig(double, Tcl_WideUInt *, int *, @@ -534,6 +534,7 @@ TclParseNumber( * to avoid a compiler warning. */ int shift = 0; /* Amount to shift when accumulating binary */ int explicitOctal = 0; + mp_err err = MP_OKAY; #define ALL_BITS ((Tcl_WideUInt)-1) #define MOST_BITS (ALL_BITS >> 1) @@ -716,7 +717,7 @@ TclParseNumber( || (octalSignificandWide > ((Tcl_WideUInt)-1 >> shift)))) { octalSignificandOverflow = 1; - mp_init_u64(&octalSignificandBig, + err = mp_init_u64(&octalSignificandBig, octalSignificandWide); } } @@ -724,10 +725,17 @@ TclParseNumber( octalSignificandWide = (octalSignificandWide << shift) + (c - '0'); } else { - mp_mul_2d(&octalSignificandBig, shift, - &octalSignificandBig); - mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'), - &octalSignificandBig); + if (err == MP_OKAY) { + err = mp_mul_2d(&octalSignificandBig, shift, + &octalSignificandBig); + } + if (err == MP_OKAY) { + err = mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'), + &octalSignificandBig); + } + } + if (err != MP_OKAY) { + return TCL_ERROR; } } if (numSigDigs != 0) { @@ -833,17 +841,22 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - mp_init_u64(&significandBig, + err = mp_init_u64(&significandBig, significandWide); } } if (!significandOverflow) { significandWide = (significandWide << shift) + d; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); - mp_add_d(&significandBig, (mp_digit) d, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); + if (err == MP_OKAY) { + err = mp_add_d(&significandBig, (mp_digit) d, &significandBig); + } } } + if (err != MP_OKAY) { + return TCL_ERROR; + } numTrailZeros = 0; state = HEXADECIMAL; break; @@ -875,17 +888,22 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > ((Tcl_WideUInt)-1 >> shift))) { significandOverflow = 1; - mp_init_u64(&significandBig, + err = mp_init_u64(&significandBig, significandWide); } } if (!significandOverflow) { significandWide = (significandWide << shift) + 1; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); - mp_add_d(&significandBig, (mp_digit) 1, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); + if (err == MP_OKAY) { + err = mp_add_d(&significandBig, (mp_digit) 1, &significandBig); + } } } + if (err != MP_OKAY) { + return TCL_ERROR; + } numTrailZeros = 0; state = BINARY; break; @@ -1220,15 +1238,18 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - mp_init_u64(&significandBig, significandWide); + err = mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { significandWide <<= shift; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); } } + if (err != MP_OKAY) { + return TCL_ERROR; + } goto returnInteger; case HEXADECIMAL: @@ -1241,15 +1262,18 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; - mp_init_u64(&significandBig, significandWide); + err = mp_init_u64(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { significandWide <<= shift; - } else { - mp_mul_2d(&significandBig, shift, &significandBig); + } else if (err == MP_OKAY) { + err = mp_mul_2d(&significandBig, shift, &significandBig); } } + if (err != MP_OKAY) { + return TCL_ERROR; + } goto returnInteger; case OCTAL: @@ -1262,20 +1286,20 @@ TclParseNumber( ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || octalSignificandWide > (MOST_BITS + signum) >> shift)) { octalSignificandOverflow = 1; - mp_init_u64(&octalSignificandBig, + err = mp_init_u64(&octalSignificandBig, octalSignificandWide); } if (shift) { if (!octalSignificandOverflow) { octalSignificandWide <<= shift; - } else { - mp_mul_2d(&octalSignificandBig, shift, + } else if (err == MP_OKAY) { + err = mp_mul_2d(&octalSignificandBig, shift, &octalSignificandBig); } } if (!octalSignificandOverflow) { - if (octalSignificandWide > (MOST_BITS + signum)) { - mp_init_u64(&octalSignificandBig, + if ((err == MP_OKAY) && (octalSignificandWide > (MOST_BITS + signum))) { + err = mp_init_u64(&octalSignificandBig, octalSignificandWide); octalSignificandOverflow = 1; } else { @@ -1289,26 +1313,29 @@ TclParseNumber( } } } - if (octalSignificandOverflow) { + if ((err == MP_OKAY) && octalSignificandOverflow) { if (signum) { - (void)mp_neg(&octalSignificandBig, &octalSignificandBig); + err = mp_neg(&octalSignificandBig, &octalSignificandBig); } TclSetBignumIntRep(objPtr, &octalSignificandBig); } + if (err != MP_OKAY) { + return TCL_ERROR; + } break; case ZERO: case DECIMAL: significandOverflow = AccumulateDecimalDigit(0, numTrailZeros-1, &significandWide, &significandBig, significandOverflow); - if (!significandOverflow && (significandWide > MOST_BITS+signum)) { + if ((err == MP_OKAY) && !significandOverflow && (significandWide > MOST_BITS+signum)) { significandOverflow = 1; - mp_init_u64(&significandBig, significandWide); + err = mp_init_u64(&significandBig, significandWide); } returnInteger: if (!significandOverflow) { - if (significandWide > MOST_BITS+signum) { - mp_init_u64(&significandBig, + if ((err == MP_OKAY) && (significandWide > MOST_BITS+signum)) { + err = mp_init_u64(&significandBig, significandWide); significandOverflow = 1; } else { @@ -1322,12 +1349,15 @@ TclParseNumber( } } } - if (significandOverflow) { + if ((err == MP_OKAY) && significandOverflow) { if (signum) { - (void)mp_neg(&significandBig, &significandBig); + err = mp_neg(&significandBig, &significandBig); } TclSetBignumIntRep(objPtr, &significandBig); } + if (err != MP_OKAY) { + return TCL_ERROR; + } break; case FRACTION: @@ -1492,7 +1522,9 @@ AccumulateDecimalDigit( * bignum and fall through into the bignum case. */ - mp_init_u64(bignumRepPtr, w); + if (mp_init_u64(bignumRepPtr, w) != MP_OKAY) { + return 0; + } } else { /* * Wide multiplication. @@ -1512,10 +1544,12 @@ AccumulateDecimalDigit( * Up to about 8 zeros - single digit multiplication. */ - mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[numZeros+1], - bignumRepPtr); - mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr); + if ((mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[numZeros+1], + bignumRepPtr) != MP_OKAY) + || (mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr) != MP_OKAY)) + return 0; } else { + mp_err err; /* * More than single digit multiplication. Multiply by the appropriate * small powers of 5, and then shift. Large strings of zeroes are @@ -1526,18 +1560,21 @@ AccumulateDecimalDigit( */ n = numZeros + 1; - mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr); - for (i=3; i<=7; ++i) { + err = mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr); + for (i = 3; (err == MP_OKAY) && (i <= 7); ++i) { if (n & (1 << i)) { - mp_mul(bignumRepPtr, pow5+i, bignumRepPtr); + err = mp_mul(bignumRepPtr, pow5+i, bignumRepPtr); } } - while (n >= 256) { - mp_mul(bignumRepPtr, pow5+8, bignumRepPtr); + while ((err == MP_OKAY) && (n >= 256)) { + err = mp_mul(bignumRepPtr, pow5+8, bignumRepPtr); n -= 256; } - mp_mul_2d(bignumRepPtr, (int)(numZeros+1)&~0x7, bignumRepPtr); - mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr); + if ((err != MP_OKAY) + || (mp_mul_2d(bignumRepPtr, (int)(numZeros+1)&~0x7, bignumRepPtr) != MP_OKAY) + || (mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr) != MP_OKAY)) { + return 0; + } } return 1; @@ -1638,7 +1675,9 @@ MakeLowPrecisionDouble( * call MakeHighPrecisionDouble to do it the hard way. */ - mp_init_u64(&significandBig, significand); + if (mp_init_u64(&significandBig, significand) != MP_OKAY) { + return 0.0; + } retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs, exponent); mp_clear(&significandBig); @@ -1687,7 +1726,7 @@ MakeHighPrecisionDouble( long exponent) /* Power of 10 by which to multiply */ { double retval; - int machexp; /* Machine exponent of a power of 10. */ + int machexp = 0; /* Machine exponent of a power of 10. */ /* * With gcc on x86, the floating point rounding mode is double-extended. @@ -1852,6 +1891,7 @@ RefineApproximation( Tcl_WideInt rteSigWide; /* Wide integer version of the significand * for testing evenness */ int i; + mp_err err = MP_OKAY; /* * The first approximation is always low. If we find that it's HUGE_VAL, @@ -1900,7 +1940,9 @@ RefineApproximation( msb = binExponent + M2; /* 1008 */ nDigits = msb / MP_DIGIT_BIT + 1; - mp_init_size(&twoMv, nDigits); + if (mp_init_size(&twoMv, nDigits) != MP_OKAY) { + return approxResult; + } i = (msb % MP_DIGIT_BIT + 1); twoMv.used = nDigits; significand *= SafeLdExp(1.0, i); @@ -1910,8 +1952,9 @@ RefineApproximation( significand = SafeLdExp(significand, MP_DIGIT_BIT); } for (i = 0; i <= 8; ++i) { - if (M5 & (1 << i)) { - mp_mul(&twoMv, pow5+i, &twoMv); + if (M5 & (1 << i) && (mp_mul(&twoMv, pow5+i, &twoMv) != MP_OKAY)) { + mp_clear(&twoMv); + return approxResult; } } @@ -1921,20 +1964,27 @@ RefineApproximation( * by 2**(M5+exponent+1), which is, of couse, a left shift. */ - mp_init_copy(&twoMd, exactSignificand); - for (i=0; i<=8; ++i) { + if (mp_init_copy(&twoMd, exactSignificand) != MP_OKAY) { + mp_clear(&twoMv); + return approxResult; + } + for (i = 0; (i <= 8); ++i) { if ((M5 + exponent) & (1 << i)) { - mp_mul(&twoMd, pow5+i, &twoMd); + err = mp_mul(&twoMd, pow5+i, &twoMd); } } - mp_mul_2d(&twoMd, M2+exponent+1, &twoMd); + if (err == MP_OKAY) { + err = mp_mul_2d(&twoMd, M2+exponent+1, &twoMd); + } /* * Now let twoMd = twoMd - twoMv, the difference between the exact and * approximate values. */ - mp_sub(&twoMd, &twoMv, &twoMd); + if (err == MP_OKAY) { + err = mp_sub(&twoMd, &twoMv, &twoMd); + } /* * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction @@ -1945,16 +1995,25 @@ RefineApproximation( scale = binExponent - mantBits - 1; mp_set_u64(&twoMv, 1); - for (i=0; i<=8; ++i) { + for (i = 0; (i <= 8) && (err == MP_OKAY); ++i) { if (M5 & (1 << i)) { - mp_mul(&twoMv, pow5+i, &twoMv); + err = mp_mul(&twoMv, pow5+i, &twoMv); } } multiplier = M2 + scale + 1; - if (multiplier > 0) { - mp_mul_2d(&twoMv, multiplier, &twoMv); + if (err != MP_OKAY) { + mp_clear(&twoMd); + mp_clear(&twoMv); + return approxResult; + } else if (multiplier > 0) { + err = mp_mul_2d(&twoMv, multiplier, &twoMv); } else if (multiplier < 0) { - mp_div_2d(&twoMv, -multiplier, &twoMv, NULL); + err = mp_div_2d(&twoMv, -multiplier, &twoMv, NULL); + } + if (err != MP_OKAY) { + mp_clear(&twoMd); + mp_clear(&twoMv); + return approxResult; } /* @@ -2003,8 +2062,15 @@ RefineApproximation( */ shift = mp_count_bits(&twoMv) - FP_PRECISION - 1; if (shift > 0) { - mp_div_2d(&twoMv, shift, &twoMv, NULL); - mp_div_2d(&twoMd, shift, &twoMd, NULL); + err = mp_div_2d(&twoMv, shift, &twoMv, NULL); + if (err == MP_OKAY) { + err = mp_div_2d(&twoMd, shift, &twoMd, NULL); + } + } + if (err != MP_OKAY) { + mp_clear(&twoMd); + mp_clear(&twoMv); + return approxResult; } /* @@ -2043,7 +2109,7 @@ RefineApproximation( *---------------------------------------------------------------------- */ -static inline void +static inline mp_err MulPow5( mp_int *base, /* Number to multiply. */ unsigned n, /* Power of 5 to multiply by. */ @@ -2052,23 +2118,25 @@ MulPow5( mp_int *p = base; int n13 = n / 13; int r = n % 13; + mp_err err = MP_OKAY; if (r != 0) { - mp_mul_d(p, dpow5[r], result); + err = mp_mul_d(p, dpow5[r], result); p = result; } r = 0; - while (n13 != 0) { + while ((err == MP_OKAY) && (n13 != 0)) { if (n13 & 1) { - mp_mul(p, pow5_13+r, result); + err = mp_mul(p, pow5_13+r, result); p = result; } n13 >>= 1; ++r; } - if (p != result) { - mp_copy(p, result); + if ((err == MP_OKAY) && (p != result)) { + err = mp_copy(p, result); } + return err; } /* @@ -3268,8 +3336,7 @@ ShouldBankerRoundUpToNextPowD( * 2**(MP_DIGIT_BIT*sd) */ - mp_add(b, m, temp); - if (temp->used <= sd) { /* Too few digits to be > s */ + if ((mp_add(b, m, temp) != MP_OKAY) || (temp->used <= sd)) { /* Too few digits to be > s */ return 0; } if (temp->used > sd+1 || temp->dp[sd] > 1) { @@ -3337,23 +3404,31 @@ ShorteningBignumConversionPowD( int i; /* Index in the output buffer. */ mp_int temp; int r1; + mp_err err = MP_OKAY; /* * b = bw * 2**b2 * 5**b5 * mminus = 5**m5 */ - mp_init_u64(&b, bw); - mp_init_set(&mminus, 1); - MulPow5(&b, b5, &b); - mp_mul_2d(&b, b2, &b); + if ((retval == NULL) || (mp_init_u64(&b, bw) != MP_OKAY)) { + return NULL; + } + if (mp_init_set(&mminus, 1) != MP_OKAY) { + mp_clear(&b); + return NULL; + } + err = MulPow5(&b, b5, &b); + if (err == MP_OKAY) { + err = mp_mul_2d(&b, b2, &b); + } /* * Adjust if the logarithm was guessed wrong. */ - if (b.used <= sd) { - mp_mul_d(&b, 10, &b); + if ((err == MP_OKAY) && (b.used <= sd)) { + err = mp_mul_d(&b, 10, &b); ++m2plus; ++m2minus; ++m5; ilim = ilim1; --k; @@ -3364,13 +3439,21 @@ ShorteningBignumConversionPowD( * mplus = 5**m5 * 2**m2plus */ - mp_mul_2d(&mminus, m2minus, &mminus); - MulPow5(&mminus, m5, &mminus); - if (m2plus > m2minus) { - mp_init_copy(&mplus, &mminus); - mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + if (err == MP_OKAY) { + err = mp_mul_2d(&mminus, m2minus, &mminus); + } + if (err == MP_OKAY) { + err = MulPow5(&mminus, m5, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_init_copy(&mplus, &mminus); + if (err == MP_OKAY) { + err = mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + } + } + if (err == MP_OKAY) { + err = mp_init(&temp); } - mp_init(&temp); /* * Loop through the digits. Do division and mod by s == 2**(sd*MP_DIGIT_BIT) @@ -3452,10 +3535,14 @@ ShorteningBignumConversionPowD( * Advance to the next digit. */ - mp_mul_d(&b, 10, &b); - mp_mul_d(&mminus, 10, &mminus); - if (m2plus > m2minus) { - mp_mul_2d(&mminus, m2plus-m2minus, &mplus); + if (err == MP_OKAY) { + err = mp_mul_d(&b, 10, &b); + } + if (err == MP_OKAY) { + err = mp_mul_d(&mminus, 10, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_mul_2d(&mminus, m2plus-m2minus, &mplus); } ++i; } @@ -3474,7 +3561,7 @@ ShorteningBignumConversionPowD( if (endPtr) { *endPtr = s; } - return retval; + return (err == MP_OKAY) ? retval : NULL; } /* @@ -3522,21 +3609,26 @@ StrictBignumConversionPowD( mp_digit digit; /* Current output digit. */ char *s = retval; /* Cursor in the output buffer. */ int i; /* Index in the output buffer. */ + mp_err err; /* * b = bw * 2**b2 * 5**b5 */ - mp_init_u64(&b, bw); - MulPow5(&b, b5, &b); - mp_mul_2d(&b, b2, &b); + if (mp_init_u64(&b, bw) != MP_OKAY) { + return NULL; + } + err = MulPow5(&b, b5, &b); + if (err == MP_OKAY) { + err = mp_mul_2d(&b, b2, &b); + } /* * Adjust if the logarithm was guessed wrong. */ - if (b.used <= sd) { - mp_mul_d(&b, 10, &b); + if ((err == MP_OKAY) && (b.used <= sd)) { + err = mp_mul_d(&b, 10, &b); ilim = ilim1; --k; } @@ -3547,7 +3639,7 @@ StrictBignumConversionPowD( */ i = 1; - for (;;) { + while (err == MP_OKAY) { if (b.used <= sd) { digit = 0; } else { @@ -3579,7 +3671,7 @@ StrictBignumConversionPowD( * Advance to the next digit. */ - mp_mul_d(&b, 10, &b); + err = mp_mul_d(&b, 10, &b); ++i; } @@ -3661,8 +3753,9 @@ ShouldBankerRoundUpToNext( * Compare b and S-m: this is the same as comparing B+m and S. */ - mp_init(&temp); - mp_add(b, m, &temp); + if ((mp_init(&temp) != MP_OKAY) || (mp_add(b, m, &temp) != MP_OKAY)) { + return 0; + } r = mp_cmp_mag(&temp, S); mp_clear(&temp); switch(r) { @@ -3721,23 +3814,33 @@ ShorteningBignumConversion( int minit = 1; /* Fudge factor for when we misguess k. */ int i; int r1; + mp_err err; /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ - mp_init_u64(&b, bw); - mp_mul_2d(&b, b2, &b); - mp_init_set(&S, 1); - MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); + if ((retval == NULL) || (mp_init_u64(&b, bw) != MP_OKAY)) { + return NULL; + } + err = mp_mul_2d(&b, b2, &b); + if (err == MP_OKAY) { + err = mp_init_set(&S, 1); + } + if (err == MP_OKAY) { + err = MulPow5(&S, s5, &S); + } + if (err == MP_OKAY) { + err = mp_mul_2d(&S, s2, &S); + } /* * Handle the case where we guess the position of the decimal point wrong. */ - if (mp_cmp_mag(&b, &S) == MP_LT) { - mp_mul_d(&b, 10, &b); + if ((err == MP_OKAY) && (mp_cmp_mag(&b, &S) == MP_LT)) { + err = mp_mul_d(&b, 10, &b); minit = 10; ilim =ilim1; --k; @@ -3747,21 +3850,29 @@ ShorteningBignumConversion( * mminus = 2**m2minus * 5**m5 */ - mp_init_set(&mminus, minit); - mp_mul_2d(&mminus, m2minus, &mminus); - if (m2plus > m2minus) { - mp_init_copy(&mplus, &mminus); - mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + if (err == MP_OKAY) { + err = mp_init_set(&mminus, minit); + } + if (err == MP_OKAY) { + err = mp_mul_2d(&mminus, m2minus, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_init_copy(&mplus, &mminus); + if (err == MP_OKAY) { + err = mp_mul_2d(&mplus, m2plus-m2minus, &mplus); + } } /* * Loop through the digits. */ - mp_init(&dig); + if (err == MP_OKAY) { + err = mp_init(&dig); + } i = 1; - for (;;) { - mp_div(&b, &S, &dig, &b); + while (err == MP_OKAY) { + err = mp_div(&b, &S, &dig, &b); if (dig.used > 1 || dig.dp[0] >= 10) { Tcl_Panic("wrong digit!"); } @@ -3774,7 +3885,7 @@ ShorteningBignumConversion( r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus); if (r1 == MP_LT || (r1 == MP_EQ && (dPtr->w.word1 & 1) == 0)) { - mp_mul_2d(&b, 1, &b); + err = mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { ++digit; if (digit == 10) { @@ -3809,8 +3920,8 @@ ShorteningBignumConversion( */ *s++ = '0' + digit; - if (i == ilim) { - mp_mul_2d(&b, 1, &b); + if ((err == MP_OKAY) && (i == ilim)) { + err = mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } @@ -3821,17 +3932,21 @@ ShorteningBignumConversion( * Advance to the next digit. */ - if (s5 > 0) { + if ((err == MP_OKAY) && (s5 > 0)) { /* * Can possibly shorten the denominator. */ - mp_mul_2d(&b, 1, &b); - mp_mul_2d(&mminus, 1, &mminus); - if (m2plus > m2minus) { - mp_mul_2d(&mplus, 1, &mplus); + err = mp_mul_2d(&b, 1, &b); + if (err == MP_OKAY) { + err = mp_mul_2d(&mminus, 1, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_mul_2d(&mplus, 1, &mplus); + } + if (err == MP_OKAY) { + err = mp_div_d(&S, 5, &S, NULL); } - mp_div_d(&S, 5, &S, NULL); --s5; /* @@ -3861,11 +3976,13 @@ ShorteningBignumConversion( * 10**42 16 trips * thereafter no gain. */ - } else { - mp_mul_d(&b, 10, &b); - mp_mul_d(&mminus, 10, &mminus); - if (m2plus > m2minus) { - mp_mul_2d(&mplus, 10, &mplus); + } else if (err == MP_OKAY) { + err = mp_mul_d(&b, 10, &b); + if (err == MP_OKAY) { + err = mp_mul_d(&mminus, 10, &mminus); + } + if ((err == MP_OKAY) && (m2plus > m2minus)) { + err = mp_mul_2d(&mplus, 10, &mplus); } } @@ -3929,24 +4046,36 @@ StrictBignumConversion( int digit; /* Current digit of the result. */ int g; /* Size of the current digit ground. */ int i, j; + mp_err err; /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ - mp_init_multi(&dig, NULL); - mp_init_u64(&b, bw); - mp_mul_2d(&b, b2, &b); - mp_init_set(&S, 1); - MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); + if (mp_init(&dig) != MP_OKAY) { + return NULL; + } + if (mp_init_u64(&b, bw) != MP_OKAY) { + mp_clear(&dig); + return NULL; + } + err = mp_mul_2d(&b, b2, &b); + if (err == MP_OKAY) { + err = mp_init_set(&S, 1); + } + if (err == MP_OKAY) { + err = MulPow5(&S, s5, &S); + if (err == MP_OKAY) { + err = mp_mul_2d(&S, s2, &S); + } + } /* * Handle the case where we guess the position of the decimal point wrong. */ - if (mp_cmp_mag(&b, &S) == MP_LT) { - mp_mul_d(&b, 10, &b); + if ((mp_cmp_mag(&b, &S) == MP_LT) && (mp_mul_d(&b, 10, &b) == MP_OKAY)) { ilim =ilim1; --k; } @@ -3956,7 +4085,7 @@ StrictBignumConversion( */ i = 0; - mp_div(&b, &S, &dig, &b); + err = mp_div(&b, &S, &dig, &b); if (dig.used > 1 || dig.dp[0] >= 10) { Tcl_Panic("wrong digit!"); } @@ -3968,12 +4097,11 @@ StrictBignumConversion( *s++ = '0' + digit; if (++i >= ilim) { - mp_mul_2d(&b, 1, &b); - if (ShouldBankerRoundUp(&b, &S, digit&1)) { + if ((mp_mul_2d(&b, 1, &b) == MP_OKAY) && ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } } else { - for (;;) { + while (err == MP_OKAY) { /* * Shift by a group of digits. */ @@ -3983,16 +4111,20 @@ StrictBignumConversion( g = DIGIT_GROUP; } if (s5 >= g) { - mp_div_d(&S, dpow5[g], &S, NULL); + err = mp_div_d(&S, dpow5[g], &S, NULL); s5 -= g; } else if (s5 > 0) { - mp_div_d(&S, dpow5[s5], &S, NULL); - mp_mul_d(&b, dpow5[g - s5], &b); + err = mp_div_d(&S, dpow5[s5], &S, NULL); + if (err == MP_OKAY) { + err = mp_mul_d(&b, dpow5[g - s5], &b); + } s5 = 0; } else { - mp_mul_d(&b, dpow5[g], &b); + err = mp_mul_d(&b, dpow5[g], &b); + } + if (err == MP_OKAY) { + err = mp_mul_2d(&b, g, &b); } - mp_mul_2d(&b, g, &b); /* * As with the shortening bignum conversion, it's possible at this @@ -4006,8 +4138,8 @@ StrictBignumConversion( * Extract the next group of digits. */ - mp_div(&b, &S, &dig, &b); - if (dig.used > 1) { + + if ((err != MP_OKAY) || (mp_div(&b, &S, &dig, &b) != MP_OKAY) || (dig.used > 1)) { Tcl_Panic("wrong digit!"); } digit = dig.dp[0]; @@ -4024,8 +4156,7 @@ StrictBignumConversion( */ if (i == ilim) { - mp_mul_2d(&b, 1, &b); - if (ShouldBankerRoundUp(&b, &S, digit&1)) { + if ((mp_mul_2d(&b, 1, &b) == MP_OKAY) && ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } break; @@ -4400,6 +4531,7 @@ TclInitDoubleConversion(void) Tcl_WideUInt iv; } bitwhack; #endif + mp_err err = MP_OKAY; #if defined(__sgi) && defined(_COMPILER_VERSION) union fpc_csr mipsCR; @@ -4456,16 +4588,19 @@ TclInitDoubleConversion(void) */ for (i=0; i<9; ++i) { - mp_init(pow5 + i); + err = err || mp_init(pow5 + i); } mp_set_u64(pow5, 5); for (i=0; i<8; ++i) { - mp_sqr(pow5+i, pow5+i+1); + err = err || mp_sqr(pow5+i, pow5+i+1); } - mp_init_u64(pow5_13, 1220703125); + err = err || mp_init_u64(pow5_13, 1220703125); for (i = 1; i < 5; ++i) { - mp_init(pow5_13 + i); - mp_sqr(pow5_13 + i - 1, pow5_13 + i); + err = err || mp_init(pow5_13 + i); + err = err || mp_sqr(pow5_13 + i - 1, pow5_13 + i); + } + if (err != MP_OKAY) { + Tcl_Panic("out of memory"); } /* @@ -4557,6 +4692,7 @@ Tcl_InitBignumFromDouble( { double fract; int expt; + mp_err err; /* * Infinite values can't convert to bignum. @@ -4574,19 +4710,24 @@ Tcl_InitBignumFromDouble( fract = frexp(d, &expt); if (expt <= 0) { - mp_init(b); + err = mp_init(b); mp_zero(b); } else { Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits); int shift = expt - mantBits; - mp_init_i64(b, w); - if (shift < 0) { - mp_div_2d(b, -shift, b, NULL); + err = mp_init_i64(b, w); + if (err != MP_OKAY) { + /* just skip */ + } else if (shift < 0) { + err = mp_div_2d(b, -shift, b, NULL); } else if (shift > 0) { - mp_mul_2d(b, shift, b); + err = mp_mul_2d(b, shift, b); } } + if (err != MP_OKAY) { + return TCL_ERROR; + } return TCL_OK; } @@ -4612,6 +4753,7 @@ TclBignumToDouble( mp_int b; int bits, shift, i, lsb; double r; + mp_err err; /* @@ -4640,11 +4782,13 @@ TclBignumToDouble( * 'rounded to even'. */ - mp_init(&b); - if (shift == 0) { - mp_copy(a, &b); + err = mp_init(&b); + if (err != MP_OKAY) { + /* just skip */ + } else if (shift == 0) { + err = mp_copy(a, &b); } else if (shift > 0) { - mp_mul_2d(a, shift, &b); + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { lsb = mp_cnt_lsb(a); if (lsb == -1-shift) { @@ -4653,12 +4797,12 @@ TclBignumToDouble( * Round to even */ - mp_div_2d(a, -shift, &b, NULL); - if (mp_isodd(&b)) { + err = mp_div_2d(a, -shift, &b, NULL); + if ((err == MP_OKAY) && mp_isodd(&b)) { if (mp_isneg(&b)) { - mp_sub_d(&b, 1, &b); + err = mp_sub_d(&b, 1, &b); } else { - mp_add_d(&b, 1, &b); + err = mp_add_d(&b, 1, &b); } } } else { @@ -4667,13 +4811,15 @@ TclBignumToDouble( * Ordinary rounding */ - mp_div_2d(a, -1-shift, &b, NULL); - if (mp_isneg(&b)) { - mp_sub_d(&b, 1, &b); + err = mp_div_2d(a, -1-shift, &b, NULL); + if (err != MP_OKAY) { + /* just skip */ + } else if (mp_isneg(&b)) { + err = mp_sub_d(&b, 1, &b); } else { - mp_add_d(&b, 1, &b); + err = mp_add_d(&b, 1, &b); } - mp_div_2d(&b, 1, &b, NULL); + err = mp_div_2d(&b, 1, &b, NULL); } } @@ -4681,8 +4827,11 @@ TclBignumToDouble( * Accumulate the result, one mp_digit at a time. */ + if (err != MP_OKAY) { + return 0.0; + } r = 0.0; - for (i=b.used-1 ; i>=0 ; --i) { + for (i = b.used-1; i>=0; --i) { r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; } mp_clear(&b); @@ -4724,10 +4873,11 @@ TclCeil( { double r = 0.0; mp_int b; + mp_err err; - mp_init(&b); - if (mp_isneg(a)) { - mp_neg(a, &b); + err = mp_init(&b); + if ((err == MP_OKAY) && mp_isneg(a)) { + err = mp_neg(a, &b); r = -TclFloor(&b); } else { int bits = mp_count_bits(a); @@ -4737,19 +4887,26 @@ TclCeil( } else { int i, exact = 1, shift = mantBits - bits; - if (shift > 0) { - mp_mul_2d(a, shift, &b); + if (err != MP_OKAY) { + /* just skip */ + } else if (shift > 0) { + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { mp_int d; - mp_init(&d); - mp_div_2d(a, -shift, &b, &d); + err = mp_init(&d); + if (err == MP_OKAY) { + err = mp_div_2d(a, -shift, &b, &d); + } exact = mp_iszero(&d); mp_clear(&d); } else { - mp_copy(a, &b); + err = mp_copy(a, &b); } - if (!exact) { - mp_add_d(&b, 1, &b); + if ((err == MP_OKAY) && !exact) { + err = mp_add_d(&b, 1, &b); + } + if (err != MP_OKAY) { + return 0.0; } for (i=b.used-1 ; i>=0 ; --i) { r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; @@ -4781,10 +4938,11 @@ TclFloor( { double r = 0.0; mp_int b; + mp_err err; - mp_init(&b); - if (mp_isneg(a)) { - mp_neg(a, &b); + err = mp_init(&b); + if ((err == MP_OKAY) && mp_isneg(a)) { + err = mp_neg(a, &b); r = -TclCeil(&b); } else { int bits = mp_count_bits(a); @@ -4795,11 +4953,14 @@ TclFloor( int i, shift = mantBits - bits; if (shift > 0) { - mp_mul_2d(a, shift, &b); + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { - mp_div_2d(a, -shift, &b, NULL); + err = mp_div_2d(a, -shift, &b, NULL); } else { - mp_copy(a, &b); + err = mp_copy(a, &b); + } + if (err != MP_OKAY) { + return 0.0; } for (i=b.used-1 ; i>=0 ; --i) { r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; @@ -4841,6 +5002,7 @@ BignumToBiasedFrExp( int shift; int i; double r; + mp_err err = MP_OKAY; /* * Determine how many bits we need, and extract that many from the input. @@ -4849,13 +5011,15 @@ BignumToBiasedFrExp( bits = mp_count_bits(a); shift = mantBits - 2 - bits; - mp_init(&b); + if (mp_init(&b)) { + return 0.0; + } if (shift > 0) { - mp_mul_2d(a, shift, &b); + err = mp_mul_2d(a, shift, &b); } else if (shift < 0) { - mp_div_2d(a, -shift, &b, NULL); + err = mp_div_2d(a, -shift, &b, NULL); } else { - mp_copy(a, &b); + err = mp_copy(a, &b); } /* @@ -4863,8 +5027,10 @@ BignumToBiasedFrExp( */ r = 0.0; - for (i=b.used-1; i>=0; --i) { - r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; + if (err == MP_OKAY) { + for (i=b.used-1; i>=0; --i) { + r = ldexp(r, MP_DIGIT_BIT) + b.dp[i]; + } } mp_clear(&b); diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index ced860e..9d976cd 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -289,7 +289,8 @@ TestbignumobjCmd( } break; - case BIGNUM_ISEVEN: + case BIGNUM_ISEVEN: { + mp_err err; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; @@ -301,13 +302,18 @@ TestbignumobjCmd( &bignumValue) != TCL_OK) { return TCL_ERROR; } + err = mp_mod_2d(&bignumValue, 1, &bignumValue); + if (err == MP_OKAY && !mp_iszero(&bignumValue)) { + err = MP_ERR; + } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetIntObj(varPtr[varIndex], !mp_isodd(&bignumValue)); + Tcl_SetIntObj(varPtr[varIndex], err == MP_OKAY); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(!mp_isodd(&bignumValue))); + SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(err == MP_OKAY)); } mp_clear(&bignumValue); - break; + } + break; case BIGNUM_RADIXSIZE: if (objc != 3) { |