diff options
-rw-r--r-- | src/mongo/db/update/arithmetic_node.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/update/arithmetic_node_test.cpp | 17 |
2 files changed, 29 insertions, 6 deletions
diff --git a/src/mongo/db/update/arithmetic_node.cpp b/src/mongo/db/update/arithmetic_node.cpp index 49dfc9165e6..c5b7a3373f7 100644 --- a/src/mongo/db/update/arithmetic_node.cpp +++ b/src/mongo/db/update/arithmetic_node.cpp @@ -76,12 +76,11 @@ Status ArithmeticNode::init(BSONElement modExpr, const CollatorInterface* collat ModifierNode::ModifyResult ArithmeticNode::updateExistingElement( mutablebson::Element* element, std::shared_ptr<FieldRef> elementPath) const { if (!element->isNumeric()) { - mutablebson::Element idElem = - mutablebson::findFirstChildNamed(element->getDocument().root(), "_id"); + auto idElem = mutablebson::findFirstChildNamed(element->getDocument().root(), "_id"); uasserted(ErrorCodes::TypeMismatch, str::stream() << "Cannot apply " << getModifierNameForOp(_op) << " to a value of non-numeric type. {" - << idElem.toString() + << (idElem.ok() ? idElem.toString() : "no id") << "} has the field '" << element->getFieldName() << "' of non-numeric type " @@ -103,10 +102,17 @@ ModifierNode::ModifyResult ArithmeticNode::updateExistingElement( // if the found element is in a deserialized state, we can't do that. if (element->getValue().ok() && valueToSet.isIdentical(originalValue)) { return ModifyResult::kNoOp; + } else if (!valueToSet.isValid()) { + auto idElem = mutablebson::findFirstChildNamed(element->getDocument().root(), "_id"); + uasserted(ErrorCodes::BadValue, + str::stream() << "Failed to apply " << getModifierNameForOp(_op) + << " operations to current value (" + << originalValue.debugString() + << ") for document {" + << (idElem.ok() ? idElem.toString() : "no id") + << "}"); } else { - - // This can fail if 'valueToSet' is not representable as a 64-bit integer. - uassertStatusOK(element->setValueSafeNum(valueToSet)); + invariantOK(element->setValueSafeNum(valueToSet)); return ModifyResult::kNormalUpdate; } } diff --git a/src/mongo/db/update/arithmetic_node_test.cpp b/src/mongo/db/update/arithmetic_node_test.cpp index a0a74654ac0..105f2019057 100644 --- a/src/mongo/db/update/arithmetic_node_test.cpp +++ b/src/mongo/db/update/arithmetic_node_test.cpp @@ -590,6 +590,23 @@ TEST_F(ArithmeticNodeTest, ApplyIncToStringFails) { "\"test_object\"} has the field 'a' of non-numeric type string"); } +TEST_F(ArithmeticNodeTest, OverflowingOperationFails) { + auto update = fromjson("{$mul: {a: 2}}"); + const CollatorInterface* collator = nullptr; + ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); + ASSERT_OK(node.init(update["$mul"]["a"], collator)); + + mutablebson::Document doc(fromjson("{_id: 'test_object', a: NumberLong(9223372036854775807)}")); + setPathTaken("a"); + addIndexedPath("a"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), + AssertionException, + ErrorCodes::BadValue, + "Failed to apply $mul operations to current value " + "((NumberLong)9223372036854775807) for document {_id: " + "\"test_object\"}"); +} + TEST_F(ArithmeticNodeTest, ApplyNewPath) { auto update = fromjson("{$inc: {a: 2}}"); const CollatorInterface* collator = nullptr; |