Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-37183

BSONElement::safeNumberLong is not safe

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 4.0.7, 4.1.7
    • Affects Version/s: None
    • Component/s: Internal Code
    • Labels:
    • 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()
          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.
          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.

            backlog-server-query Backlog - Query Team (Inactive)
            martin.neupauer@mongodb.com Martin Neupauer
            0 Vote for this issue
            15 Start watching this issue