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

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

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 5.1.0-rc0
    • Affects Version/s: None
    • Component/s: Internal Code
    • Labels:
      None
    • Fully Compatible
    • ALL
    • QE 2021-09-20
    • 135

      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().

            Assignee:
            mohammad.dashti@mongodb.com Mohammad Dashti (Inactive)
            Reporter:
            irina.yatsenko@mongodb.com Irina Yatsenko (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            13 Start watching this issue

              Created:
              Updated:
              Resolved: