@@ -508,45 +508,70 @@ 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 ensure that the constant sizes are not going to lead
516
+ // to overflow.
514
517
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" );
518
+ static_assert (PacketBuffer::kStructureSize <= UINT16_MAX, " kStructureSize should not exceed UINT16_MAX." );
519
+ static_assert (PacketBuffer::kMaxSizeWithoutReserve <= UINT16_MAX, " kMaxSizeWithoutReserve should not exceed UINT16_MAX." );
520
+
521
+ // Ensure that aAvailableSize is not big enough to cause overflow.
522
+ if (aAvailableSize > UINT32_MAX)
523
+ {
524
+ ChipLogError (chipSystemLayer, " PacketBuffer: AvailableSize of a buffer cannot exceed UINT32_MAX. aAvailableSize = %" PRIu64,
525
+ static_cast <uint64_t >(aAvailableSize));
526
+ return PacketBufferHandle ();
527
+ }
528
+
529
+ // Cast all to uint64_t and add. This cannot overflow because we have
530
+ // ensured that the maximal value of the summation is
531
+ // UINT32_MAX + UINT16_MAX + UINT16_MAX, which should always fit in
532
+ // a uint64_t variable.
533
+ uint64_t sumOfSizes = static_cast <uint64_t >(aAvailableSize) + static_cast <uint64_t >(aReservedSize) +
534
+ static_cast <uint64_t >(PacketBuffer::kStructureSize );
535
+ uint64_t sumOfAvailAndReserved = static_cast <uint64_t >(aAvailableSize) + static_cast <uint64_t >(aReservedSize);
536
+
537
+ // Ensure that the sum does not overflow a size_t whose max value is at
538
+ // least INT_MAX.
539
+ if (!CanCastTo<size_t >(sumOfSizes))
540
+ {
541
+ ChipLogError (chipSystemLayer, " PacketBuffer: Sizes of allocation request are invalid. (aAvailableSize = %" PRIu64 " , aReservedSize = %" PRIu64 " )" ,
542
+ static_cast <uint64_t >(aAvailableSize), static_cast <uint64_t >(aReservedSize));
543
+ return PacketBufferHandle ();
544
+ }
545
+
518
546
#if CHIP_SYSTEM_CONFIG_USE_LWIP
519
547
// LwIP based APIs have a maximum buffer size of UINT16_MAX. Ensure that
520
548
// limit is met during allocation.
521
- VerifyOrDieWithMsg (aAvailableSize + aReservedSize < UINT16_MAX, chipSystemLayer,
522
- " LwIP based systems can handle only up to UINT16_MAX!" );
549
+ VerifyOrDieWithMsg (sumOfAvailAndReserved < UINT16_MAX, chipSystemLayer, " LwIP based systems can handle only up to UINT16_MAX!" );
523
550
#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
524
551
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;
528
- const size_t lBlockSize = PacketBuffer::kStructureSize + lAllocSize;
552
+ // sumOfAvailAndReserved is no larger than sumOfSizes, which we checked can be cast to
553
+ // size_t.
554
+ const size_t lAllocSize = static_cast <size_t >(sumOfAvailAndReserved);
529
555
PacketBuffer * lPacket;
530
556
531
557
CHIP_SYSTEM_FAULT_INJECT (FaultInjection::kFault_PacketBufferNew , return PacketBufferHandle ());
532
558
533
- // TODO: Change the max to a lower value
534
- if (aAvailableSize > UINT32_MAX || lAllocSize > PacketBuffer::kMaxSizeWithoutReserve || lBlockSize > UINT32_MAX)
559
+ if (lAllocSize > PacketBuffer::kMaxSizeWithoutReserve )
535
560
{
536
- ChipLogError (chipSystemLayer, " PacketBuffer: allocation too large ." );
561
+ ChipLogError (chipSystemLayer, " PacketBuffer: allocation exceeding buffer capacity limits ." );
537
562
return PacketBufferHandle ();
538
563
}
539
564
540
565
#if CHIP_SYSTEM_CONFIG_USE_LWIP
541
-
566
+ // This cast is safe because lAllocSize is no larger than
567
+ // kMaxSizeWithoutReserve, which fits in uint16_t.
542
568
lPacket = static_cast <PacketBuffer *>(
543
569
pbuf_alloc (PBUF_RAW, static_cast <uint16_t >(lAllocSize), CHIP_SYSTEM_PACKETBUFFER_LWIP_PBUF_TYPE));
544
570
545
571
SYSTEM_STATS_UPDATE_LWIP_PBUF_COUNTS ();
546
572
547
573
#elif CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_POOL
548
574
549
- static_cast <void >(lBlockSize);
550
575
#if !CHIP_SYSTEM_CONFIG_NO_LOCKING && CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING
551
576
if (!sBufferPoolMutex .isInitialized ())
552
577
{
@@ -565,7 +590,9 @@ PacketBufferHandle PacketBufferHandle::New(size_t aAvailableSize, uint16_t aRese
565
590
UNLOCK_BUF_POOL ();
566
591
567
592
#elif CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_HEAP
568
-
593
+ // sumOfSizes is essentially (kStructureSize + lAllocSize) which we already
594
+ // checked to fit in a size_t.
595
+ const size_t lBlockSize = static_cast <size_t >(sumOfSizes);
569
596
lPacket = reinterpret_cast <PacketBuffer *>(chip::Platform::MemoryAlloc (lBlockSize));
570
597
SYSTEM_STATS_INCREMENT (chip::System::Stats::kSystemLayer_NumPacketBufs );
571
598
0 commit comments