Mitigate integer overflow in ComputeShrinkHard (#1138)
Some checks failed
Build / Bazel, cl, windows-latest (push) Has been cancelled
Build / Bazel, clang++, macos-latest (push) Has been cancelled
Build / Bazel, clang++, ubuntu-latest (push) Has been cancelled
Build / Bazel, g++, macos-latest (push) Has been cancelled
Build / Bazel, g++, ubuntu-latest (push) Has been cancelled
Build / CMake, cl, windows-latest (push) Has been cancelled
Build / CMake, gcc, ubuntu-latest (push) Has been cancelled
Build / CMake, llvm, ubuntu-latest (push) Has been cancelled
Build / CMake, llvm, macos-latest (push) Has been cancelled
Build / Test modules (llvm, ubuntu-latest) (push) Has been cancelled
Documentation / documentation (push) Has been cancelled

The multiplication in ComputeShrinkHard has the potential to overflow when
very large elements are present inside of a vbox. To mitigate the issue, the
multiplication happens in int64_t values.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
This commit is contained in:
its-pablo
2025-10-19 01:06:46 -07:00
committed by GitHub
parent d4fda16e20
commit 68281ce3e8
2 changed files with 18 additions and 3 deletions

View File

@@ -32,6 +32,9 @@ Next
- Fix vertical `ftxui::Slider`. The "up" key was previously decreasing the - Fix vertical `ftxui::Slider`. The "up" key was previously decreasing the
value. Thanks @its-pablo in #1093 for reporting the issue. value. Thanks @its-pablo in #1093 for reporting the issue.
### Dom
- Fix integer overflow in `ComputeShrinkHard`. Thanks @its-pablo in #1137 for
reporting and fixing the issue.
6.1.9 (2025-05-07) 6.1.9 (2025-05-07)
------------ ------------

View File

@@ -4,6 +4,7 @@
#include "ftxui/dom/box_helper.hpp" #include "ftxui/dom/box_helper.hpp"
#include <algorithm> // for max #include <algorithm> // for max
#include <cstdint>
#include <vector> // for vector #include <vector> // for vector
namespace ftxui::box_helper { namespace ftxui::box_helper {
@@ -40,7 +41,7 @@ void ComputeShrinkEasy(std::vector<Element>* elements,
} }
// Called when the size allowed is lower than the requested size, and the // Called when the size allowed is lower than the requested size, and the
// shrinkable element can not absorbe the (negative) extra_space. This assign // shrinkable element can not absorb the (negative) extra_space. This assigns
// zero to shrinkable elements and distribute the remaining (negative) // zero to shrinkable elements and distribute the remaining (negative)
// extra_space toward the other non shrinkable elements. // extra_space toward the other non shrinkable elements.
void ComputeShrinkHard(std::vector<Element>* elements, void ComputeShrinkHard(std::vector<Element>* elements,
@@ -52,7 +53,18 @@ void ComputeShrinkHard(std::vector<Element>* elements,
continue; continue;
} }
const int added_space = extra_space * element.min_size / std::max(1, size); // Perform operation into int64_t to avoid overflow.
// The size of an int is at most 32 bits, so the multiplication can't
// overflow int64_t. Since `size` is the sum of elements.min_size, it is
// greater than every element.min_size. The added_space represents the
// fraction of extra_space assigned to this element, so it is always less
// than extra_space in absolute. Since extra_space fits into int,
// added_space fits into int as well.
int added_space =
static_cast<int>(static_cast<int64_t>(extra_space) *
static_cast<int64_t>(element.min_size) /
std::max(static_cast<int64_t>(size), 1L));
extra_space -= added_space; extra_space -= added_space;
size -= element.min_size; size -= element.min_size;