From cc211af4eafca77e7d1ede7371c88c6d6fc44a80 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 9 Jan 2020 09:20:57 +0000 Subject: Start handling WUR (Warn Unused Result) in all tommath calls. WIP, not complete yet. --- generic/tclBasic.c | 37 ++++++++--- generic/tclExecute.c | 181 ++++++++++++++++++++++++++++++++++----------------- generic/tclObj.c | 25 ++++--- generic/tclStrToD.c | 127 +++++++++++++++++++++++------------- generic/tclTestObj.c | 14 ++-- 5 files changed, 260 insertions(+), 124 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 8bc83cc..3d75d97 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -652,6 +652,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: @@ -1796,6 +1797,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"); @@ -1854,8 +1856,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; } @@ -6149,6 +6154,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); @@ -7593,6 +7601,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". @@ -8032,6 +8047,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); @@ -8093,9 +8109,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); } @@ -8108,21 +8129,30 @@ ExecuteExtendedBinaryMathOp( } Tcl_GetBignumFromObj(NULL, valuePtr, &big1); Tcl_GetBignumFromObj(NULL, value2Ptr, &big2); - mp_init(&bigResult); - mp_init(&bigRemainder); - mp_div(&big1, &big2, &bigResult, &bigRemainder); + err = mp_init_multi(&bigResult, &bigRemainder, NULL); + if (err == MP_OKAY) { + err = mp_div(&big1, &big2, &bigResult, &bigRemainder); + } 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); + } + if (err != 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: @@ -8248,11 +8278,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); @@ -8265,20 +8300,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); @@ -8341,8 +8381,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); } @@ -8499,8 +8539,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); } @@ -8647,38 +8692,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); @@ -8699,6 +8750,7 @@ ExecuteExtendedUnaryMathOp( Tcl_WideInt w; mp_int big; Tcl_Obj *objResultPtr; + mp_err err = MP_OKAY; (void) GetNumberFromObj(NULL, valuePtr, &ptr, &type); @@ -8710,8 +8762,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) { @@ -8722,12 +8779,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..94e06ce 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -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) { + mp_add_d(&significandBig, (mp_digit) d, &significandBig); + } } } + if (err != MP_OKAY) { + return TCL_ERROR; + } numTrailZeros = 0; state = HEXADECIMAL; break; @@ -4557,6 +4570,7 @@ Tcl_InitBignumFromDouble( { double fract; int expt; + mp_err err; /* * Infinite values can't convert to bignum. @@ -4574,19 +4588,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 +4631,7 @@ TclBignumToDouble( mp_int b; int bits, shift, i, lsb; double r; + mp_err err; /* @@ -4640,11 +4660,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 +4675,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 +4689,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 +4705,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 +4751,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 +4765,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 ((err == MP_OKAY) && !exact) { + err = mp_add_d(&b, 1, &b); } - if (!exact) { - 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 +4816,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 +4831,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]; diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index e616433..0faf9a8 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -281,7 +281,8 @@ TestbignumobjCmd( } break; - case BIGNUM_ISEVEN: + case BIGNUM_ISEVEN: { + mp_err err; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; @@ -293,13 +294,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) { -- cgit v0.12