[Concept,33/33] test: Clear bootstd cur_bootflow after each test

Message ID 20260416023021.626949-34-sjg@u-boot.org
State New
Headers
Series Fix memory leaks and test pollution in sandbox tests |

Commit Message

Simon Glass April 16, 2026, 2:29 a.m. UTC
  From: Simon Glass <sjg@chromium.org>

bootflow_efi and similar tests run 'bootflow select N', which stores a
pointer to an entry of std->bootflows in std->cur_bootflow. The
bootflow alist holds its elements in one allocated buffer and reallocs
that buffer (dropping the old one, which mcheck flood-fills with 0xf5)
when the list grows. A later test can then re-grow the alist, leaving
cur_bootflow dangling.

ut_measurement_measure hits this: env_set("bootargs", ...) fires the
on_bootargs callback which reads std->cur_bootflow, tries to free
bflow->cmdline, and segfaults on the flood-filled pointer.

Reset cur_bootflow to NULL in test_post_run() so no test leaves a
dangling reference behind. on_bootargs already returns early when
cur_bootflow is NULL, so the callback becomes a no-op instead of a
use-after-free.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 test/test-main.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
  

Patch

diff --git a/test/test-main.c b/test/test-main.c
index fc66b2af0d0..a8ec76ab8ad 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -8,6 +8,7 @@ 
 
 #include <blk.h>
 #include <bootstage.h>
+#include <bootstd.h>
 #include <console.h>
 #include <cyclic.h>
 #include <dm.h>
@@ -608,9 +609,24 @@  static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
  */
 static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
 {
+	struct bootstd_priv *std;
+
 	ut_unsilence_console(uts);
 	if (test->flags & UTF_DM)
 		ut_assertok(dm_test_post_run(uts));
+
+	/*
+	 * Drop any reference to the currently selected bootflow. The bootflow
+	 * may be inside an alist buffer that a later test re-grows (and
+	 * therefore frees); leaving the pointer behind turns the on_bootargs
+	 * env callback into a use-after-free.
+	 */
+	if (CONFIG_IS_ENABLED(BOOTSTD)) {
+		std = bootstd_try_priv();
+		if (std)
+			std->cur_bootflow = NULL;
+	}
+
 	ut_assertok(cyclic_unregister_all());
 	ut_assertok(event_uninit());