diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index f05d7ae83c5..ae1e6d27d08 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -6010,6 +6010,11 @@ bool malloc_backtrace_is_active(bool *skipp, bool *busyp)
 #endif
 }
 
+bool malloc_mcheck_overflow(void)
+{
+	return mcheck_registry_full;
+}
+
 static const char *mcheck_caller(void)
 {
 #if CONFIG_IS_ENABLED(MCHECK_BACKTRACE)
diff --git a/common/mcheck_core.inc.h b/common/mcheck_core.inc.h
index 968b058ba6d..9f13945cde8 100644
--- a/common/mcheck_core.inc.h
+++ b/common/mcheck_core.inc.h
@@ -79,6 +79,7 @@ static char mcheck_pedantic_flag __section(".data") = 0;
 static void *mcheck_registry[REGISTRY_SZ] __section(".data") = {0};
 static size_t mcheck_chunk_count __section(".data") = 0;
 static size_t mcheck_chunk_count_max __section(".data") = 0;
+static bool mcheck_registry_full __section(".data");
 
 typedef unsigned long long mcheck_elem;
 typedef struct {
@@ -200,7 +201,6 @@ static void *mcheck_allocated_helper(void *altoghether_ptr, size_t customer_sz,
 				     size_t alignment, int clean_content,
 				     const char *caller)
 {
-	static bool overflow_msg_shown;
 	const size_t slop = alignment ?
 		mcheck_evaluate_memalign_prefix_size(alignment) - sizeof(struct mcheck_hdr) : 0;
 	struct mcheck_hdr *hdr = (struct mcheck_hdr *)((char *)altoghether_ptr + slop);
@@ -239,8 +239,8 @@ static void *mcheck_allocated_helper(void *altoghether_ptr, size_t customer_sz,
 			return payload; // normal end
 		}
 
-	if (!overflow_msg_shown) {
-		overflow_msg_shown = true;
+	if (!mcheck_registry_full) {
+		mcheck_registry_full = true;
 		printf("\n\nERROR: mcheck registry overflow, pedantic check would be incomplete!\n\n");
 	}
 	return payload;
diff --git a/include/malloc.h b/include/malloc.h
index 05d4c06fb89..0a780fc03c3 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -863,6 +863,22 @@ static inline bool malloc_backtrace_is_active(bool *skipp, bool *busyp)
 }
 #endif
 
+/**
+ * malloc_mcheck_overflow() - Check whether the mcheck registry filled
+ *
+ * The mcheck code registers each allocation's header in a fixed-size array so
+ * that leak reporting and pedantic checking can find it. If the array is ever
+ * exhausted, later allocations are still returned but their caller info cannot
+ * be recovered.
+ *
+ * Return: true if the registry has overflowed at any point
+ */
+#if CONFIG_IS_ENABLED(MCHECK_HEAP_PROTECTION)
+bool malloc_mcheck_overflow(void);
+#else
+static inline bool malloc_mcheck_overflow(void) { return false; }
+#endif
+
 /**
  * malloc_chunk_size() - Return the dlmalloc chunk size for an allocation
  *
diff --git a/test/cmd/malloc.c b/test/cmd/malloc.c
index 95809845dd7..db4350afe68 100644
--- a/test/cmd/malloc.c
+++ b/test/cmd/malloc.c
@@ -63,6 +63,12 @@ static int cmd_test_malloc_leak(struct unit_test_state *uts)
 	void *ptr;
 	int ret;
 
+	/*
+	 * If the mcheck registry ever overflowed, later allocations are not
+	 * registered and leak reports cannot recover the caller string.
+	 */
+	ut_assert(!malloc_mcheck_overflow());
+
 	/* Take a snapshot, then check with no leaks */
 	ut_assertok(malloc_leak_check_start(&snap));
 	ut_assert(snap.count > 0);
