test: Support testing malloc() failures

It is helpful to test that out-of-memory checks work correctly in code
that calls malloc().

Add a simple way to force failure after a given number of malloc() calls.

Fix a header guard to avoid a build error on sandbox_vpl.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
Simon Glass 2022-09-06 20:27:00 -06:00 committed by Tom Rini
parent 7c14dc7f77
commit 62d638386c
4 changed files with 33 additions and 0 deletions

View File

@ -6,6 +6,7 @@
*/ */
#ifndef __ASM_MALLOC_H #ifndef __ASM_MALLOC_H
#define __ASM_MALLOC_H
void *malloc(size_t size); void *malloc(size_t size);
void free(void *ptr); void free(void *ptr);

View File

@ -596,6 +596,9 @@ ulong mem_malloc_start = 0;
ulong mem_malloc_end = 0; ulong mem_malloc_end = 0;
ulong mem_malloc_brk = 0; ulong mem_malloc_brk = 0;
static bool malloc_testing; /* enable test mode */
static int malloc_max_allocs; /* return NULL after this many calls to malloc() */
void *sbrk(ptrdiff_t increment) void *sbrk(ptrdiff_t increment)
{ {
ulong old = mem_malloc_brk; ulong old = mem_malloc_brk;
@ -1307,6 +1310,11 @@ Void_t* mALLOc(bytes) size_t bytes;
return malloc_simple(bytes); return malloc_simple(bytes);
#endif #endif
if (CONFIG_IS_ENABLED(UNIT_TEST) && malloc_testing) {
if (--malloc_max_allocs < 0)
return NULL;
}
/* check if mem_malloc_init() was run */ /* check if mem_malloc_init() was run */
if ((mem_malloc_start == 0) && (mem_malloc_end == 0)) { if ((mem_malloc_start == 0) && (mem_malloc_end == 0)) {
/* not initialized yet */ /* not initialized yet */
@ -2470,6 +2478,17 @@ int initf_malloc(void)
return 0; return 0;
} }
void malloc_enable_testing(int max_allocs)
{
malloc_testing = true;
malloc_max_allocs = max_allocs;
}
void malloc_disable_testing(void)
{
malloc_testing = false;
}
/* /*
History: History:

View File

@ -883,6 +883,18 @@ extern Void_t* sbrk();
void malloc_simple_info(void); void malloc_simple_info(void);
/**
* malloc_enable_testing() - Put malloc() into test mode
*
* This only works if UNIT_TESTING is enabled
*
* @max_allocs: return -ENOMEM after max_allocs calls to malloc()
*/
void malloc_enable_testing(int max_allocs);
/** malloc_disable_testing() - Put malloc() into normal mode */
void malloc_disable_testing(void);
#if CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE) #if CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE)
#define malloc malloc_simple #define malloc malloc_simple
#define realloc realloc_simple #define realloc realloc_simple

View File

@ -47,6 +47,7 @@ static int dm_test_pre_run(struct unit_test_state *uts)
uts->force_fail_alloc = false; uts->force_fail_alloc = false;
uts->skip_post_probe = false; uts->skip_post_probe = false;
gd->dm_root = NULL; gd->dm_root = NULL;
malloc_disable_testing();
if (CONFIG_IS_ENABLED(UT_DM) && !CONFIG_IS_ENABLED(OF_PLATDATA)) if (CONFIG_IS_ENABLED(UT_DM) && !CONFIG_IS_ENABLED(OF_PLATDATA))
memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count)); memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
arch_reset_for_test(); arch_reset_for_test();