Skip to content

Commit 58770b0

Browse files
authored
Check for add overflow only once (#467)
Update the size calculations such that we only need to check for add overflow only once. Also, change the way we detect add overflow so that we do not need to cause an overflow to detect an overflow. Signed-off-by: Gaurav Aggarwal <[email protected]>
1 parent 8eb3585 commit 58770b0

File tree

3 files changed

+54
-63
lines changed

3 files changed

+54
-63
lines changed

portable/MemMang/heap_2.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,14 @@
6262
/* Assumes 8bit bytes! */
6363
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
6464

65+
/* Max value that fits in a size_t type. */
66+
#define heapSIZE_MAX ( ~( ( size_t ) 0 ) )
67+
6568
/* Check if multiplying a and b will result in overflow. */
66-
#define heapMULTIPLY_WILL_OVERFLOW( a, b, max ) ( ( ( a ) > 0 ) && ( ( b ) > ( ( max ) / ( a ) ) ) )
69+
#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) )
70+
71+
/* Check if adding a and b will result in overflow. */
72+
#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) )
6773

6874
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
6975
* the allocation status of a block. When MSB of the xBlockSize member of
@@ -97,7 +103,7 @@ typedef struct A_BLOCK_LINK
97103
} BlockLink_t;
98104

99105

100-
static const uint16_t heapSTRUCT_SIZE = ( ( sizeof( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );
106+
static const uint16_t heapSTRUCT_SIZE = ( ( sizeof( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ) );
101107
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
102108

103109
/* Create a couple of list links to mark the start and end of the list. */
@@ -149,6 +155,7 @@ void * pvPortMalloc( size_t xWantedSize )
149155
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
150156
PRIVILEGED_DATA static BaseType_t xHeapHasBeenInitialised = pdFALSE;
151157
void * pvReturn = NULL;
158+
size_t xAdditionalRequiredSize;
152159

153160
vTaskSuspendAll();
154161
{
@@ -160,29 +167,22 @@ void * pvPortMalloc( size_t xWantedSize )
160167
xHeapHasBeenInitialised = pdTRUE;
161168
}
162169

163-
/* The wanted size must be increased so it can contain a BlockLink_t
164-
* structure in addition to the requested amount of bytes. */
165-
if( ( xWantedSize > 0 ) &&
166-
( ( xWantedSize + heapSTRUCT_SIZE ) > xWantedSize ) ) /* Overflow check. */
170+
if( xWantedSize > 0 )
167171
{
168-
xWantedSize += heapSTRUCT_SIZE;
172+
/* The wanted size must be increased so it can contain a BlockLink_t
173+
* structure in addition to the requested amount of bytes. Some
174+
* additional increment may also be needed for alignment. */
175+
xAdditionalRequiredSize = heapSTRUCT_SIZE + portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK );
169176

170-
/* Byte alignment required. Check for overflow. */
171-
if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) )
172-
> xWantedSize )
177+
if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
173178
{
174-
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
175-
configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
179+
xWantedSize += xAdditionalRequiredSize;
176180
}
177181
else
178182
{
179183
xWantedSize = 0;
180184
}
181185
}
182-
else
183-
{
184-
xWantedSize = 0;
185-
}
186186

187187
/* Check the block size we are trying to allocate is not so large that the
188188
* top bit is set. The top bit of the block size member of the BlockLink_t
@@ -320,9 +320,8 @@ void * pvPortCalloc( size_t xNum,
320320
size_t xSize )
321321
{
322322
void * pv = NULL;
323-
const size_t xSizeMaxValue = ~( ( size_t ) 0 );
324323

325-
if( !heapMULTIPLY_WILL_OVERFLOW( xNum, xSize, xSizeMaxValue ) )
324+
if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 )
326325
{
327326
pv = pvPortMalloc( xNum * xSize );
328327

portable/MemMang/heap_4.c

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,14 @@
6161
/* Assumes 8bit bytes! */
6262
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
6363

64+
/* Max value that fits in a size_t type. */
65+
#define heapSIZE_MAX ( ~( ( size_t ) 0 ) )
66+
6467
/* Check if multiplying a and b will result in overflow. */
65-
#define heapMULTIPLY_WILL_OVERFLOW( a, b, max ) ( ( ( a ) > 0 ) && ( ( b ) > ( ( max ) / ( a ) ) ) )
68+
#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) )
69+
70+
/* Check if adding a and b will result in overflow. */
71+
#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) )
6672

6773
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
6874
* the allocation status of a block. When MSB of the xBlockSize member of
@@ -132,6 +138,7 @@ void * pvPortMalloc( size_t xWantedSize )
132138
{
133139
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
134140
void * pvReturn = NULL;
141+
size_t xAdditionalRequiredSize;
135142

136143
vTaskSuspendAll();
137144
{
@@ -146,35 +153,25 @@ void * pvPortMalloc( size_t xWantedSize )
146153
mtCOVERAGE_TEST_MARKER();
147154
}
148155

149-
/* The wanted size must be increased so it can contain a BlockLink_t
150-
* structure in addition to the requested amount of bytes. */
151-
if( ( xWantedSize > 0 ) &&
152-
( ( xWantedSize + xHeapStructSize ) > xWantedSize ) ) /* Overflow check. */
156+
if( xWantedSize > 0 )
153157
{
154-
xWantedSize += xHeapStructSize;
158+
/* The wanted size must be increased so it can contain a BlockLink_t
159+
* structure in addition to the requested amount of bytes. Some
160+
* additional increment may also be needed for alignment. */
161+
xAdditionalRequiredSize = xHeapStructSize + portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK );
155162

156-
/* Ensure that blocks are always aligned. */
157-
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
163+
if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
158164
{
159-
/* Byte alignment required. Check for overflow. */
160-
if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) > xWantedSize )
161-
{
162-
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
163-
configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
164-
}
165-
else
166-
{
167-
xWantedSize = 0;
168-
}
165+
xWantedSize += xAdditionalRequiredSize;
169166
}
170167
else
171168
{
172-
mtCOVERAGE_TEST_MARKER();
169+
xWantedSize = 0;
173170
}
174171
}
175172
else
176173
{
177-
xWantedSize = 0;
174+
mtCOVERAGE_TEST_MARKER();
178175
}
179176

180177
/* Check the block size we are trying to allocate is not so large that the
@@ -362,9 +359,8 @@ void * pvPortCalloc( size_t xNum,
362359
size_t xSize )
363360
{
364361
void * pv = NULL;
365-
const size_t xSizeMaxValue = ~( ( size_t ) 0 );
366362

367-
if( !heapMULTIPLY_WILL_OVERFLOW( xNum, xSize, xSizeMaxValue ) )
363+
if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 )
368364
{
369365
pv = pvPortMalloc( xNum * xSize );
370366

portable/MemMang/heap_5.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,14 @@
9595
/* Assumes 8bit bytes! */
9696
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
9797

98+
/* Max value that fits in a size_t type. */
99+
#define heapSIZE_MAX ( ~( ( size_t ) 0 ) )
100+
98101
/* Check if multiplying a and b will result in overflow. */
99-
#define heapMULTIPLY_WILL_OVERFLOW( a, b, max ) ( ( ( a ) > 0 ) && ( ( b ) > ( ( max ) / ( a ) ) ) )
102+
#define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) )
103+
104+
/* Check if adding a and b will result in overflow. */
105+
#define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) )
100106

101107
/* MSB of the xBlockSize member of an BlockLink_t structure is used to track
102108
* the allocation status of a block. When MSB of the xBlockSize member of
@@ -150,42 +156,33 @@ void * pvPortMalloc( size_t xWantedSize )
150156
{
151157
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
152158
void * pvReturn = NULL;
159+
size_t xAdditionalRequiredSize;
153160

154161
/* The heap must be initialised before the first call to
155162
* prvPortMalloc(). */
156163
configASSERT( pxEnd );
157164

158165
vTaskSuspendAll();
159166
{
160-
/* The wanted size is increased so it can contain a BlockLink_t
161-
* structure in addition to the requested amount of bytes. */
162-
if( ( xWantedSize > 0 ) &&
163-
( ( xWantedSize + xHeapStructSize ) > xWantedSize ) ) /* Overflow check. */
167+
if( xWantedSize > 0 )
164168
{
165-
xWantedSize += xHeapStructSize;
169+
/* The wanted size must be increased so it can contain a BlockLink_t
170+
* structure in addition to the requested amount of bytes. Some
171+
* additional increment may also be needed for alignment. */
172+
xAdditionalRequiredSize = xHeapStructSize + portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK );
166173

167-
/* Ensure that blocks are always aligned */
168-
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
174+
if( heapADD_WILL_OVERFLOW( xWantedSize, xAdditionalRequiredSize ) == 0 )
169175
{
170-
/* Byte alignment required. Check for overflow */
171-
if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) >
172-
xWantedSize )
173-
{
174-
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
175-
}
176-
else
177-
{
178-
xWantedSize = 0;
179-
}
176+
xWantedSize += xAdditionalRequiredSize;
180177
}
181178
else
182179
{
183-
mtCOVERAGE_TEST_MARKER();
180+
xWantedSize = 0;
184181
}
185182
}
186183
else
187184
{
188-
xWantedSize = 0;
185+
mtCOVERAGE_TEST_MARKER();
189186
}
190187

191188
/* Check the block size we are trying to allocate is not so large that the
@@ -365,9 +362,8 @@ void * pvPortCalloc( size_t xNum,
365362
size_t xSize )
366363
{
367364
void * pv = NULL;
368-
const size_t xSizeMaxValue = ~( ( size_t ) 0 );
369365

370-
if( !heapMULTIPLY_WILL_OVERFLOW( xNum, xSize, xSizeMaxValue ) )
366+
if( heapMULTIPLY_WILL_OVERFLOW( xNum, xSize ) == 0 )
371367
{
372368
pv = pvPortMalloc( xNum * xSize );
373369

@@ -502,7 +498,7 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
502498
* inserted at the end of the region space. */
503499
xAddress = xAlignedHeap + xTotalRegionSize;
504500
xAddress -= xHeapStructSize;
505-
xAddress &= ~portBYTE_ALIGNMENT_MASK;
501+
xAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
506502
pxEnd = ( BlockLink_t * ) xAddress;
507503
pxEnd->xBlockSize = 0;
508504
pxEnd->pxNextFreeBlock = NULL;

0 commit comments

Comments
 (0)