Skip to content

Commit fbedcc1

Browse files
authored
Heap panic / abort cleanup (#8465)
Isolate NULL/panic test of _context to dev debug assert macro. Use abort instead of panic for case of caller providing non-heap address pointer. Added debug print. Improved get_unpoisoned_check_neighbors to print file/line when available.
1 parent a29eaff commit fbedcc1

File tree

4 files changed

+56
-31
lines changed

4 files changed

+56
-31
lines changed

Diff for: cores/esp8266/umm_malloc/umm_local.c

+13-10
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,20 @@ static void *get_unpoisoned_check_neighbors(void *vptr, const char *file, int li
9898
UMM_CRITICAL_DECL(id_poison);
9999
uint16_t c;
100100
bool poison = false;
101-
umm_heap_context_t *_context = umm_get_ptr_context(vptr);
102-
if (NULL == _context) {
103-
panic();
104-
return NULL;
101+
umm_heap_context_t *_context = _umm_get_ptr_context((void *)ptr);
102+
if (_context) {
103+
104+
/* Figure out which block we're in. Note the use of truncated division... */
105+
c = (ptr - (uintptr_t)(&(_context->heap[0]))) / sizeof(umm_block);
106+
107+
UMM_CRITICAL_ENTRY(id_poison);
108+
poison =
109+
check_poison_block(&UMM_BLOCK(c)) &&
110+
check_poison_neighbors(_context, c);
111+
UMM_CRITICAL_EXIT(id_poison);
112+
} else {
113+
DBGLOG_ERROR("\nPointer %p is not a Heap address.\n", vptr);
105114
}
106-
/* Figure out which block we're in. Note the use of truncated division... */
107-
c = (ptr - (uintptr_t)(&(_context->heap[0]))) / sizeof(umm_block);
108-
109-
UMM_CRITICAL_ENTRY(id_poison);
110-
poison = check_poison_block(&UMM_BLOCK(c)) && check_poison_neighbors(_context, c);
111-
UMM_CRITICAL_EXIT(id_poison);
112115

113116
if (!poison) {
114117
if (file) {

Diff for: cores/esp8266/umm_malloc/umm_malloc.cpp

+40-16
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ extern uint32_t UMM_MALLOC_CFG_HEAP_SIZE;
8484
* CRT0 init.
8585
*/
8686

87+
#if 0 // Must be zero at release
88+
#warning "Macro NON_NULL_CONTEXT_ASSERT() is active!"
89+
/*
90+
* Keep for future debug/maintenance of umm_malloc. Not needed in a
91+
* regular/debug build. Call paths that use NON_NULL_CONTEXT_ASSERT logically
92+
* guard against returning NULL. This macro double-checks that assumption during
93+
* development.
94+
*/
95+
#define NON_NULL_CONTEXT_ASSERT() assert((NULL != _context))
96+
#else
97+
#define NON_NULL_CONTEXT_ASSERT() (void)0
98+
#endif
99+
87100
#include "umm_local.h" // target-dependent supplemental
88101

89102
/* ------------------------------------------------------------------------- */
@@ -213,21 +226,41 @@ int umm_get_heap_stack_index(void) {
213226
* realloc or free since you may not be in the right heap to handle it.
214227
*
215228
*/
216-
static bool test_ptr_context(size_t which, void *ptr) {
229+
static bool test_ptr_context(const size_t which, const void *const ptr) {
217230
return
218231
heap_context[which].heap &&
219232
ptr >= (void *)heap_context[which].heap &&
220233
ptr < heap_context[which].heap_end;
221234
}
222235

223-
static umm_heap_context_t *umm_get_ptr_context(void *ptr) {
236+
/*
237+
* Find Heap context by allocation address - may return NULL
238+
*/
239+
umm_heap_context_t *_umm_get_ptr_context(const void *const ptr) {
224240
for (size_t i = 0; i < UMM_NUM_HEAPS; i++) {
225241
if (test_ptr_context(i, ptr)) {
226242
return umm_get_heap_by_id(i);
227243
}
228244
}
229245

230-
panic();
246+
return NULL;
247+
}
248+
249+
/*
250+
* Find Heap context by allocation address - must either succeed or abort
251+
*/
252+
static umm_heap_context_t *umm_get_ptr_context(const void *const ptr) {
253+
umm_heap_context_t *const _context = _umm_get_ptr_context(ptr);
254+
if (_context) {
255+
return _context;
256+
}
257+
258+
[[maybe_unused]] uintptr_t sketch_ptr = (uintptr_t)ptr;
259+
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
260+
sketch_ptr += sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE;
261+
#endif
262+
DBGLOG_ERROR("\nPointer %p is not a Heap address.\n", (void *)sketch_ptr);
263+
abort();
231264
return NULL;
232265
}
233266

@@ -579,10 +612,7 @@ static void umm_free_core(umm_heap_context_t *_context, void *ptr) {
579612

580613
uint16_t c;
581614

582-
if (NULL == _context) {
583-
panic();
584-
return;
585-
}
615+
NON_NULL_CONTEXT_ASSERT();
586616

587617
STATS__FREE_REQUEST(id_free);
588618
/*
@@ -672,12 +702,9 @@ static void *umm_malloc_core(umm_heap_context_t *_context, size_t size) {
672702

673703
uint16_t cf;
674704

675-
STATS__ALLOC_REQUEST(id_malloc, size);
705+
NON_NULL_CONTEXT_ASSERT();
676706

677-
if (NULL == _context) {
678-
panic();
679-
return NULL;
680-
}
707+
STATS__ALLOC_REQUEST(id_malloc, size);
681708

682709
blocks = umm_blocks(size);
683710

@@ -925,10 +952,7 @@ void *umm_realloc(void *ptr, size_t size) {
925952

926953
/* Need to be in the heap in which this block lives */
927954
umm_heap_context_t *_context = umm_get_ptr_context(ptr);
928-
if (NULL == _context) {
929-
panic();
930-
return NULL;
931-
}
955+
NON_NULL_CONTEXT_ASSERT();
932956

933957
if (0 == size) {
934958
DBGLOG_DEBUG("realloc to 0 size, just free the block\n");

Diff for: cores/esp8266/umm_malloc/umm_malloc_cfg.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,7 @@ void IRAM_ATTR heap_vPortFree(void *ptr, const char *file, int line);
779779
#define dbg_heap_free(p) free(p)
780780
#endif
781781

782-
#elif defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
782+
#elif defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) // #elif for #ifdef DEBUG_ESP_OOM
783783
#include <pgmspace.h>
784784
void *IRAM_ATTR heap_pvPortRealloc(void *ptr, size_t size, const char *file, int line);
785785
#define realloc(p,s) ({ static const char mem_debug_file[] PROGMEM STORE_ATTR = __FILE__; heap_pvPortRealloc(p, s, mem_debug_file, __LINE__); })

Diff for: cores/esp8266/umm_malloc/umm_poison.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,8 @@ static void *get_unpoisoned(void *vptr) {
142142
ptr -= (sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE);
143143

144144
umm_heap_context_t *_context = umm_get_ptr_context(vptr);
145-
if (NULL == _context) {
146-
panic();
147-
return NULL;
148-
}
145+
NON_NULL_CONTEXT_ASSERT();
146+
149147
/* Figure out which block we're in. Note the use of truncated division... */
150148
c = (ptr - (uintptr_t)(&(_context->heap[0]))) / sizeof(umm_block);
151149

0 commit comments

Comments
 (0)