From fe78c9ae8b4c9701cf6d84a0572a2d503c6ee424 Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Mon, 14 May 2012 02:50:01 +0200 Subject: Don't overflow signed ints in CBigNum::setint64(). CBigNum::setint64() does 'n <<= 8', where n is of type "long long". This leads to shifting onto and past the sign bit, which is undefined behavior in C++11 and can cause problems in the future. --- src/bignum.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/bignum.h') diff --git a/src/bignum.h b/src/bignum.h index f0971e8850..3716c49656 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -122,16 +122,22 @@ public: return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::min() : -(int)n); } - void setint64(int64 n) + void setint64(int64 sn) { - unsigned char pch[sizeof(n) + 6]; + unsigned char pch[sizeof(sn) + 6]; unsigned char* p = pch + 4; - bool fNegative = false; - if (n < (int64)0) + bool fNegative; + uint64 n; + + if (sn < (int64)0) { - n = -n; + n = -sn; fNegative = true; + } else { + n = sn; + fNegative = false; } + bool fLeadingZeroes = true; for (int i = 0; i < 8; i++) { -- cgit v1.2.3 From 5849bd472a3a7296f91b887884946218897ca11f Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Mon, 14 May 2012 21:17:24 +0200 Subject: Fix signed subtraction overflow in CBigNum::setint64(). As noticed by sipa (Pieter Wuille), this can happen when CBigNum::setint64() is called with an integer value of INT64_MIN (-2^63). When compiled with -ftrapv, the program would crash. Otherwise, it would execute an undefined operation (although in practice, usually the correct one). --- src/bignum.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/bignum.h') diff --git a/src/bignum.h b/src/bignum.h index 3716c49656..5190c2f390 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -131,7 +131,15 @@ public: if (sn < (int64)0) { - n = -sn; + // 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; fNegative = true; } else { n = sn; -- cgit v1.2.3