summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2016-01-19 15:03:06 -0500
committerDavid Storch <david.storch@10gen.com>2016-01-21 15:11:38 -0500
commitabafc33866c53f6339e2f30f11077a692d64c709 (patch)
tree06eefb31d37e47b5124f1db8f9dda97967351ff8 /src/mongo
parentee050e4700001d0f9ebf8aa388c57307ff405574 (diff)
downloadmongo-abafc33866c53f6339e2f30f11077a692d64c709.tar.gz
SERVER-20808 reject negative ntoreturn on OP_GET_MORE messages
Also makes negative ntoreturn an error on a tailable cursor, which was previously the only known edge case in which the shell could send a negative ntoreturn with a getMore.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/instance.cpp2
-rw-r--r--src/mongo/db/query/find.cpp2
-rw-r--r--src/mongo/db/query/lite_parsed_query.cpp8
-rw-r--r--src/mongo/db/query/lite_parsed_query_test.cpp11
-rw-r--r--src/mongo/s/strategy.cpp4
5 files changed, 25 insertions, 2 deletions
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index e1cd9230d24..921f507ab00 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -878,6 +878,8 @@ bool receivedGetMore(OperationContext* txn, DbResponse& dbresponse, Message& m,
const char* ns = d.getns();
int ntoreturn = d.pullInt();
+ uassert(
+ 34368, str::stream() << "Invalid ntoreturn for OP_GET_MORE: " << ntoreturn, ntoreturn >= 0);
long long cursorid = d.pullInt64();
curop.debug().ntoreturn = ntoreturn;
diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp
index 89c356a3fe8..a56a282817a 100644
--- a/src/mongo/db/query/find.cpp
+++ b/src/mongo/db/query/find.cpp
@@ -252,6 +252,8 @@ QueryResult::View getMore(OperationContext* txn,
long long cursorid,
bool* exhaust,
bool* isCursorAuthorized) {
+ invariant(ntoreturn >= 0);
+
CurOp& curop = *CurOp::get(txn);
// For testing, we may want to fail if we receive a getmore.
diff --git a/src/mongo/db/query/lite_parsed_query.cpp b/src/mongo/db/query/lite_parsed_query.cpp
index a4f9696b7a0..672d143c22f 100644
--- a/src/mongo/db/query/lite_parsed_query.cpp
+++ b/src/mongo/db/query/lite_parsed_query.cpp
@@ -653,13 +653,19 @@ Status LiteParsedQuery::validate() const {
"'limit' or 'batchSize' fields can not be set with 'ntoreturn' field.");
}
- // Tailable cursors cannot have any sort other than {$natural: 1}.
if (_tailable) {
+ // Tailable cursors cannot have any sort other than {$natural: 1}.
const BSONObj expectedSort = BSON("$natural" << 1);
if (!_sort.isEmpty() && _sort != expectedSort) {
return Status(ErrorCodes::BadValue,
"cannot use tailable option with a sort other than {$natural: 1}");
}
+
+ // Cannot indicate that you want a 'singleBatch' if the cursor is tailable.
+ if (!_wantMore) {
+ return Status(ErrorCodes::BadValue,
+ "cannot use tailable option with the 'singleBatch' option");
+ }
}
return Status::OK();
diff --git a/src/mongo/db/query/lite_parsed_query_test.cpp b/src/mongo/db/query/lite_parsed_query_test.cpp
index d2c1cd92842..4ae2f3096b9 100644
--- a/src/mongo/db/query/lite_parsed_query_test.cpp
+++ b/src/mongo/db/query/lite_parsed_query_test.cpp
@@ -188,6 +188,17 @@ TEST(LiteParsedQueryTest, ForbidTailableWithNonNaturalSort) {
ASSERT_NOT_OK(result.getStatus());
}
+TEST(LiteParsedQueryTest, ForbidTailableWithSingleBatch) {
+ BSONObj cmdObj = fromjson(
+ "{find: 'testns',"
+ "tailable: true,"
+ "singleBatch: true}");
+ const NamespaceString nss("test.testns");
+ bool isExplain = false;
+ auto result = LiteParsedQuery::makeFromFindCommand(nss, cmdObj, isExplain);
+ ASSERT_NOT_OK(result.getStatus());
+}
+
TEST(LiteParsedQueryTest, AllowTailableWithNaturalSort) {
BSONObj cmdObj = fromjson(
"{find: 'testns',"
diff --git a/src/mongo/s/strategy.cpp b/src/mongo/s/strategy.cpp
index 84fb002839c..409c6ad827d 100644
--- a/src/mongo/s/strategy.cpp
+++ b/src/mongo/s/strategy.cpp
@@ -339,6 +339,8 @@ void Strategy::commandOp(OperationContext* txn,
void Strategy::getMore(OperationContext* txn, Request& request) {
const char* ns = request.getns();
const int ntoreturn = request.d().pullInt();
+ uassert(
+ 34369, str::stream() << "Invalid ntoreturn for OP_GET_MORE: " << ntoreturn, ntoreturn >= 0);
const long long id = request.d().pullInt64();
// TODO: Handle stale config exceptions here from coll being dropped or sharded during op for
@@ -354,7 +356,7 @@ void Strategy::getMore(OperationContext* txn, Request& request) {
boost::optional<long long> batchSize;
if (ntoreturn) {
- batchSize = abs(ntoreturn);
+ batchSize = ntoreturn;
}
GetMoreRequest getMoreRequest(
NamespaceString(ns), id, batchSize, boost::none, boost::none, boost::none);