summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-05-25 23:21:10 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-05-25 23:21:10 -0700
commit225ae600e82d6e2b67341cfb398519c213650b99 (patch)
treed191fad80c880f1e4fe8ded972e5ea20142f4db7
parentd40e471e4d1e4c4a721da3d8a95dca99cc51cff0 (diff)
downloadtxr-225ae600e82d6e2b67341cfb398519c213650b99.tar.gz
txr-225ae600e82d6e2b67341cfb398519c213650b99.tar.bz2
txr-225ae600e82d6e2b67341cfb398519c213650b99.zip
mpi: avoid additive inverse of most negative integer.
* mpi.c (mp_set_int, mp_set_intptr, mp_set_double_intptr): When the signed input is negative, do not simply calculate its inverse with unary minus, because it could be the most negative value that has no additive inverse. Instead, convert to unsigned first, then apply the unary minus to the unsigned type, which calculates the two's complement.
-rw-r--r--mpi/mpi.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/mpi/mpi.c b/mpi/mpi.c
index 5befd2b3..52525762 100644
--- a/mpi/mpi.c
+++ b/mpi/mpi.c
@@ -364,7 +364,8 @@ void mp_set(mp_int *mp, mp_digit d)
mp_err mp_set_int(mp_int *mp, long z)
{
mp_size ix;
- unsigned long v = abs(z);
+ unsigned long w = z;
+ unsigned long v = z >= 0 ? w : -w;
mp_err res;
ARGCHK(mp != NULL, MP_BADARG);
@@ -422,7 +423,8 @@ mp_err mp_set_uintptr(mp_int *mp, uint_ptr_t z)
mp_err mp_set_intptr(mp_int *mp, int_ptr_t z)
{
- int_ptr_t v = z > 0 ? z : -z;
+ uint_ptr_t w = z;
+ uint_ptr_t v = z >= 0 ? w : -w;
mp_err err = mp_set_uintptr(mp, v);
if (err == MP_OKAY && z < 0)
@@ -496,7 +498,8 @@ int mp_in_uintptr_range(mp_int *mp)
mp_err mp_set_double_intptr(mp_int *mp, double_intptr_t z)
{
mp_size ix, shift;
- double_intptr_t v = z > 0 ? z : -z;
+ double_uintptr_t w = z;
+ double_uintptr_t v = z >= 0 ? w : -w;
const mp_size nd = (sizeof v + sizeof (mp_digit) - 1) / sizeof (mp_digit);
ARGCHK(mp != NULL, MP_BADARG);