mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-22 21:23:07 +03:00
Fix umm_blocks() (#8429)
Extracted fix from upstream for umm_blocks() - On allocations that were too large, umm_blocks() could return an incorrectly truncated value when the result is cast to uint16_t.
This commit is contained in:
parent
b5f3d1d6d5
commit
e5a214e6f1
@ -266,28 +266,68 @@ static umm_heap_context_t *umm_get_ptr_context(void *ptr) {
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
static uint16_t umm_blocks( size_t size ) {
|
static uint16_t umm_blocks(size_t size) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The calculation of the block size is not too difficult, but there are
|
* The calculation of the block size is not too difficult, but there are
|
||||||
* a few little things that we need to be mindful of.
|
* a few little things that we need to be mindful of.
|
||||||
*
|
*
|
||||||
* When a block removed from the free list, the space used by the free
|
* When a block removed from the free list, the space used by the free
|
||||||
* pointers is available for data. That's what the first calculation
|
* pointers is available for data. That's what the first calculation
|
||||||
* of size is doing.
|
* of size is doing.
|
||||||
*/
|
*
|
||||||
|
* We don't check for the special case of (size == 0) here as this needs
|
||||||
|
* special handling in the caller depending on context. For example when we
|
||||||
|
* realloc() a block to size 0 it should simply be freed.
|
||||||
|
*
|
||||||
|
* We do NOT need to check for allocating more blocks than the heap can
|
||||||
|
* possibly hold - the allocator figures this out for us.
|
||||||
|
*
|
||||||
|
* There are only two cases left to consider:
|
||||||
|
*
|
||||||
|
* 1. (size <= body) Obviously this is just one block
|
||||||
|
* 2. (blocks > (2^15)) This should return ((2^15)) to force a
|
||||||
|
* failure when the allocator runs
|
||||||
|
*
|
||||||
|
* If the requested size is greater that 32677-2 blocks (max block index
|
||||||
|
* minus the overhead of the top and bottom bookkeeping blocks) then we
|
||||||
|
* will return an incorrectly truncated value when the result is cast to
|
||||||
|
* a uint16_t.
|
||||||
|
*/
|
||||||
|
|
||||||
if( size <= (sizeof(((umm_block *)0)->body)) )
|
if (size <= (sizeof(((umm_block *)0)->body))) {
|
||||||
return( 1 );
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's for more than that, then we need to figure out the number of
|
* If it's for more than that, then we need to figure out the number of
|
||||||
* additional whole blocks the size of an umm_block are required.
|
* additional whole blocks the size of an umm_block are required, so
|
||||||
*/
|
* reduce the size request by the number of bytes in the body of the
|
||||||
|
* first block.
|
||||||
|
*/
|
||||||
|
|
||||||
size -= ( 1 + (sizeof(((umm_block *)0)->body)) );
|
size -= (sizeof(((umm_block *)0)->body));
|
||||||
|
|
||||||
return( 2 + size/(sizeof(umm_block)) );
|
/* NOTE WELL that we take advantage of the fact that INT16_MAX is the
|
||||||
|
* number of blocks that we can index in 15 bits :-)
|
||||||
|
*
|
||||||
|
* The below expression looks wierd, but it's right. Assuming body
|
||||||
|
* size of 4 bytes and a block size of 8 bytes:
|
||||||
|
*
|
||||||
|
* BYTES (BYTES-BODY) (BYTES-BODY-1)/BLOCKSIZE BLOCKS
|
||||||
|
* 1 n/a n/a 1
|
||||||
|
* 5 1 0 2
|
||||||
|
* 12 8 0 2
|
||||||
|
* 13 9 1 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t blocks = (2 + ((size - 1) / sizeof(umm_block)));
|
||||||
|
|
||||||
|
if (blocks > (INT16_MAX)) {
|
||||||
|
blocks = INT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint16_t)blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user