From 3c6929b025ad8080f6833ac17f4e9ffed8847cc9 Mon Sep 17 00:00:00 2001 From: Mitchell Dorrell Date: Fri, 26 May 2023 01:26:21 -0400 Subject: [PATCH] Fix integer overflows in btop_collect.cpp Correct data types in calls to std::accumulate(). The "bandwidth" deques have type "long long", so the initial value of the accumulator (0) must also be "long long" (i.e., "0ll") to prevent integer overflows. Also, since since the bandwidth deques are (signed) "long long", the avg_speed should presumably be a signed "long long" instead of an unsigned "uint64_t". The previous behavior was for large bandwidth values to overflow the accumulator, resulting in a negative total, which then was cast to be a huge "uint64_t" value. As a consequence, the network graph autoscaling was broken for large bandwidths. --- src/freebsd/btop_collect.cpp | 4 ++-- src/linux/btop_collect.cpp | 6 +++--- src/osx/btop_collect.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 2b92ba3..507f62c 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -986,8 +986,8 @@ namespace Net { for (const auto &dir : {"download", "upload"}) { for (const auto &sel : {0, 1}) { if (rescale or max_count[dir][sel] >= 5) { - const uint64_t avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 - ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0) / 5 + const long long avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 + ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0ll) / 5 : net[selected_iface].stat[dir].speed); graph_max[dir] = max(uint64_t(avg_speed * (sel == 0 ? 1.3 : 3.0)), (uint64_t)10 << 10); max_count[dir][0] = max_count[dir][1] = 0; diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 8be5dc7..9a26b6e 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -733,7 +733,7 @@ namespace Cpu { if (times.size() < 4) throw std::runtime_error("Malformatted /proc/stat"); //? Subtract fields 8-9 and any future unknown fields - const long long totals = max(0ll, total_sum - (times.size() > 8 ? std::accumulate(times.begin() + 8, times.end(), 0) : 0)); + const long long totals = max(0ll, total_sum - (times.size() > 8 ? std::accumulate(times.begin() + 8, times.end(), 0ll) : 0)); //? Add iowait field if present const long long idles = max(0ll, times.at(3) + (times.size() > 4 ? times.at(4) : 0)); @@ -1543,8 +1543,8 @@ namespace Net { for (const auto& dir: {"download", "upload"}) { for (const auto& sel : {0, 1}) { if (rescale or max_count[dir][sel] >= 5) { - const uint64_t avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 - ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0) / 5 + const long long avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 + ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0ll) / 5 : net[selected_iface].stat[dir].speed); graph_max[dir] = max(uint64_t(avg_speed * (sel == 0 ? 1.3 : 3.0)), (uint64_t)10 << 10); max_count[dir][0] = max_count[dir][1] = 0; diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index 08e80d0..05fd292 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -1026,8 +1026,8 @@ namespace Net { for (const auto &dir : {"download", "upload"}) { for (const auto &sel : {0, 1}) { if (rescale or max_count[dir][sel] >= 5) { - const uint64_t avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 - ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0) / 5 + const long long avg_speed = (net[selected_iface].bandwidth[dir].size() > 5 + ? std::accumulate(net.at(selected_iface).bandwidth.at(dir).rbegin(), net.at(selected_iface).bandwidth.at(dir).rbegin() + 5, 0ll) / 5 : net[selected_iface].stat[dir].speed); graph_max[dir] = max(uint64_t(avg_speed * (sel == 0 ? 1.3 : 3.0)), (uint64_t)10 << 10); max_count[dir][0] = max_count[dir][1] = 0;