diff options
author | James Wahlin <james@mongodb.com> | 2018-09-27 15:57:11 -0400 |
---|---|---|
committer | James Wahlin <james@mongodb.com> | 2018-10-01 16:41:30 -0400 |
commit | 7270505e68837f0e86e1f55b77c317e353d61789 (patch) | |
tree | d94cc58f987cef754f95b9a0e9612107da5f4316 /src | |
parent | 1c922de9cac97065fb018f5d049566ecba803433 (diff) | |
download | mongo-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.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/update/push_node_test.cpp | 8 |
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( |