summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/update/arithmetic_node.cpp18
-rw-r--r--src/mongo/db/update/arithmetic_node_test.cpp17
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;