[message] check for potential integer overflows (#11834)

This commit adds checks to prevent potential integer overflow issues
within the `Message` class.

Previously, calculations involving message offset and length, such as
`offset + length`, assumed the caller would provide values within a
safe range. However, in some edge cases where larger values are
given, this addition could wrap around. This could lead to incorrect
behavior, potential memory corruption, or assertion failures.

To address this, this change introduces a new generic utility
function, `CanAddSafely()`, to detect unsigned integer addition
overflows. This check is now applied in the following `Message`
methods to validate lengths and offsets before performing
arithmetic:

- `AppendBytes()`: Returns an error if `offset + length` overflows.
- `AppendBytesFromMessage()`: Returns an error on overflow.
- `GetFirstChunk()`: Safely clamps the read length to the available
  message length.
- `WriteBytes()`: Asserts if `offset + length` overflows.

Unit tests for the new `CanAddSafely()` utility are included, covering
`uint8_t` and `uint16_t` cases.
This commit is contained in:
Abtin Keshavarzian
2025-08-20 22:22:39 -07:00
committed by GitHub
parent 364bbf5e49
commit 968dbb2a04
3 changed files with 61 additions and 7 deletions
+25
View File
@@ -110,6 +110,31 @@ void TestNumUtils(void)
u32 = 0xfff0000;
VerifyOrQuit(ClampToUint16(u32) == 0xffff);
VerifyOrQuit(CanAddSafely<uint8_t>(0, 0));
VerifyOrQuit(CanAddSafely<uint8_t>(100, 0));
VerifyOrQuit(CanAddSafely<uint8_t>(0, 100));
VerifyOrQuit(CanAddSafely<uint8_t>(200, 55));
VerifyOrQuit(CanAddSafely<uint8_t>(56, 199));
VerifyOrQuit(CanAddSafely<uint8_t>(127, 127));
VerifyOrQuit(!CanAddSafely<uint8_t>(200, 56));
VerifyOrQuit(!CanAddSafely<uint8_t>(100, 156));
VerifyOrQuit(!CanAddSafely<uint8_t>(1, 255));
VerifyOrQuit(!CanAddSafely<uint8_t>(255, 1));
VerifyOrQuit(!CanAddSafely<uint8_t>(255, 255));
VerifyOrQuit(!CanAddSafely<uint8_t>(128, 128));
VerifyOrQuit(CanAddSafely<uint16_t>(0, 0));
VerifyOrQuit(CanAddSafely<uint16_t>(0xffff, 0));
VerifyOrQuit(CanAddSafely<uint16_t>(0, 0xffff));
VerifyOrQuit(CanAddSafely<uint16_t>(0xff00, 0xff));
VerifyOrQuit(CanAddSafely<uint16_t>(0xfff, 0xf000));
VerifyOrQuit(!CanAddSafely<uint16_t>(0xffff, 1));
VerifyOrQuit(!CanAddSafely<uint16_t>(1, 0xffff));
VerifyOrQuit(!CanAddSafely<uint16_t>(65000, 65000));
VerifyOrQuit(!CanAddSafely<uint16_t>(32768, 32768));
VerifyOrQuit(IsValueInRange<uint8_t>(5, 5, 10));
VerifyOrQuit(IsValueInRange<uint8_t>(7, 5, 10));
VerifyOrQuit(IsValueInRange<uint8_t>(10, 5, 10));