diff --git a/components/esp32/ld/esp32.extram.bss.ld b/components/esp32/ld/esp32.extram.bss.ld index 6e0ab496e5..582f6eb6ea 100644 --- a/components/esp32/ld/esp32.extram.bss.ld +++ b/components/esp32/ld/esp32.extram.bss.ld @@ -12,6 +12,7 @@ SECTIONS *libpp.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON) *liblwip.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON) *libbt.a:(EXCLUDE_FILE (libbtdm_app.a) .dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON) + . = ALIGN(4); _ext_ram_bss_end = ABSOLUTE(.); } > extern_ram_seg } diff --git a/components/esp32/spiram.c b/components/esp32/spiram.c index 11a775b826..dbb279d212 100644 --- a/components/esp32/spiram.c +++ b/components/esp32/spiram.c @@ -61,7 +61,7 @@ static const char* TAG = "spiram"; #endif #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY -extern int _ext_ram_bss_start, _ext_ram_bss_end; +extern uint8_t _ext_ram_bss_start, _ext_ram_bss_end; #endif static bool spiram_inited=false; diff --git a/components/heap/multi_heap.c b/components/heap/multi_heap.c index 39917f4af0..d131ff269c 100644 --- a/components/heap/multi_heap.c +++ b/components/heap/multi_heap.c @@ -326,18 +326,21 @@ size_t multi_heap_get_allocated_size_impl(multi_heap_handle_t heap, void *p) return block_data_size(pb); } -multi_heap_handle_t multi_heap_register_impl(void *start, size_t size) +multi_heap_handle_t multi_heap_register_impl(void *start_ptr, size_t size) { - heap_t *heap = (heap_t *)ALIGN_UP((intptr_t)start); - uintptr_t end = ALIGN((uintptr_t)start + size); - if (end - (uintptr_t)start < sizeof(heap_t) + 2*sizeof(heap_block_t)) { + uintptr_t start = ALIGN_UP((uintptr_t)start_ptr); + uintptr_t end = ALIGN((uintptr_t)start_ptr + size); + heap_t *heap = (heap_t *)start; + size = end - start; + + if (end < start || size < sizeof(heap_t) + 2*sizeof(heap_block_t)) { return NULL; /* 'size' is too small to fit a heap here */ } heap->lock = NULL; heap->last_block = (heap_block_t *)(end - sizeof(heap_block_t)); /* first 'real' (allocatable) free block goes after the heap structure */ - heap_block_t *first_free_block = (heap_block_t *)((intptr_t)start + sizeof(heap_t)); + heap_block_t *first_free_block = (heap_block_t *)(start + sizeof(heap_t)); first_free_block->header = (intptr_t)heap->last_block | BLOCK_FREE_FLAG; first_free_block->next_free = heap->last_block; @@ -356,7 +359,7 @@ multi_heap_handle_t multi_heap_register_impl(void *start, size_t size) - minus header of first_free_block - minus whole block at heap->last_block */ - heap->free_bytes = ALIGN(size) - sizeof(heap_t) - sizeof(first_free_block->header) - sizeof(heap_block_t); + heap->free_bytes = size - sizeof(heap_t) - sizeof(first_free_block->header) - sizeof(heap_block_t); heap->minimum_free_bytes = heap->free_bytes; return heap; diff --git a/components/heap/test_multi_heap_host/test_multi_heap.cpp b/components/heap/test_multi_heap_host/test_multi_heap.cpp index 133f12536b..310ee9dcf1 100644 --- a/components/heap/test_multi_heap_host/test_multi_heap.cpp +++ b/components/heap/test_multi_heap_host/test_multi_heap.cpp @@ -453,3 +453,44 @@ TEST_CASE("corrupt heap block", "[multi_heap]") memset(a, 0xEE, 64); REQUIRE( !multi_heap_check(heap, true) ); } + +TEST_CASE("unaligned heaps", "[multi_heap]") +{ + const size_t CHUNK_LEN = 256; + const size_t CANARY_LEN = 16; + const uint8_t CANARY_BYTE = 0x3E; + uint8_t heap_chunk[CHUNK_LEN + CANARY_LEN * 2]; + + /* Put some canary bytes before and after the bytes we intend to use for + the heap, make sure they aren't ever overwritten */ + memset(heap_chunk, CANARY_BYTE, CANARY_LEN); + memset(heap_chunk + CANARY_LEN + CHUNK_LEN, CANARY_BYTE, CANARY_LEN); + + for (int i = 0; i < 8; i++) { + printf("Testing with offset %d\n", i); + multi_heap_handle_t heap = multi_heap_register(heap_chunk + CANARY_LEN + i, CHUNK_LEN - i); + multi_heap_info_t info; + + REQUIRE( multi_heap_check(heap, true) ); + + multi_heap_get_info(heap, &info); + + REQUIRE( info.total_free_bytes > CHUNK_LEN - 64 - i ); + REQUIRE( info.largest_free_block > CHUNK_LEN - 64 - i ); + + void *a = multi_heap_malloc(heap, info.largest_free_block); + REQUIRE( a != NULL ); + memset(a, 0xAA, info.largest_free_block); + + REQUIRE( multi_heap_check(heap, true) ); + + multi_heap_free(heap, a); + + REQUIRE( multi_heap_check(heap, true) ); + + for (unsigned j = 0; j < CANARY_LEN; j++) { // check canaries + REQUIRE( heap_chunk[j] == CANARY_BYTE ); + REQUIRE( heap_chunk[CHUNK_LEN + CANARY_LEN + j] == CANARY_BYTE ); + } + } +}