diff options
| author | Luke Dashjr <[email protected]> | 2012-06-18 20:35:10 +0000 |
|---|---|---|
| committer | Luke Dashjr <[email protected]> | 2012-06-18 20:37:57 +0000 |
| commit | 0f5a2a82d93f55e1f5ad1c5401b8b5ceeb38b0df (patch) | |
| tree | 5c976160f2611e2d5dfdb33c3e5c76d5865643e0 /src/bignum.h | |
| parent | Fix signed subtraction overflow in CBigNum::setint64(). (diff) | |
| download | discoin-0f5a2a82d93f55e1f5ad1c5401b8b5ceeb38b0df.tar.xz discoin-0f5a2a82d93f55e1f5ad1c5401b8b5ceeb38b0df.zip | |
CBigNum: Convert negative int64 values in a more well-defined way
Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
Diffstat (limited to 'src/bignum.h')
| -rw-r--r-- | src/bignum.h | 12 |
1 files changed, 3 insertions, 9 deletions
diff --git a/src/bignum.h b/src/bignum.h index 5190c2f39..74f657b56 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -131,15 +131,9 @@ public: if (sn < (int64)0) { - // We negate in 2 steps to avoid signed subtraction overflow, - // i.e. -(-2^63), which is an undefined operation and causes SIGILL - // when compiled with -ftrapv. - // - // Note that uint64_t n = sn, when sn is an int64_t, is a - // well-defined operation and n will be equal to sn + 2^64 when sn - // is negative. - n = sn; - n = -n; + // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate + n = -(sn + 1); + ++n; fNegative = true; } else { n = sn; |