[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.
This commit is contained in:
Abtin Keshavarzian
2025-12-03 12:39:40 -08:00
committed by GitHub
parent 97598f88e8
commit 3335928a5d
2 changed files with 19 additions and 1 deletions
+18 -1
View File
@@ -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<uint16_t>(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<uint16_t>::kMax);
VerifyOrExit(aSize <= NumericLimits<uint16_t>::kMax);
totalSize = aCount * aSize;
VerifyOrExit(totalSize <= NumericLimits<uint16_t>::kMax - kTotalSizeGuard);
size = static_cast<uint16_t>(totalSize);
VerifyOrExit(size);
+1
View File
@@ -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!");