lib/os/heap: guard against arithmetic overflows
Let's do it upfront only once for each entry point and dispense with overflow checks later to keep the code simple. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
c92ad609b3
commit
f436315e02
2 changed files with 20 additions and 4 deletions
|
@ -223,11 +223,12 @@ static chunkid_t alloc_chunk(struct z_heap *h, size_t sz)
|
||||||
|
|
||||||
void *sys_heap_alloc(struct sys_heap *heap, size_t bytes)
|
void *sys_heap_alloc(struct sys_heap *heap, size_t bytes)
|
||||||
{
|
{
|
||||||
if (bytes == 0U) {
|
struct z_heap *h = heap->heap;
|
||||||
|
|
||||||
|
if (bytes == 0U || size_too_big(h, bytes)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct z_heap *h = heap->heap;
|
|
||||||
size_t chunk_sz = bytes_to_chunksz(h, bytes);
|
size_t chunk_sz = bytes_to_chunksz(h, bytes);
|
||||||
chunkid_t c = alloc_chunk(h, chunk_sz);
|
chunkid_t c = alloc_chunk(h, chunk_sz);
|
||||||
if (c == 0U) {
|
if (c == 0U) {
|
||||||
|
@ -253,7 +254,7 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
|
||||||
if (align <= chunk_header_bytes(h)) {
|
if (align <= chunk_header_bytes(h)) {
|
||||||
return sys_heap_alloc(heap, bytes);
|
return sys_heap_alloc(heap, bytes);
|
||||||
}
|
}
|
||||||
if (bytes == 0) {
|
if (bytes == 0 || size_too_big(h, bytes)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,6 +298,8 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
|
||||||
|
|
||||||
void *sys_heap_realloc(struct sys_heap *heap, void *ptr, size_t bytes)
|
void *sys_heap_realloc(struct sys_heap *heap, void *ptr, size_t bytes)
|
||||||
{
|
{
|
||||||
|
struct z_heap *h = heap->heap;
|
||||||
|
|
||||||
/* special realloc semantics */
|
/* special realloc semantics */
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
return sys_heap_alloc(heap, bytes);
|
return sys_heap_alloc(heap, bytes);
|
||||||
|
@ -306,7 +309,10 @@ void *sys_heap_realloc(struct sys_heap *heap, void *ptr, size_t bytes)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct z_heap *h = heap->heap;
|
if (size_too_big(h, bytes)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
chunkid_t c = mem_to_chunkid(h, ptr);
|
chunkid_t c = mem_to_chunkid(h, ptr);
|
||||||
chunkid_t rc = right_chunk(h, c);
|
chunkid_t rc = right_chunk(h, c);
|
||||||
size_t chunks_need = bytes_to_chunksz(h, bytes);
|
size_t chunks_need = bytes_to_chunksz(h, bytes);
|
||||||
|
|
|
@ -229,6 +229,16 @@ static inline int bucket_idx(struct z_heap *h, size_t sz)
|
||||||
return 31 - __builtin_clz(usable_sz);
|
return 31 - __builtin_clz(usable_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool size_too_big(struct z_heap *h, size_t bytes)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Quick check to bail out early if size is too big.
|
||||||
|
* Also guards against potential arithmetic overflows elsewhere.
|
||||||
|
* There is a minimum of one chunk always in use by the heap header.
|
||||||
|
*/
|
||||||
|
return (bytes / CHUNK_UNIT) >= h->len;
|
||||||
|
}
|
||||||
|
|
||||||
/* For debugging */
|
/* For debugging */
|
||||||
void heap_dump(struct z_heap *h);
|
void heap_dump(struct z_heap *h);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue