diff options
Diffstat (limited to 'src/mongo/bson/bsonelement.cpp')
| -rw-r--r-- | src/mongo/bson/bsonelement.cpp | 59 |
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; |
