diff options
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/ops/write_ops.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops_parsers.h | 14 | ||||
-rw-r--r-- | src/mongo/db/pipeline/aggregation_request_helper.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/pipeline/aggregation_request_helper.h | 19 | ||||
-rw-r--r-- | src/mongo/db/pipeline/aggregation_request_test.cpp | 17 | ||||
-rw-r--r-- | src/mongo/db/query/hint_parser.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/query/max_time_ms_parser.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/query/max_time_ms_parser.h | 4 | ||||
-rw-r--r-- | src/mongo/db/query/query_request_test.cpp | 58 | ||||
-rw-r--r-- | src/mongo/idl/basic_types.h | 26 | ||||
-rw-r--r-- | src/mongo/idl/idl_parser.cpp | 16 | ||||
-rw-r--r-- | src/mongo/idl/idl_parser.h | 16 |
12 files changed, 203 insertions, 11 deletions
diff --git a/src/mongo/db/ops/write_ops.cpp b/src/mongo/db/ops/write_ops.cpp index 8e00f19713a..f69ad8844bb 100644 --- a/src/mongo/db/ops/write_ops.cpp +++ b/src/mongo/db/ops/write_ops.cpp @@ -79,6 +79,10 @@ void checkOpCountForCommand(const T& op, size_t numOps) { namespace write_ops { +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ bool readMultiDeleteProperty(const BSONElement& limitElement) { // Using a double to avoid throwing away illegal fractional portion. Don't want to accept 0.5 // here @@ -90,6 +94,10 @@ bool readMultiDeleteProperty(const BSONElement& limitElement) { return limit == 0; } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void writeMultiDeleteProperty(bool isMulti, StringData fieldName, BSONObjBuilder* builder) { builder->append(fieldName, isMulti ? 0 : 1); } @@ -328,6 +336,10 @@ write_ops::UpdateModification::UpdateModification(const BSONObj& update, Classic write_ops::UpdateModification::UpdateModification(std::vector<BSONObj> pipeline) : _update{PipelineUpdate{std::move(pipeline)}} {} +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ write_ops::UpdateModification write_ops::UpdateModification::parseFromBSON(BSONElement elem) { return UpdateModification(elem); } @@ -363,6 +375,10 @@ write_ops::UpdateModification::Type write_ops::UpdateModification::type() const _update); } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void write_ops::UpdateModification::serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const { diff --git a/src/mongo/db/ops/write_ops_parsers.h b/src/mongo/db/ops/write_ops_parsers.h index 20b9f543bc7..900740b271b 100644 --- a/src/mongo/db/ops/write_ops_parsers.h +++ b/src/mongo/db/ops/write_ops_parsers.h @@ -51,11 +51,17 @@ constexpr int kRetryableAndTxnBatchWriteBSONSizeOverhead = /** * Parses the 'limit' property of a delete entry, which has inverted meaning from the 'multi' * property of an update. + * + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. */ bool readMultiDeleteProperty(const BSONElement& limitElement); /** * Writes the 'isMulti' value as a limit property. + * + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. */ void writeMultiDeleteProperty(bool isMulti, StringData fieldName, BSONObjBuilder* builder); @@ -100,8 +106,16 @@ public: /** * These methods support IDL parsing of the "u" field from the update command and OP_UPDATE. + * + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. */ static UpdateModification parseFromBSON(BSONElement elem); + + /** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const; // When parsing from legacy OP_UPDATE messages, we receive the "u" field as an object. When an diff --git a/src/mongo/db/pipeline/aggregation_request_helper.cpp b/src/mongo/db/pipeline/aggregation_request_helper.cpp index 133e151dae6..5bfa4b7c2a3 100644 --- a/src/mongo/db/pipeline/aggregation_request_helper.cpp +++ b/src/mongo/db/pipeline/aggregation_request_helper.cpp @@ -241,6 +241,10 @@ PlanExecutorPipeline::ResumableScanType getResumableScanType(const AggregateComm // Custom serializers/deserializers for AggregateCommandRequest. +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON( const BSONElement& explainElem) { uassert(ErrorCodes::TypeMismatch, @@ -254,6 +258,10 @@ boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON( return boost::none; } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain, StringData fieldName, BSONObjBuilder* builder) { @@ -264,6 +272,10 @@ void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain, return; } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& cursorElem) { if (cursorElem.eoo()) { SimpleCursorOptions cursor; @@ -284,6 +296,10 @@ mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& curso return cursor; } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeAggregateCursorToBSON(const mongo::SimpleCursorOptions& cursor, StringData fieldName, BSONObjBuilder* builder) { diff --git a/src/mongo/db/pipeline/aggregation_request_helper.h b/src/mongo/db/pipeline/aggregation_request_helper.h index 631fd87a278..bb447712f7f 100644 --- a/src/mongo/db/pipeline/aggregation_request_helper.h +++ b/src/mongo/db/pipeline/aggregation_request_helper.h @@ -131,23 +131,40 @@ PlanExecutorPipeline::ResumableScanType getResumableScanType(const AggregateComm /** * Custom serializers/deserializers for AggregateCommandRequest. + * + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. */ - boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON( const BSONElement& explainElem); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain, StringData fieldName, BSONObjBuilder* builder); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& cursorElem); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeAggregateCursorToBSON(const SimpleCursorOptions& cursor, StringData fieldName, BSONObjBuilder* builder); /** * Parse an aggregation pipeline definition from 'pipelineElem'. + * + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. */ static std::vector<BSONObj> parsePipelineFromBSON(const BSONElement& pipelineElem) { std::vector<BSONObj> pipeline; diff --git a/src/mongo/db/pipeline/aggregation_request_test.cpp b/src/mongo/db/pipeline/aggregation_request_test.cpp index 66bac44423c..947764892b7 100644 --- a/src/mongo/db/pipeline/aggregation_request_test.cpp +++ b/src/mongo/db/pipeline/aggregation_request_test.cpp @@ -554,6 +554,23 @@ TEST(AggregationRequestTest, ShouldRejectNoCursorNoExplain) { aggregation_request_helper::parseFromBSONForTests(nss, cursorRequest.done()).getStatus()); } +TEST(AggregationRequestTest, ShouldRejectNonObjectCursor) { + NamespaceString nss("a.collection"); + const BSONObj validRequest = fromjson( + "{aggregate: 'collection'," + "pipeline: [{$match: {a: 'abc'}}]," + "cursor: {}," + "isMapReduceCommand: true," + "$db: 'a'}"); + const BSONObj nonObjCursorCommand = fromjson("{cursor: 1}"); + aggregationRequestParseFailureHelper( + nss, validRequest, nonObjCursorCommand, ErrorCodes::TypeMismatch); + + const BSONObj arrayCursorCommand = fromjson("{cursor: []}"); + aggregationRequestParseFailureHelper( + nss, validRequest, arrayCursorCommand, ErrorCodes::TypeMismatch); +} + TEST(AggregationRequestTest, ShouldRejectExplainTrueWithSeparateExplainArg) { NamespaceString nss("a.collection"); const BSONObj validRequest = fromjson( diff --git a/src/mongo/db/query/hint_parser.cpp b/src/mongo/db/query/hint_parser.cpp index d1372d86f55..1de75b84f82 100644 --- a/src/mongo/db/query/hint_parser.cpp +++ b/src/mongo/db/query/hint_parser.cpp @@ -33,6 +33,10 @@ namespace mongo { +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ BSONObj parseHint(const BSONElement& element) { if (element.type() == BSONType::String) { return BSON("$hint" << element.valueStringData()); @@ -44,6 +48,10 @@ BSONObj parseHint(const BSONElement& element) { MONGO_UNREACHABLE; } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeHintToBSON(const BSONObj& hint, StringData fieldName, BSONObjBuilder* builder) { if (hint.isEmpty()) return; diff --git a/src/mongo/db/query/max_time_ms_parser.cpp b/src/mongo/db/query/max_time_ms_parser.cpp index 7f2c84f07ad..054b2b76ead 100644 --- a/src/mongo/db/query/max_time_ms_parser.cpp +++ b/src/mongo/db/query/max_time_ms_parser.cpp @@ -62,6 +62,10 @@ StatusWith<int> parseMaxTimeMS(BSONElement maxTimeMSElt) { return StatusWith<int>(static_cast<int>(maxTimeMSLongLong)); } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ int32_t parseMaxTimeMSForIDL(BSONElement maxTimeMSElt) { return static_cast<int32_t>(uassertStatusOK(parseMaxTimeMS(maxTimeMSElt))); } diff --git a/src/mongo/db/query/max_time_ms_parser.h b/src/mongo/db/query/max_time_ms_parser.h index 1e5ec985c77..d111b480599 100644 --- a/src/mongo/db/query/max_time_ms_parser.h +++ b/src/mongo/db/query/max_time_ms_parser.h @@ -56,6 +56,10 @@ static constexpr auto kMaxTimeMSOpOnlyMaxPadding = 100LL; */ StatusWith<int> parseMaxTimeMS(BSONElement maxTimeMSElt); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ int32_t parseMaxTimeMSForIDL(BSONElement maxTimeMSElt); } // namespace mongo diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp index e60a04ff79e..8518c0e4661 100644 --- a/src/mongo/db/query/query_request_test.cpp +++ b/src/mongo/db/query/query_request_test.cpp @@ -1194,36 +1194,74 @@ TEST(QueryRequestTest, ParseFromCommandForbidExtraOption) { TEST(QueryRequestTest, ParseMaxTimeMSStringValueFails) { BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << "foo"); - ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS])); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); +} + +TEST(QueryRequestTest, ParseMaxTimeMSBoolValueFails) { + BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << true); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); +} + +TEST(QueryRequestTest, ParseMaxTimeMSNullValueFails) { + BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << BSONNULL); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); +} + +TEST(QueryRequestTest, ParseMaxTimeMSUndefinedValueFails) { + BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << BSONUndefined); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); +} + +TEST(QueryRequestTest, ParseMaxTimeMSEmptyObjectValueFails) { + const auto emptyObj = BSONObjBuilder().obj(); + BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << emptyObj); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); } TEST(QueryRequestTest, ParseMaxTimeMSNonIntegralValueFails) { BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 100.3); - ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS])); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); } TEST(QueryRequestTest, ParseMaxTimeMSOutOfRangeDoubleFails) { BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 1e200); - ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS])); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); } TEST(QueryRequestTest, ParseMaxTimeMSNegativeValueFails) { BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << -400); - ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS])); + ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), + DBException, + ErrorCodes::BadValue); } TEST(QueryRequestTest, ParseMaxTimeMSZeroSucceeds) { BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 0); - auto maxTime = parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]); - ASSERT_OK(maxTime); - ASSERT_EQ(maxTime.getValue(), 0); + ASSERT_EQ(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), 0); +} + +TEST(QueryRequestTest, ParseMaxTimeMSEmptyElementSucceeds) { + const auto emptyElem = BSONElement(); + ASSERT_EQ(parseMaxTimeMSForIDL(emptyElem), 0); } TEST(QueryRequestTest, ParseMaxTimeMSPositiveInRangeSucceeds) { BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 300); - auto maxTime = parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]); - ASSERT_OK(maxTime); - ASSERT_EQ(maxTime.getValue(), 300); + ASSERT_EQ(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), 300); } TEST(QueryRequestTest, ConvertToAggregationSucceeds) { diff --git a/src/mongo/idl/basic_types.h b/src/mongo/idl/basic_types.h index c02366d3c5f..62e191a9bf5 100644 --- a/src/mongo/idl/basic_types.h +++ b/src/mongo/idl/basic_types.h @@ -47,6 +47,10 @@ namespace mongo { */ class OptionalBool { public: + /** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ static OptionalBool parseFromBSON(BSONElement element) { uassert(ErrorCodes::TypeMismatch, str::stream() << "Field '" << element.fieldNameStringData() @@ -76,6 +80,9 @@ public: /** * Serialize this object as a field in a document. If _value is empty, omit the field. + * + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. */ void serializeToBSON(StringData fieldName, BSONObjBuilder* builder) const { if (_value) { @@ -85,6 +92,9 @@ public: /** * Serialize this object as an element of a BSON array. If _value is empty, omit the entry. + * + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. */ void serializeToBSON(BSONArrayBuilder* builder) const { if (_value) { @@ -112,6 +122,10 @@ private: */ class IDLAnyType { public: + /** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ static IDLAnyType parseFromBSON(const BSONElement& element) { return IDLAnyType(element); } @@ -119,10 +133,18 @@ public: IDLAnyType() = default; IDLAnyType(const BSONElement& element) : _element(element) {} + /** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeToBSON(StringData fieldName, BSONObjBuilder* builder) const { builder->appendAs(_element, fieldName); } + /** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeToBSON(BSONArrayBuilder* builder) const { builder->append(_element); } @@ -141,6 +163,10 @@ protected: */ class IDLAnyTypeOwned : public IDLAnyType { public: + /** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ static IDLAnyTypeOwned parseFromBSON(const BSONElement& element) { return IDLAnyTypeOwned(element); } diff --git a/src/mongo/idl/idl_parser.cpp b/src/mongo/idl/idl_parser.cpp index 9cad14bffca..de0ffd40852 100644 --- a/src/mongo/idl/idl_parser.cpp +++ b/src/mongo/idl/idl_parser.cpp @@ -341,14 +341,26 @@ std::vector<std::vector<std::uint8_t>> transformVector(const std::vector<ConstDa return output; } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void noOpSerializer(bool, StringData fieldName, BSONObjBuilder* bob) {} +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeBSONWhenNotEmpty(BSONObj obj, StringData fieldName, BSONObjBuilder* bob) { if (!obj.isEmpty()) { bob->append(fieldName, obj); } } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ BSONObj parseOwnedBSON(BSONElement element) { uassert(ErrorCodes::TypeMismatch, str::stream() << "Expected field " << element.fieldNameStringData() @@ -357,6 +369,10 @@ BSONObj parseOwnedBSON(BSONElement element) { return element.Obj().getOwned(); } +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ bool parseBoolean(BSONElement element) { uassert(ErrorCodes::TypeMismatch, str::stream() << "Expected field " << element.fieldNameStringData() diff --git a/src/mongo/idl/idl_parser.h b/src/mongo/idl/idl_parser.h index 47096c0d117..316ccd06c7e 100644 --- a/src/mongo/idl/idl_parser.h +++ b/src/mongo/idl/idl_parser.h @@ -289,12 +289,28 @@ std::vector<std::string> transformVector(const std::vector<StringData>& input); std::vector<ConstDataRange> transformVector(const std::vector<std::vector<std::uint8_t>>& input); std::vector<std::vector<std::uint8_t>> transformVector(const std::vector<ConstDataRange>& input); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void noOpSerializer(bool, StringData fieldName, BSONObjBuilder* bob); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ void serializeBSONWhenNotEmpty(BSONObj obj, StringData fieldName, BSONObjBuilder* bob); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ BSONObj parseOwnedBSON(BSONElement element); +/** + * IMPORTANT: The method should not be modified, as API version input/output guarantees could + * break because of it. + */ bool parseBoolean(BSONElement element); } // namespace mongo |