summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2016-02-17 19:16:59 -0500
committerJason Carey <jcarey@argv.me>2016-03-03 13:07:12 -0500
commit9778d0678715fc3f9b9f725cfd11ea85ce03b2fc (patch)
tree038d07f50634c208b9fe3187d2cb87169f609bd9 /src/mongo
parent8f451aa7e402b815f77db259611291744184e65c (diff)
downloadmongo-9778d0678715fc3f9b9f725cfd11ea85ce03b2fc.tar.gz
SERVER-22710 Fix UB in ASIO timeout durations
std::chrono types can naturally signed integer overflow if you accidentally pass a large duration in lower granularity (std::chrono::milliseconds::max()) to a higher granularity constructor (std::chrono::nanoseconds). We have to clamp our casts to ensure that we don't wrap around to negative values.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/executor/connection_pool_asio.cpp4
-rw-r--r--src/mongo/executor/connection_pool_asio.h2
-rw-r--r--src/mongo/executor/network_interface_asio.cpp5
3 files changed, 9 insertions, 2 deletions
diff --git a/src/mongo/executor/connection_pool_asio.cpp b/src/mongo/executor/connection_pool_asio.cpp
index b2344b54ffa..82e4264d997 100644
--- a/src/mongo/executor/connection_pool_asio.cpp
+++ b/src/mongo/executor/connection_pool_asio.cpp
@@ -52,12 +52,14 @@ ASIOTimer::~ASIOTimer() {
++_callbackSharedState->id;
}
+const auto kMaxTimerDuration = duration_cast<Milliseconds>(ASIOTimer::clock_type::duration::max());
+
void ASIOTimer::setTimeout(Milliseconds timeout, TimeoutCallback cb) {
_strand->dispatch([this, timeout, cb] {
_cb = std::move(cb);
cancelTimeout();
- _impl.expires_after(timeout);
+ _impl.expires_after(std::min(kMaxTimerDuration, timeout));
decltype(_callbackSharedState->id) id;
decltype(_callbackSharedState) sharedState;
diff --git a/src/mongo/executor/connection_pool_asio.h b/src/mongo/executor/connection_pool_asio.h
index 20b728e542e..55e0f9d34fc 100644
--- a/src/mongo/executor/connection_pool_asio.h
+++ b/src/mongo/executor/connection_pool_asio.h
@@ -44,6 +44,8 @@ namespace connection_pool_asio {
*/
class ASIOTimer final : public ConnectionPool::TimerInterface {
public:
+ using clock_type = asio::steady_timer::clock_type;
+
ASIOTimer(asio::io_service::strand* strand);
~ASIOTimer();
diff --git a/src/mongo/executor/network_interface_asio.cpp b/src/mongo/executor/network_interface_asio.cpp
index 2324482279d..7da182d2073 100644
--- a/src/mongo/executor/network_interface_asio.cpp
+++ b/src/mongo/executor/network_interface_asio.cpp
@@ -379,9 +379,12 @@ void NetworkInterfaceASIO::cancelAllCommands() {
}
}
+const auto kMaxTimerDuration = duration_cast<Milliseconds>(asio::steady_timer::duration::max());
+
void NetworkInterfaceASIO::setAlarm(Date_t when, const stdx::function<void()>& action) {
// "alarm" must stay alive until it expires, hence the shared_ptr.
- auto alarm = std::make_shared<asio::steady_timer>(_io_service, when - now());
+ auto alarm = std::make_shared<asio::steady_timer>(_io_service,
+ std::min(when - now(), kMaxTimerDuration));
alarm->async_wait([alarm, this, action](std::error_code ec) {
if (!ec) {
return action();