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

Values of value::TypeTags::ArraySet type might compare incorrectly for equality

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 5.1.0-rc0
    • Component/s: Internal Code
    • Labels:
      None
    • Backwards Compatibility:
      Fully Compatible
    • Operating System:
      ALL
    • Sprint:
      QE 2021-09-20
    • Linked BF Score:
      135

      Description

      Add a unit test similar to this one:

      TEST_F(SbeAccumulatorBuilderTest, compareTwoArraySets) {
          using namespace mongo::sbe;
       
          auto bsonObj = BSON("c" << 1);
          auto bsonArr = BSON_ARRAY(1 << 2 << 3);
       
          auto [lhsTag, lhsVal] = value::makeNewArraySet();
          value::ValueGuard lhsGuard{lhsTag, lhsVal};
          auto lhsView = value::getArraySetView(lhsVal);
          auto [lhsItemTag, lhsItemVal] =
              value::makeNewString("a long enough string"_sd); // FAILS
              // value::copyValue(value::TypeTags::bsonArray, value::bitcastFrom<const char*>(bsonArr.objdata())); // FAILS
              // value::makeSmallString("abc"_sd); // OK
              // copyValue(value::TypeTags::bsonObject, value::bitcastFrom<const char*>(bsonObj.objdata())); // FAILS
              lhsView->push_back(lhsItemTag, lhsItemVal);
       
          auto [rhsTag, rhsVal] = value::makeNewArraySet();
          value::ValueGuard rhsGuard{rhsTag, rhsVal};
          auto rhsView = value::getArraySetView(rhsVal);
          auto [rhsItemTag, rhsItemVal] =
              value::makeNewString("a long enough string"_sd); // FAILS
              // value::copyValue(value::TypeTags::bsonArray, value::bitcastFrom<const char*>(bsonArr.objdata())); // FAILS
              // value::makeSmallString("abc"_sd); // OK
              // copyValue(value::TypeTags::bsonObject, value::bitcastFrom<const char*>(bsonObj.objdata())); // FAILS
          rhsView->push_back(rhsItemTag, rhsItemVal);
       
          ASSERT(valueEquals(lhsTag, lhsVal, rhsTag, rhsVal))
              << "lhs set: " << std::make_pair(lhsTag, lhsVal)
              << "rhs set: " << std::make_pair(rhsTag, rhsVal);
      }
      
      

      The test creates two arraySets with a single item in each. The items would compare equal on their own, but when the containing sets are checked for equality, it would fail for pointer-based types of values such as bsonObject or long strings.

      The problem seems to be with the implementation of raw_hash_set::has_element() (see https://github.com/10gen/mongo/blob/defbe4582778e3da3abdc23c73ef7639543ab380/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.h#L1693 as, after matching the hashes, it compares the stored pairs literally, rather than using value::compareValue().

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              mohammad.dashti Mohammad Dashti
              Reporter:
              irina.yatsenko Irina Yatsenko
              Participants:
              Votes:
              0 Vote for this issue
              Watchers:
              13 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: