diff options
author | Waley <waley.chen@10gen.com> | 2016-01-27 13:48:16 -0500 |
---|---|---|
committer | Waley <waleycz@gmail.com> | 2016-02-08 11:28:07 -0500 |
commit | e34706733411e42dba63826a10b15f81e13fdd0d (patch) | |
tree | 2b29f4bcb8e43ed20ed2e2d907ff55a7bdc80214 /src/mongo/util/safe_num.cpp | |
parent | 93f767caeebda5ffd295f935e734e0bf02da3356 (diff) | |
download | mongo-e34706733411e42dba63826a10b15f81e13fdd0d.tar.gz |
SERVER-10568 SafeNum should be written in terms of explicitly sized types
Diffstat (limited to 'src/mongo/util/safe_num.cpp')
-rw-r--r-- | src/mongo/util/safe_num.cpp | 66 |
1 files changed, 29 insertions, 37 deletions
diff --git a/src/mongo/util/safe_num.cpp b/src/mongo/util/safe_num.cpp index f49fcd7b53a..cf8af43377c 100644 --- a/src/mongo/util/safe_num.cpp +++ b/src/mongo/util/safe_num.cpp @@ -116,7 +116,7 @@ bool SafeNum::isEquivalent(const SafeNum& rhs) const { // If none of the sides is a double, compare them as long's. if (_type != NumberDouble && rhs._type != NumberDouble) { - return getLongLong(*this) == getLongLong(rhs); + return getInt64(*this) == getInt64(rhs); } // If both sides are doubles, compare them as so. @@ -158,7 +158,7 @@ bool SafeNum::isIdentical(const SafeNum& rhs) const { } } -long long SafeNum::getLongLong(const SafeNum& snum) { +int64_t SafeNum::getInt64(const SafeNum& snum) { switch (snum._type) { case NumberInt: return snum._value.int32Val; @@ -201,7 +201,7 @@ Decimal128 SafeNum::getDecimal(const SafeNum& snum) { namespace { -SafeNum addInt32Int32(int lInt32, int rInt32) { +SafeNum addInt32Int32(int32_t lInt32, int32_t rInt32) { // NOTE: Please see "Secure Coding in C and C++", Second Edition, page 264-265 for // details on this algorithm (for an alternative resources, see // @@ -211,29 +211,25 @@ SafeNum addInt32Int32(int lInt32, int rInt32) { // // We are using the "Downcast from a larger type" algorithm here. We always perform // the arithmetic in 64-bit mode, which can never overflow for 32-bit - // integers. Then, if we fall within the allowable range of int, we downcast, + // integers. Then, if we fall within the allowable range of int32_t, we downcast, // otherwise, we retain the 64-bit result. + const int64_t result = static_cast<int64_t>(lInt32) + static_cast<int64_t>(rInt32); - // This algorithm is only correct if sizeof(long long) > sizeof(int) - static_assert(sizeof(long long) > sizeof(int), "sizeof(long long) > sizeof(int)"); - - const long long int result = - static_cast<long long int>(lInt32) + static_cast<long long int>(rInt32); - - if (result <= std::numeric_limits<int>::max() && result >= std::numeric_limits<int>::min()) { - return SafeNum(static_cast<int>(result)); + if (result <= std::numeric_limits<int32_t>::max() && + result >= std::numeric_limits<int32_t>::min()) { + return SafeNum(static_cast<int32_t>(result)); } return SafeNum(result); } -SafeNum addInt64Int64(long long lInt64, long long rInt64) { +SafeNum addInt64Int64(int64_t lInt64, int64_t rInt64) { // NOTE: Please see notes in addInt32Int32 above for references. In this case, since we // have no larger integer size, if our precondition test detects overflow we must // return an invalid SafeNum. Otherwise, the operation is safely performed by standard // arithmetic. - if (((rInt64 > 0) && (lInt64 > (std::numeric_limits<long long>::max() - rInt64))) || - ((rInt64 < 0) && (lInt64 < (std::numeric_limits<long long>::min() - rInt64)))) { + if (((rInt64 > 0) && (lInt64 > (std::numeric_limits<int64_t>::max() - rInt64))) || + ((rInt64 < 0) && (lInt64 < (std::numeric_limits<int64_t>::min() - rInt64)))) { return SafeNum(); } @@ -249,7 +245,7 @@ SafeNum addDecimals(Decimal128 lDecimal, Decimal128 rDecimal) { return SafeNum(lDecimal.add(rDecimal)); } -SafeNum mulInt32Int32(int lInt32, int rInt32) { +SafeNum mulInt32Int32(int32_t lInt32, int32_t rInt32) { // NOTE: Please see "Secure Coding in C and C++", Second Edition, page 264-265 for // details on this algorithm (for an alternative resources, see // @@ -259,23 +255,19 @@ SafeNum mulInt32Int32(int lInt32, int rInt32) { // // We are using the "Downcast from a larger type" algorithm here. We always perform // the arithmetic in 64-bit mode, which can never overflow for 32-bit - // integers. Then, if we fall within the allowable range of int, we downcast, + // integers. Then, if we fall within the allowable range of int32_t, we downcast, // otherwise, we retain the 64-bit result. + const int64_t result = static_cast<int64_t>(lInt32) * static_cast<int64_t>(rInt32); - // This algorithm is only correct if sizeof(long long) >= (2 * sizeof(int)) - static_assert(sizeof(long long) >= (2 * sizeof(int)), "sizeof(long long) >= (2 * sizeof(int))"); - - const long long int result = - static_cast<long long int>(lInt32) * static_cast<long long int>(rInt32); - - if (result <= std::numeric_limits<int>::max() && result >= std::numeric_limits<int>::min()) { - return SafeNum(static_cast<int>(result)); + if (result <= std::numeric_limits<int32_t>::max() && + result >= std::numeric_limits<int32_t>::min()) { + return SafeNum(static_cast<int32_t>(result)); } return SafeNum(result); } -SafeNum mulInt64Int64(long long lInt64, long long rInt64) { +SafeNum mulInt64Int64(int64_t lInt64, int64_t rInt64) { // NOTE: Please see notes in mulInt32Int32 above for references. In this case, // since we have no larger integer size, if our precondition test detects overflow // we must return an invalid SafeNum. Otherwise, the operation is safely performed @@ -283,27 +275,27 @@ SafeNum mulInt64Int64(long long lInt64, long long rInt64) { if (lInt64 > 0) { if (rInt64 > 0) { - if (lInt64 > (std::numeric_limits<long long>::max() / rInt64)) { + if (lInt64 > (std::numeric_limits<int64_t>::max() / rInt64)) { return SafeNum(); } } else { - if (rInt64 < (std::numeric_limits<long long>::min() / lInt64)) { + if (rInt64 < (std::numeric_limits<int64_t>::min() / lInt64)) { return SafeNum(); } } } else { if (rInt64 > 0) { - if (lInt64 < (std::numeric_limits<long long>::min() / rInt64)) { + if (lInt64 < (std::numeric_limits<int64_t>::min() / rInt64)) { return SafeNum(); } } else { - if ((lInt64 != 0) && (rInt64 < (std::numeric_limits<long long>::max() / lInt64))) { + if ((lInt64 != 0) && (rInt64 < (std::numeric_limits<int64_t>::max() / lInt64))) { return SafeNum(); } } } - const long long result = lInt64 * rInt64; + const int64_t result = lInt64 * rInt64; return SafeNum(result); } @@ -391,11 +383,11 @@ SafeNum SafeNum::andInternal(const SafeNum& lhs, const SafeNum& rhs) { } if (lType == NumberInt && rType == NumberLong) { - return (static_cast<long long int>(lhs._value.int32Val) & rhs._value.int64Val); + return (static_cast<int64_t>(lhs._value.int32Val) & rhs._value.int64Val); } if (lType == NumberLong && rType == NumberInt) { - return (lhs._value.int64Val & static_cast<long long int>(rhs._value.int32Val)); + return (lhs._value.int64Val & static_cast<int64_t>(rhs._value.int32Val)); } if (lType == NumberLong && rType == NumberLong) { @@ -414,11 +406,11 @@ SafeNum SafeNum::orInternal(const SafeNum& lhs, const SafeNum& rhs) { } if (lType == NumberInt && rType == NumberLong) { - return (static_cast<long long int>(lhs._value.int32Val) | rhs._value.int64Val); + return (static_cast<int64_t>(lhs._value.int32Val) | rhs._value.int64Val); } if (lType == NumberLong && rType == NumberInt) { - return (lhs._value.int64Val | static_cast<long long int>(rhs._value.int32Val)); + return (lhs._value.int64Val | static_cast<int64_t>(rhs._value.int32Val)); } if (lType == NumberLong && rType == NumberLong) { @@ -437,11 +429,11 @@ SafeNum SafeNum::xorInternal(const SafeNum& lhs, const SafeNum& rhs) { } if (lType == NumberInt && rType == NumberLong) { - return (static_cast<long long int>(lhs._value.int32Val) ^ rhs._value.int64Val); + return (static_cast<int64_t>(lhs._value.int32Val) ^ rhs._value.int64Val); } if (lType == NumberLong && rType == NumberInt) { - return (lhs._value.int64Val ^ static_cast<long long int>(rhs._value.int32Val)); + return (lhs._value.int64Val ^ static_cast<int64_t>(rhs._value.int32Val)); } if (lType == NumberLong && rType == NumberLong) { |