Skip to content

Commit 8ce7a9d

Browse files
xy24evergreen
authored andcommitted
SERVER-43071 Fix the bug in KeyString::toBsonSafeWithDiscriminator which mistakenly invert discriminator byte
1 parent 6639626 commit 8ce7a9d

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

src/mongo/db/storage/key_string.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,10 +2388,10 @@ BSONObj toBsonSafeWithDiscriminator(const char* buffer,
23882388
size_t len,
23892389
Ordering ord,
23902390
const TypeBits& typeBits) {
2391-
boost::optional<std::string> discriminatorBit;
2392-
int fieldNo = -1;
2391+
boost::optional<std::string> discriminatorFieldName;
2392+
int fieldNo = -1; // Record which field should add the discriminator field name.
23932393

2394-
// First pass, get the discriminatorBit if there is any.
2394+
// First pass, get the discriminator byte if there is any.
23952395
{
23962396
BSONObjBuilder builder;
23972397
BufReader reader(buffer, len);
@@ -2400,9 +2400,13 @@ BSONObj toBsonSafeWithDiscriminator(const char* buffer,
24002400
const bool invert = (ord.get(i) == -1);
24012401
uint8_t ctype = readType<uint8_t>(&reader, invert);
24022402
if (ctype == kLess || ctype == kGreater) {
2403-
discriminatorBit = ctype == kLess ? "l" : "r";
2403+
// Discriminator byte should not be inverted. It's possible when `ord` has more
2404+
// fields than keystring and `invert` got mistakenly applied to discriminator byte.
2405+
if (invert)
2406+
ctype = ~ctype; // Invert it back.
2407+
discriminatorFieldName = ctype == kLess ? "l" : "g";
24042408
fieldNo = i - 1;
2405-
ctype = readType<uint8_t>(&reader, invert);
2409+
ctype = readType<uint8_t>(&reader, false);
24062410
invariant(ctype == kEnd);
24072411
}
24082412

@@ -2413,12 +2417,12 @@ BSONObj toBsonSafeWithDiscriminator(const char* buffer,
24132417
toBsonValue(
24142418
ctype, &reader, &typeBitsReader, invert, typeBits.version, &(builder << ""), 1);
24152419
}
2416-
// Early return if there is no discriminatorBit.
2417-
if (!discriminatorBit)
2420+
// Early return if there is no discriminator byte.
2421+
if (!discriminatorFieldName)
24182422
return builder.obj();
24192423
}
24202424

2421-
// Second pass, add discriminatorBit as the fieldName.
2425+
// Second pass, add discriminator byte as the fieldName.
24222426
{
24232427
BSONObjBuilder builder;
24242428
BufReader reader(buffer, len);
@@ -2427,15 +2431,18 @@ BSONObj toBsonSafeWithDiscriminator(const char* buffer,
24272431
const bool invert = (ord.get(i) == -1);
24282432
uint8_t ctype = readType<uint8_t>(&reader, invert);
24292433
if (ctype == kLess || ctype == kGreater) {
2430-
ctype = readType<uint8_t>(&reader, invert);
2434+
// Invert it back if discriminator byte got mistakenly inverted.
2435+
if (invert)
2436+
ctype = ~ctype;
2437+
ctype = readType<uint8_t>(&reader, false);
24312438
invariant(ctype == kEnd);
24322439
}
24332440

24342441
if (ctype == kEnd) {
24352442
break;
24362443
}
24372444

2438-
auto fn = i == fieldNo ? discriminatorBit.get() : "";
2445+
auto fn = i == fieldNo ? discriminatorFieldName.get() : "";
24392446
toBsonValue(
24402447
ctype, &reader, &typeBitsReader, invert, typeBits.version, &(builder << fn), 1);
24412448
}
@@ -2457,6 +2464,9 @@ Discriminator decodeDiscriminator(const char* buffer,
24572464
const bool invert = (ord.get(i) == -1);
24582465
uint8_t ctype = readType<uint8_t>(&reader, invert);
24592466
if (ctype == kLess || ctype == kGreater) {
2467+
// Invert it back if discriminator byte got mistakenly inverted.
2468+
if (invert)
2469+
ctype = ~ctype;
24602470
return ctype == kLess ? Discriminator::kExclusiveBefore
24612471
: Discriminator::kExclusiveAfter;
24622472
}

0 commit comments

Comments
 (0)