-
Type: Bug
-
Resolution: Unresolved
-
Priority: Minor - P4
-
None
-
Affects Version/s: None
-
Component/s: None
-
Query Optimization
-
ALL
When used to parse a field with the name maxTimeMSOpOnly, parseMaxTimeMS increases the max permitted value beyond INT_MAX.
However, the returned value is of type int - the result will be narrowed long long -> int.
StatusWith<int> parseMaxTimeMS(BSONElement maxTimeMSElt) { ... const long long maxVal = maxTimeMSElt.fieldNameStringData() == kMaxTimeMSOpOnlyField ? (long long)(INT_MAX) + kMaxTimeMSOpOnlyMaxPadding : INT_MAX; ... if (maxTimeMSLongLong < 0 || maxTimeMSLongLong > maxVal) return Status(ErrorCodes::BadValue, ...); .. return StatusWith<int>(static_cast<int>(maxTimeMSLongLong)); }
The justification for this leeway:
src/mongo/db/query/max_time_ms_parser.h
// A constant by which 'maxTimeMSOpOnly' values are allowed to exceed the max allowed value for // 'maxTimeMS'. This is because mongod and mongos server processes add a small amount to the // 'maxTimeMS' value they are given before passing it on as 'maxTimeMSOpOnly', to allow for // clock precision. static constexpr auto kMaxTimeMSOpOnlyMaxPadding = 100LL;
Given this, if maxTimeMS is provided INT_MAX, any maxTimeMSOpOnly derived from increasing this value slightly will be parsed as a very negative int value.
The only use of this method on a field named maxTimeMSOpOnly identified so far is:
src/mongo/db/service_entry_point_common.cpp
void ExecCommandDatabase::_initiateCommand() { ... const auto maxTimeMS = Milliseconds{uassertStatusOK(parseMaxTimeMS(cmdOptionMaxTimeMSField))}; const auto maxTimeMSOpOnly = Milliseconds{uassertStatusOK(parseMaxTimeMS(maxTimeMSOpOnlyField))}; if ((maxTimeMS > Milliseconds::zero() || maxTimeMSOpOnly > Milliseconds::zero()) && command->getLogicalOp() != LogicalOp::opGetMore) { ... if (!ignoreMaxTimeMSOpOnly && maxTimeMSOpOnly > Milliseconds::zero() && (maxTimeMS == Milliseconds::zero() || maxTimeMSOpOnly < maxTimeMS)) { opCtx->storeMaxTimeMS(maxTimeMS); opCtx->setDeadlineByDate(startedCommandExecAt + maxTimeMSOpOnly, ErrorCodes::MaxTimeMSExpired); } else if (maxTimeMS > Milliseconds::zero()) { opCtx->setDeadlineByDate(startedCommandExecAt + maxTimeMS, ErrorCodes::MaxTimeMSExpired); } }
This compares > 0, so may treat this situation as if maxTimeMSOpOnly were 0 or unset.
Given INT_MAX milliseconds is around 25 days, it's possible this has no real-world impact.