From 92c8a53689ae3aed2756704c0497352e686c3ae2 Mon Sep 17 00:00:00 2001
From: "jan.nijtmans" <nijtmans@users.sourceforge.net>
Date: Thu, 23 Jan 2020 12:55:41 +0000
Subject: Better error-handling in some libtommath calls.

---
 generic/tclBasic.c            |  2 +-
 generic/tclObj.c              |  9 ++++++++-
 generic/tclStrToD.c           |  4 ++--
 generic/tclTestObj.c          | 30 +++++++++++++++---------------
 generic/tclTomMathInterface.c | 19 +++++++------------
 5 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index a03f131..68f32c2 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -7547,7 +7547,7 @@ ExprAbsFunc(
 	if (mp_cmp_d((const mp_int *) ptr, 0) == MP_LT) {
 	    Tcl_GetBignumFromObj(NULL, objv[1], &big);
 	tooLarge:
-	    mp_neg(&big, &big);
+	    (void)mp_neg(&big, &big);
 	    Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
 	} else {
 	unChanged:
diff --git a/generic/tclObj.c b/generic/tclObj.c
index eca456f..b5d6d84 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -3392,7 +3392,14 @@ GetBignumFromObj(
 		mp_int temp;
 
 		UNPACK_BIGNUM(objPtr, temp);
-		mp_init_copy(bignumValue, &temp);
+		if (mp_init_copy(bignumValue, &temp) != MP_OKAY) {
+		    if (interp != NULL) {
+			Tcl_SetObjResult(interp, Tcl_NewStringObj(
+				"insufficient memory to unpack bignum", -1));
+			Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
+		    }
+		    return TCL_ERROR;
+		}
 	    } else {
 		UNPACK_BIGNUM(objPtr, *bignumValue);
 		objPtr->internalRep.twoPtrValue.ptr1 = NULL;
diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c
index 16eca19..523e0cb 100644
--- a/generic/tclStrToD.c
+++ b/generic/tclStrToD.c
@@ -1283,7 +1283,7 @@ TclParseNumber(
 	    }
 	    if (octalSignificandOverflow) {
 		if (signum) {
-		    mp_neg(&octalSignificandBig, &octalSignificandBig);
+		    (void)mp_neg(&octalSignificandBig, &octalSignificandBig);
 		}
 		TclSetBignumIntRep(objPtr, &octalSignificandBig);
 	    }
@@ -1330,7 +1330,7 @@ TclParseNumber(
 	    }
 	    if (significandOverflow) {
 		if (signum) {
-		    mp_neg(&significandBig, &significandBig);
+		    (void)mp_neg(&significandBig, &significandBig);
 		}
 		TclSetBignumIntRep(objPtr, &significandBig);
 	    }
diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c
index f741714..ba1dda6 100644
--- a/generic/tclTestObj.c
+++ b/generic/tclTestObj.c
@@ -160,7 +160,7 @@ TestbignumobjCmd(
     };
     int index, varIndex;
     const char *string;
-    mp_int bignumValue, newValue;
+    mp_int bignumValue;
     Tcl_Obj **varPtr;
 
     if (objc < 3) {
@@ -233,19 +233,16 @@ TestbignumobjCmd(
 		&bignumValue) != TCL_OK) {
 	    return TCL_ERROR;
 	}
-	if (mp_init(&newValue) != MP_OKAY
-		|| (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) {
+	if (mp_mul_d(&bignumValue, 10, &bignumValue) != MP_OKAY) {
 	    mp_clear(&bignumValue);
-	    mp_clear(&newValue);
 	    Tcl_SetObjResult(interp,
 		    Tcl_NewStringObj("error in mp_mul_d", -1));
 	    return TCL_ERROR;
 	}
-	mp_clear(&bignumValue);
 	if (!Tcl_IsShared(varPtr[varIndex])) {
-	    Tcl_SetBignumObj(varPtr[varIndex], &newValue);
+	    Tcl_SetBignumObj(varPtr[varIndex], &bignumValue);
 	} else {
-	    SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&newValue));
+	    SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&bignumValue));
 	}
 	break;
 
@@ -261,19 +258,16 @@ TestbignumobjCmd(
 		&bignumValue) != TCL_OK) {
 	    return TCL_ERROR;
 	}
-	if (mp_init(&newValue) != MP_OKAY
-		|| (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) {
+	if (mp_div_d(&bignumValue, 10, &bignumValue, NULL) != MP_OKAY) {
 	    mp_clear(&bignumValue);
-	    mp_clear(&newValue);
 	    Tcl_SetObjResult(interp,
 		    Tcl_NewStringObj("error in mp_div_d", -1));
 	    return TCL_ERROR;
 	}
-	mp_clear(&bignumValue);
 	if (!Tcl_IsShared(varPtr[varIndex])) {
-	    Tcl_SetBignumObj(varPtr[varIndex], &newValue);
+	    Tcl_SetBignumObj(varPtr[varIndex], &bignumValue);
 	} else {
-	    SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&newValue));
+	    SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&bignumValue));
 	}
 	break;
 
@@ -289,10 +283,16 @@ TestbignumobjCmd(
 		&bignumValue) != TCL_OK) {
 	    return TCL_ERROR;
 	}
+	if (mp_mod_2d(&bignumValue, 1, &bignumValue) != MP_OKAY) {
+	    mp_clear(&bignumValue);
+	    Tcl_SetObjResult(interp,
+		    Tcl_NewStringObj("error in mp_mod_2d", -1));
+	    return TCL_ERROR;
+	}
 	if (!Tcl_IsShared(varPtr[varIndex])) {
-	    Tcl_SetIntObj(varPtr[varIndex], !mp_isodd(&bignumValue));
+	    Tcl_SetIntObj(varPtr[varIndex], mp_iszero(&bignumValue));
 	} else {
-	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(!mp_isodd(&bignumValue)));
+	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(mp_iszero(&bignumValue)));
 	}
 	mp_clear(&bignumValue);
 	break;
diff --git a/generic/tclTomMathInterface.c b/generic/tclTomMathInterface.c
index 2dc8c2d..21fd238 100644
--- a/generic/tclTomMathInterface.c
+++ b/generic/tclTomMathInterface.c
@@ -111,7 +111,6 @@ TclBNInitBignumFromLong(
     mp_int *a,
     long initVal)
 {
-    int status;
     unsigned long v;
     mp_digit *p;
 
@@ -119,8 +118,7 @@ TclBNInitBignumFromLong(
      * Allocate enough memory to hold the largest possible long
      */
 
-    status = mp_init(a);
-    if (status != MP_OKAY) {
+    if (mp_init(a) != MP_OKAY) {
 	Tcl_Panic("initialization failure in TclBNInitBignumFromLong");
     }
 
@@ -130,7 +128,7 @@ TclBNInitBignumFromLong(
 
     if (initVal < 0) {
 	a->sign = MP_NEG;
-	v = -initVal;
+	v = -(unsigned long)initVal;
     } else {
 	a->sign = MP_ZPOS;
 	v = initVal;
@@ -170,12 +168,11 @@ TclBNInitBignumFromWideInt(
     mp_int *a,			/* Bignum to initialize */
     Tcl_WideInt v)		/* Initial value */
 {
-    if (v < (Tcl_WideInt)0) {
-	TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)(-v));
-	mp_neg(a, a);
-    } else {
-	TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)v);
+    if (v < 0) {
+	(void)TclBNInitBignumFromWideUInt(a, -(Tcl_WideUInt)v);
+	return mp_neg(a, a);
     }
+    (void)TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)v);
     return MP_OKAY;
 }
 
@@ -200,15 +197,13 @@ TclBNInitBignumFromWideUInt(
     mp_int *a,			/* Bignum to initialize */
     Tcl_WideUInt v)		/* Initial value */
 {
-    int status;
     mp_digit *p;
 
     /*
      * Allocate enough memory to hold the largest possible Tcl_WideUInt.
      */
 
-    status = mp_init(a);
-    if (status != MP_OKAY) {
+    if (mp_init(a) != MP_OKAY) {
 	Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt");
     }
 
-- 
cgit v0.12