summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames Wahlin <james@mongodb.com>2018-09-27 15:57:11 -0400
committerJames Wahlin <james@mongodb.com>2018-10-01 16:41:30 -0400
commit7270505e68837f0e86e1f55b77c317e353d61789 (patch)
treed94cc58f987cef754f95b9a0e9612107da5f4316 /src
parent1c922de9cac97065fb018f5d049566ecba803433 (diff)
downloadmongo-7270505e68837f0e86e1f55b77c317e353d61789.tar.gz
SERVER-37353 Handle $slice value of LLONG_MIN gracefully
(cherry picked from commit 93fe6ccfb37d14f382abdf0e90abd013fbe8af7b)
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/update/push_node.cpp8
-rw-r--r--src/mongo/db/update/push_node_test.cpp8
2 files changed, 12 insertions, 4 deletions
diff --git a/src/mongo/db/update/push_node.cpp b/src/mongo/db/update/push_node.cpp
index ac235e722f9..e625eb722ed 100644
--- a/src/mongo/db/update/push_node.cpp
+++ b/src/mongo/db/update/push_node.cpp
@@ -260,7 +260,13 @@ ModifierNode::ModifyResult PushNode::performPush(mutablebson::Element* element,
sortChildren(*element, *_sort);
}
- while (static_cast<long long>(countChildren(*element)) > std::abs(_slice)) {
+ // std::abs(LLONG_MIN) results in undefined behavior on 2's complement systems because the
+ // absolute value of LLONG_MIN cannot be represented in a 'long long'.
+ const auto sliceAbs = _slice == std::numeric_limits<decltype(_slice)>::min()
+ ? std::abs(_slice + 1)
+ : std::abs(_slice);
+
+ while (static_cast<long long>(countChildren(*element)) > sliceAbs) {
result = ModifyResult::kNormalUpdate;
if (_slice >= 0) {
invariantOK(element->popBack());
diff --git a/src/mongo/db/update/push_node_test.cpp b/src/mongo/db/update/push_node_test.cpp
index 6eefb09bd53..3931bb56c4d 100644
--- a/src/mongo/db/update/push_node_test.cpp
+++ b/src/mongo/db/update/push_node_test.cpp
@@ -655,16 +655,18 @@ void checkDocumentAndResult(BSONObj updateModifier,
TEST_F(PushNodeTest, ApplyToEmptyArrayWithSliceValues) {
struct testData {
- int sliceValue;
+ long long sliceValue;
BSONObj resultingDoc;
};
// We repeat the same test for several different values of $slice.
- std::vector<testData> testDataList{{-2, fromjson("{a: [1]}")},
+ std::vector<testData> testDataList{{LLONG_MIN, fromjson("{a: [1]}")},
+ {-2, fromjson("{a: [1]}")},
{-1, fromjson("{a: [1]}")},
{0, fromjson("{a: []}")},
{1, fromjson("{a: [1]}")},
- {2, fromjson("{a: [1]}")}};
+ {2, fromjson("{a: [1]}")},
+ {LLONG_MAX, fromjson("{a: [1]}")}};
for (const auto& data : testDataList) {
auto update = BSON(