-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: Internal Code
-
None
-
Query
-
Fully Compatible
-
ALL
-
v4.0
-
61
BSONElement::safeNumberLong is not as safe as it may seem. Consider the following simple program:
#include <limits> #include <iostream> int main() { //9223372036854775807 //0x7fffffffffffffff long long l1 = std::numeric_limits<long long>::max(); std::cout << l1 << "\n"; // convert the long long to double // The 0x7fffffffffffffff is not representable exactly as double // and the final result is greater than the original value. // It means that we will hit UB when going back to long long. double d = (double)l1; // In our case d and long long max are EQUAL so we will NOT enter // the branch. if (d > (double)std::numeric_limits<long long>::max()) { std::cout << "safe\n"; } if (d < std::numeric_limits<long long>::min()) { std::cout << "safe\n"; } // And hence BOOM! We hit the UB. //-9223372036854775808 //0x8000000000000000 long long l2 = (long long)d; std::cout << l2 << "\n"; return 0; }
I.e. there exist a double value that is greater than the long long max and yet is fails to be clamped by safeNumberLong.
Please note that safeNumberLong is called as part of the hash index processing. It means that we may have computed and stored wrong hash values to disk. If safeNumberLong gets fixed it may start generating different hash values leading to incorrect query results.
- is related to
-
SERVER-38623 Make safeNumberLongForHash consistent between PPC and other architectures
- Closed
- related to
-
SERVER-48286 Handle accuracy issues of casting long long to double
- Closed