summaryrefslogtreecommitdiff
path: root/src/mongo/bson/bsonelement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/bson/bsonelement.cpp')
-rw-r--r--src/mongo/bson/bsonelement.cpp59
1 files changed, 25 insertions, 34 deletions
diff --git a/src/mongo/bson/bsonelement.cpp b/src/mongo/bson/bsonelement.cpp
index 2409084bcfc..0990b1a18c7 100644
--- a/src/mongo/bson/bsonelement.cpp
+++ b/src/mongo/bson/bsonelement.cpp
@@ -46,6 +46,7 @@
#include "mongo/logv2/log.h"
#include "mongo/platform/strnlen.h"
#include "mongo/util/base64.h"
+#include "mongo/util/decimal_counter.h"
#include "mongo/util/duration.h"
#include "mongo/util/hex.h"
#include "mongo/util/scopeguard.h"
@@ -444,6 +445,7 @@ int BSONElement::compareElements(const BSONElement& l,
*/
std::vector<BSONElement> BSONElement::Array() const {
chk(mongo::Array);
+
std::vector<BSONElement> v;
BSONObjIterator i(Obj());
while (i.more()) {
@@ -464,6 +466,23 @@ std::vector<BSONElement> BSONElement::Array() const {
return v;
}
+std::vector<BSONElement> BSONElement::ArrayVerifyIndexes() const {
+ chk(mongo::Array);
+
+ std::vector<BSONElement> v;
+ DecimalCounter<std::uint32_t> counter(0);
+ for (auto element : Obj()) {
+ auto fieldName = element.fieldNameStringData();
+ uassert(ErrorCodes::BadValue,
+ fmt::format(
+ "Invalid array index field name: \"{}\", expected \"{}\"", fieldName, counter),
+ fieldName == counter);
+ counter++;
+ v.push_back(element);
+ }
+ return v;
+}
+
int BSONElement::woCompare(const BSONElement& elem,
ComparisonRulesSet rules,
const StringData::ComparatorInterface* comparator) const {
@@ -646,41 +665,13 @@ BSONElement BSONElement::operator[](StringData field) const {
}
namespace {
-MONGO_COMPILER_NOINLINE void msgAssertedBadType [[noreturn]] (const char* data) {
- // We intentionally read memory that may be out of the allocated memory's boundary, so do not
- // do this when the address sanitizer is enabled. We do this in an attempt to log as much
- // context about the failure, even if that risks undefined behavior or a segmentation fault.
-#if !__has_feature(address_sanitizer)
- bool logMemory = true;
-#else
- bool logMemory = false;
-#endif
- str::stream output;
- if (!logMemory) {
- output << fmt::format("BSONElement: bad type {0:d} @ {1:p}", *data, data);
- } else {
- // To reduce the risk of a segmentation fault, only print the bytes in the 32-bit aligned
- // block in which the address is located (i.e. round down to the lowest multiple of 32). The
- // hope is that it's safe to read memory that may fall within the same cache line. Generate
- // a mask to zero-out the last bits for a block-aligned address.
- // Ex: Inverse of 0x1F (32 - 1) looks like 0xFFFFFFE0, and ANDed with the pointer, zeroes
- // the lowest 5 bits, giving the starting address of a 32-bit block.
- const size_t blockSize = 32;
- const size_t mask = ~(blockSize - 1);
- const char* startAddr =
- reinterpret_cast<const char*>(reinterpret_cast<uintptr_t>(data) & mask);
- const size_t offset = data - startAddr;
-
- output << fmt::format(
- "BSONElement: bad type {0:d} @ {1:p} at offset {2:d} in block: ", *data, data, offset);
-
- for (size_t i = 0; i < blockSize; i++) {
- output << fmt::format("{0:#x} ", static_cast<uint8_t>(startAddr[i]));
- }
- }
- msgasserted(10320, output);
+MONGO_COMPILER_NOINLINE void msgAssertedBadType [[noreturn]] (int8_t type) {
+ int err = 10320; // work around linter
+ LOGV2_ERROR(err, "BSONElement: bad type", "type"_attr = zeroPaddedHex(type));
+ uasserted(err, "BSONElement: bad type");
}
+
} // namespace
int BSONElement::computeSize(int8_t type, const char* elem, int fieldNameSize, int bufSize) {
@@ -751,7 +742,7 @@ int BSONElement::computeSize(int8_t type, const char* elem, int fieldNameSize, i
if (type == MaxKey || type == MinKey)
return fieldNameSize + 1;
if (type != BSONType::RegEx)
- msgAssertedBadType(elem);
+ msgAssertedBadType(type);
// RegEx is two c-strings back-to-back.
const char* p = elem + fieldNameSize + 1;