@@ -508,32 +508,55 @@ void PacketBuffer::AddRef()
508
508
509
509
PacketBufferHandle PacketBufferHandle::New (size_t aAvailableSize, uint16_t aReservedSize)
510
510
{
511
- // Adding three 16-bit-int sized numbers together will never overflow
512
- // assuming int is at least 32 bits.
511
+ // Ensure that SIZE_MAX is at least 32 bits
513
512
static_assert (INT_MAX >= INT32_MAX, " int is not big enough" );
513
+ static_assert (SIZE_MAX >= INT_MAX, " Our additions may not fit in size_t" );
514
+
515
+ // Sanity check for kStructureSize and putting an upper bound.
514
516
static_assert (PacketBuffer::kStructureSize == sizeof (PacketBuffer), " PacketBuffer size mismatch" );
515
- static_assert (PacketBuffer::kStructureSize < UINT16_MAX, " Check for overflow more carefully" );
516
- static_assert (SIZE_MAX >= INT_MAX, " Our additions might not fit in size_t" );
517
- static_assert (PacketBuffer::kMaxSizeWithoutReserve <= UINT32_MAX, " PacketBuffer may have size not fitting uint32_t" );
517
+ static_assert (PacketBuffer::kStructureSize < UINT16_MAX, " kStructureSize should not exceed UINT16_MAX" );
518
+ static_assert (PacketBuffer::kMaxSizeWithoutReserve <= UINT16_MAX, " PacketBuffer may have size not fitting uint16_t" );
519
+
520
+ // Have a bounds check for aAvailableSize to ensure that
521
+ // the next overflow check is done correctly.
522
+ if (aAvailableSize > UINT32_MAX)
523
+ {
524
+ ChipLogError (chipSystemLayer, " PacketBuffer: AvailableSize of a buffer cannot exceed UINT32_MAX" );
525
+ return PacketBufferHandle ();
526
+ }
527
+
528
+ // Cast all to uint64_t and add to consider the widest possible result.
529
+ uint64_t sumOfSizes = static_cast <uint64_t >(aAvailableSize) + static_cast <uint64_t >(aReservedSize) +
530
+ static_cast <uint64_t >(PacketBuffer::kStructureSize );
531
+ uint64_t sumOfAvailAndReserved = static_cast <uint64_t >(aAvailableSize) + static_cast <uint64_t >(aReservedSize);
532
+
533
+ // Ensure that the sum does not overflow a size_t whose max value is at
534
+ // least INT_MAX.
535
+ if (sumOfSizes > std::numeric_limits<size_t >::max ())
536
+ {
537
+ ChipLogError (chipSystemLayer, " PacketBuffer: Sizes of allocation request are invalid" );
538
+ return PacketBufferHandle ();
539
+ }
540
+
541
+
518
542
#if CHIP_SYSTEM_CONFIG_USE_LWIP
519
543
// LwIP based APIs have a maximum buffer size of UINT16_MAX. Ensure that
520
544
// limit is met during allocation.
521
- VerifyOrDieWithMsg (aAvailableSize + aReservedSize < UINT16_MAX, chipSystemLayer,
545
+ VerifyOrDieWithMsg (sumOfAvailAndReserved < UINT16_MAX, chipSystemLayer,
522
546
" LwIP based systems can handle only up to UINT16_MAX!" );
523
547
#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
524
548
525
- // When `aAvailableSize` fits in uint16_t (as tested below) and size_t is at least 32 bits (as asserted above),
526
- // these additions will not overflow.
527
- const size_t lAllocSize = aReservedSize + aAvailableSize ;
549
+ // The above check against the size_t limit ensures that the below sum will not
550
+ // overflow.
551
+ const size_t lAllocSize = static_cast < size_t >(sumOfAvailAndReserved) ;
528
552
const size_t lBlockSize = PacketBuffer::kStructureSize + lAllocSize;
529
553
PacketBuffer * lPacket;
530
554
531
555
CHIP_SYSTEM_FAULT_INJECT (FaultInjection::kFault_PacketBufferNew , return PacketBufferHandle ());
532
556
533
- // TODO: Change the max to a lower value
534
- if (aAvailableSize > UINT32_MAX || lAllocSize > PacketBuffer::kMaxSizeWithoutReserve || lBlockSize > UINT32_MAX)
557
+ if (lAllocSize > PacketBuffer::kMaxSizeWithoutReserve )
535
558
{
536
- ChipLogError (chipSystemLayer, " PacketBuffer: allocation too large ." );
559
+ ChipLogError (chipSystemLayer, " PacketBuffer: allocation exceeding buffer capacity limits ." );
537
560
return PacketBufferHandle ();
538
561
}
539
562
0 commit comments