summaryrefslogtreecommitdiff
path: root/src/mongo/bson/bsonelement_test.cpp
diff options
context:
space:
mode:
authorJustin Seyster <justin.seyster@mongodb.com>2019-03-27 17:16:13 -0400
committerJustin Seyster <justin.seyster@mongodb.com>2019-04-03 15:16:15 -0400
commitf2ab9fa71aabf110b67c28131241de6a27a3f09e (patch)
tree66eb289716ef0c4899a6538426afed41f7fd8da8 /src/mongo/bson/bsonelement_test.cpp
parentd3b98acb26920c94079ebd922b76dddf67d580c0 (diff)
downloadmongo-f2ab9fa71aabf110b67c28131241de6a27a3f09e.tar.gz
SERVER-38623 Make safeNumberLongForHash consistent on all platforms
Previously, the hash function for double values relied on undefined behavior when computing the hash for 2^63, meaning that it could give different results on different platforms. Almost all platforms we support returned -2^63 as the result of safeNumberLongForHash when the input was 2^63, so this patch makes that the official result. Now, safeNumberLongForHash will explicitly convert 2^63 to -2^63 on _all_ platforms without invoking any undefined behavior. Note that this does not change our guidance that using a hashed index for a field containing a floating point value greater than 2^53 is unsupported: https://docs.mongodb.com/manual/core/index-hashed/#considerations
Diffstat (limited to 'src/mongo/bson/bsonelement_test.cpp')
-rw-r--r--src/mongo/bson/bsonelement_test.cpp13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/mongo/bson/bsonelement_test.cpp b/src/mongo/bson/bsonelement_test.cpp
index 27f51039245..d8f311450fd 100644
--- a/src/mongo/bson/bsonelement_test.cpp
+++ b/src/mongo/bson/bsonelement_test.cpp
@@ -138,12 +138,19 @@ TEST(BSONElement, SafeNumberLongPositiveBound) {
<< "positiveInfinity"
<< std::numeric_limits<double>::infinity());
- // The numberLongForHash() function clamps kLongLongMaxPlusOneAsDouble to the max 64-bit value
+ // kLongLongMaxPlusOneAsDouble is the least double value that will overflow a 64-bit signed
+ // two's-complement integer. Historically, converting this value with safeNumberLong() would
+ // return the result of casting to double with a C-style cast. That operation is undefined
+ // because of the overflow, but on most platforms we support, it returned the min 64-bit value
+ // (-2^63). The safeNumberLongForHash() function should preserve that behavior indefinitely for
+ // compatibility with on-disk data.
+ ASSERT_EQ(obj["kLongLongMaxPlusOneAsDouble"].safeNumberLongForHash(),
+ std::numeric_limits<long long>::lowest());
+
+ // The safeNumberLong() function clamps kLongLongMaxPlusOneAsDouble to the max 64-bit value
// (2^63 - 1).
ASSERT_EQ(obj["kLongLongMaxPlusOneAsDouble"].safeNumberLong(),
std::numeric_limits<long long>::max());
- // The safeNumberLongForHash() function will return -2^63, but we don't test it here, because
- // the overflowing cast that it uses can trigger UBSan
// One quantum below kLongLongMaxPlusOneAsDouble is the largest double that safely converts to a
// 64-bit signed two-s complement integer. Both safeNumberLong() and safeNumberLongForHash()