diff options
author | Jason Carey <jcarey@argv.me> | 2016-02-17 19:16:59 -0500 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2016-03-03 13:07:12 -0500 |
commit | 9778d0678715fc3f9b9f725cfd11ea85ce03b2fc (patch) | |
tree | 038d07f50634c208b9fe3187d2cb87169f609bd9 /src/mongo | |
parent | 8f451aa7e402b815f77db259611291744184e65c (diff) | |
download | mongo-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.cpp | 4 | ||||
-rw-r--r-- | src/mongo/executor/connection_pool_asio.h | 2 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_asio.cpp | 5 |
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(); |