diff --git a/include/libtorrent/bandwidth_limit.hpp b/include/libtorrent/bandwidth_limit.hpp index 3c7a3f8fe..259b2a308 100644 --- a/include/libtorrent/bandwidth_limit.hpp +++ b/include/libtorrent/bandwidth_limit.hpp @@ -47,7 +47,7 @@ namespace libtorrent { // member of peer_connection struct TORRENT_EXTRA_EXPORT bandwidth_channel { - static const int inf = boost::integer_traits::const_max; + static boost::int32_t const inf = boost::integer_traits::const_max; bandwidth_channel(); @@ -55,8 +55,9 @@ struct TORRENT_EXTRA_EXPORT bandwidth_channel void throttle(int limit); int throttle() const { - TORRENT_ASSERT_VAL(m_limit < INT_MAX, m_limit); - return int(m_limit); + TORRENT_ASSERT_VAL(m_limit >= 0, m_limit); + TORRENT_ASSERT_VAL(m_limit < inf, m_limit); + return m_limit; } int quota_left() const; @@ -96,10 +97,9 @@ private: // the limit is the number of bytes // per second we are allowed to use. - boost::int64_t m_limit; + boost::int32_t m_limit; }; } #endif - diff --git a/src/bandwidth_limit.cpp b/src/bandwidth_limit.cpp index 01d6f7f6b..866138765 100644 --- a/src/bandwidth_limit.cpp +++ b/src/bandwidth_limit.cpp @@ -33,8 +33,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bandwidth_limit.hpp" #include -namespace libtorrent -{ +namespace libtorrent { + bandwidth_channel::bandwidth_channel() : tmp(0) , distribute_quota(0) @@ -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 < INT_MAX); + TORRENT_ASSERT_VAL(limit < inf, limit); m_limit = limit; } @@ -59,19 +59,27 @@ 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" + boost::int64_t to_add = (boost::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 = boost::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, boost::int64_t(inf)); } - distribute_quota = int((std::max)(m_quota_left, boost::int64_t(0))); + + distribute_quota = int(std::max(m_quota_left, boost::int64_t(0))); } // this is used when connections disconnect with diff --git a/test/test_bandwidth_limiter.cpp b/test/test_bandwidth_limiter.cpp index 4d9763163..a7f4b6eaa 100644 --- a/test/test_bandwidth_limiter.cpp +++ b/test/test_bandwidth_limiter.cpp @@ -467,6 +467,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)