selftests/bpf: a test for proper cnums compare in is_state_visited()

Test case demonstrating a bug in cnum comparison logic fixed by
previous commit. A pruning point is reached with r6 in two states:
1. 32-bit range of [0x7FFFFFF0, U32_MAX] ∪ [0, 0x10]
2. 32-bit range of [0x100, 0x200]

At pruning point the buggy is_state_visited() logic would assume that
would assume range (2) to be a subset of (1) and fail to explore the
path performing division by zero.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260425-cnum-range-within-v1-2-2fdca70cb09d@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Eduard Zingerman 2026-04-25 15:48:24 -07:00 committed by Alexei Starovoitov
parent cd5b460ed1
commit af469e10b4

View File

@ -2267,4 +2267,31 @@ __naked void deduce64_from_32_wrapping_32bit(void)
: __clobber_all);
}
/* Check that range_within() compares cnum ranges, not min/max projections. */
SEC("socket")
__failure __msg("div by zero")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void range_within_cnum_cross_both_boundaries(void)
{
asm volatile (" \
call %[bpf_get_prandom_u32]; \
r1 = 0x80000020; \
if r0 > r1 goto 1f; \
r0 += 0x7FFFFFF0; /* PATH 1 */ \
goto 2f; \
1: call %[bpf_get_prandom_u32]; /* PATH 2 */ \
if r0 < 0x100 goto 3f; \
if r0 > 0x200 goto 3f; \
2: /* PATH 1: r0 ∈ [0x7FFFFFF0, U32_MAX] [0, 0x10] */ \
/* PATH 2: r0 ∈ [0x100, 0x200] */ \
if r0 != 0x100 goto 3f; /* True only on PATH 2 */ \
r0 /= 0; \
3: exit; \
"
:: __imm(bpf_map_lookup_elem),
__imm_addr(map_hash_8b),
__imm(bpf_get_prandom_u32)
: __clobber_all);
}
char _license[] SEC("license") = "GPL";