From 3335928a5dfd859ac9f45e58f761ffad006c0d0b Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 3 Dec 2025 12:39:40 -0800 Subject: [PATCH] [utils] detect and handle overflow in `Heap::CAlloc()` (#12192) This commit fixes an issue with `Utils::Heap::CAlloc()` method. This method performs a multiplication of `aCount` and `aSize` input and then casts the result to `uint16_t`. This commit adds a check to ensure that this conversion does not result in an integer overflow, which would cause the size to warp to an unexpected smaller value. --- src/core/utils/heap.cpp | 19 ++++++++++++++++++- src/core/utils/heap.hpp | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/core/utils/heap.cpp b/src/core/utils/heap.cpp index 7b3ee43ee..6489783dd 100644 --- a/src/core/utils/heap.cpp +++ b/src/core/utils/heap.cpp @@ -39,6 +39,7 @@ #include "common/code_utils.hpp" #include "common/debug.hpp" +#include "common/numeric_limits.hpp" namespace ot { namespace Utils { @@ -65,7 +66,23 @@ void *Heap::CAlloc(size_t aCount, size_t aSize) void *ret = nullptr; Block *prev = nullptr; Block *curr = nullptr; - uint16_t size = static_cast(aCount * aSize); + size_t totalSize; + uint16_t size; + + // Verify that the requested allocation size will not cause an overflow. + // + // The total size is checked to be small enough to fit in a `uint16_t` + // after accounting for internal overhead. `kTotalSizeGuard` provides a + // guard for alignment adjustments and block metadata, preventing the final + // calculated `size` from overflowing `uint16_t`. + + VerifyOrExit(aCount <= NumericLimits::kMax); + VerifyOrExit(aSize <= NumericLimits::kMax); + + totalSize = aCount * aSize; + VerifyOrExit(totalSize <= NumericLimits::kMax - kTotalSizeGuard); + + size = static_cast(totalSize); VerifyOrExit(size); diff --git a/src/core/utils/heap.hpp b/src/core/utils/heap.hpp index 415a4c0d6..484362dc3 100644 --- a/src/core/utils/heap.hpp +++ b/src/core/utils/heap.hpp @@ -223,6 +223,7 @@ private: static constexpr uint16_t kSuperBlockOffset = kAlignSize - sizeof(uint16_t); static constexpr uint16_t kFirstBlockOffset = kAlignSize * 2 - sizeof(uint16_t); static constexpr uint16_t kGuardBlockOffset = kMemorySize - sizeof(uint16_t); + static constexpr uint16_t kTotalSizeGuard = kAlignSize + sizeof(Block); static_assert(kMemorySize % kAlignSize == 0, "The heap memory size is not aligned to kAlignSize!");