[PATCH bpf-next v2 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills

From: Nuoqi Gui

Date: Wed Jun 17 2026 - 11:33:00 EST


Add a verifier regression test for a pointer spill whose high half is
cleaned dead while the low half remains live. Force checkpoint creation
with BPF_F_TEST_STATE_FREQ and assert the verifier log reaches the
checkpoint and the subsequent 32-bit fill before rejecting the partial fill
from a non-scalar spill.

Acked-by: Eduard Zingerman <eddyz87@xxxxxxxxx>
Signed-off-by: Nuoqi Gui <gnq25@xxxxxxxxxxxxxxxxxxxxx>
---
.../testing/selftests/bpf/progs/verifier_spill_fill.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
index 6bc721accbae..0174887e28f5 100644
--- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
+++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
@@ -1359,4 +1359,22 @@ __naked void var_off_write_over_scalar_spill(void)
: __clobber_all);
}

+SEC("socket")
+__description("partial fill from cleaned pointer spill")
+__failure
+__log_level(2)
+__msg("1: (05) goto pc+0")
+__msg("2: (61) r0 = *(u32 *)(r10 -4)")
+__msg("invalid size of register fill")
+__flag(BPF_F_TEST_STATE_FREQ)
+__naked void partial_fill_from_cleaned_pointer_spill(void)
+{
+ /* Spill R1(ctx), then force a checkpoint and half-slot cleanup. */
+ asm volatile ("*(u64 *)(r10 - 8) = r1;"
+ "goto +0;"
+ "r0 = *(u32 *)(r10 - 4);"
+ "exit;"
+ ::: __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";

--
2.34.1