[Concept,20/37] test: Support testing malloc() failures

Message ID 20251201170529.3237986-21-sjg@u-boot.org
State New
Headers
Series malloc: Import dlmalloc 2.8.6 |

Commit Message

Simon Glass Dec. 1, 2025, 5:04 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

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.

Also add support for realloc() testing (from commit 04894f5ad53).

Changes from original commits:
- Variable declarations moved to top of U-Boot section (before dlmalloc())
- Adapted to new dlmalloc function names (dlmalloc/dlrealloc vs mALLOc/rEALLOc)

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Sean Anderson <seanga2@gmail.com>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit 62d638386c17d17b929ad10956c7f60825335a4e)
(cherry picked from commit 04894f5ad53cab0ee03eb3bc1cc1682e22f5dd1b)
---

 common/dlmalloc.c | 24 ++++++++++++++++++++++++
 include/malloc.h  | 12 ++++++++++++
 2 files changed, 36 insertions(+)
  

Patch

diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index 9298fc445e4..aacc9b5db3b 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -592,6 +592,9 @@  MAX_RELEASE_CHECK_RATE   default: 4095 unless not HAVE_MMAP
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static bool malloc_testing;	/* enable test mode */
+static int malloc_max_allocs;	/* return NULL after this many calls to malloc() */
+
 ulong mem_malloc_start;
 ulong mem_malloc_end;
 ulong mem_malloc_brk;
@@ -4614,6 +4617,11 @@  void* dlmalloc(size_t bytes) {
   /* Return NULL if not initialized yet */
   if (!mem_malloc_start && !mem_malloc_end)
     return NULL;
+
+  if (CONFIG_IS_ENABLED(UNIT_TEST) && malloc_testing) {
+    if (--malloc_max_allocs < 0)
+      return NULL;
+  }
 #endif
   /*
      Basic algorithm:
@@ -5328,6 +5336,10 @@  void* dlrealloc(void* oldmem, size_t bytes) {
     panic("pre-reloc realloc() is not supported");
   }
 #endif
+  if (CONFIG_IS_ENABLED(UNIT_TEST) && malloc_testing) {
+    if (--malloc_max_allocs < 0)
+      return NULL;
+  }
 #endif
   void* mem = 0;
   if (oldmem == 0) {
@@ -6491,6 +6503,17 @@  void mem_malloc_init(ulong start, ulong size)
 #endif
 }
 
+void malloc_enable_testing(int max_allocs)
+{
+	malloc_testing = true;
+	malloc_max_allocs = max_allocs;
+}
+
+void malloc_disable_testing(void)
+{
+	malloc_testing = false;
+}
+
 int initf_malloc(void)
 {
 #if CONFIG_IS_ENABLED(SYS_MALLOC_F)
@@ -6501,4 +6524,5 @@  int initf_malloc(void)
 
 	return 0;
 }
+
 #endif /* __UBOOT__ */
diff --git a/include/malloc.h b/include/malloc.h
index 76068032da7..72db7fdb507 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -658,6 +658,18 @@  extern ulong mem_malloc_start;
 extern ulong mem_malloc_end;
 extern ulong mem_malloc_brk;
 
+/**
+ * malloc_enable_testing() - Enable malloc failure testing
+ *
+ * @max_allocs: Number of allocations to allow before returning NULL
+ */
+void malloc_enable_testing(int max_allocs);
+
+/**
+ * malloc_disable_testing() - Disable malloc failure testing
+ */
+void malloc_disable_testing(void);
+
 /**
  * mem_malloc_init() - Initialize the malloc() heap
  *