diff --git a/include/libtorrent/bandwidth_limit.hpp b/include/libtorrent/bandwidth_limit.hpp index 0057f4170..18b686d34 100644 --- a/include/libtorrent/bandwidth_limit.hpp +++ b/include/libtorrent/bandwidth_limit.hpp @@ -43,7 +43,7 @@ namespace libtorrent { // member of peer_connection struct TORRENT_EXTRA_EXPORT bandwidth_channel { - static constexpr int inf = std::numeric_limits::max(); + static constexpr int inf = std::numeric_limits::max(); bandwidth_channel(); @@ -51,8 +51,9 @@ struct TORRENT_EXTRA_EXPORT bandwidth_channel void throttle(int limit); int throttle() const { + TORRENT_ASSERT_VAL(m_limit >= 0, m_limit); TORRENT_ASSERT_VAL(m_limit < inf, m_limit); - return int(m_limit); + return m_limit; } int quota_left() const; @@ -92,7 +93,7 @@ private: // the limit is the number of bytes // per second we are allowed to use. - std::int64_t m_limit; + std::int32_t m_limit; }; } diff --git a/src/bandwidth_limit.cpp b/src/bandwidth_limit.cpp index a79752918..f8f923bb6 100644 --- a/src/bandwidth_limit.cpp +++ b/src/bandwidth_limit.cpp @@ -45,9 +45,9 @@ namespace libtorrent { // 0 means infinite void bandwidth_channel::throttle(int limit) { - TORRENT_ASSERT(limit >= 0); + TORRENT_ASSERT_VAL(limit >= 0, limit); // if the throttle is more than this, we might overflow - TORRENT_ASSERT(limit < inf); + TORRENT_ASSERT_VAL(limit < inf, limit); m_limit = limit; } @@ -59,18 +59,26 @@ namespace libtorrent { void bandwidth_channel::update_quota(int dt_milliseconds) { + TORRENT_ASSERT_VAL(m_limit >= 0, m_limit); + TORRENT_ASSERT_VAL(m_limit < inf, m_limit); + if (m_limit == 0) return; - // avoid integer overflow - if (m_limit >= std::numeric_limits::max() / dt_milliseconds) + // "to_add" should never have int64 overflow: "m_limit" contains < "::max" + std::int64_t to_add = (std::int64_t(m_limit) * dt_milliseconds + 500) / 1000; + + if (to_add > inf - m_quota_left) { - m_quota_left = std::numeric_limits::max(); + m_quota_left = inf; } else { - m_quota_left += (m_limit * dt_milliseconds + 500) / 1000; - if (m_quota_left / 3 > m_limit) m_quota_left = m_limit * 3; + m_quota_left += to_add; + if (m_quota_left / 3 > m_limit) m_quota_left = std::int64_t(m_limit) * 3; + // "m_quota_left" will never have int64 overflow but may exceed "::max" + m_quota_left = std::min(m_quota_left, std::int64_t(inf)); } + distribute_quota = int(std::max(m_quota_left, std::int64_t(0))); } diff --git a/test/test_bandwidth_limiter.cpp b/test/test_bandwidth_limiter.cpp index 3a6321fb0..7f6aa033f 100644 --- a/test/test_bandwidth_limiter.cpp +++ b/test/test_bandwidth_limiter.cpp @@ -466,6 +466,7 @@ TORRENT_TEST(equal_connection) test_equal_connections(33, 60000); test_equal_connections(33, 500000); test_equal_connections( 1, 1000000); + test_equal_connections( 1, 6000000); } TORRENT_TEST(conn_var_rate)