selftests/bpf: new cases handled by 32->64 range refinements

1. 32-bit range starts before 64-bit range's low bits in each block,
   causing intersection to skip entire blocks.
2. 32-bit range crosses the U32_MAX/0 boundary, represented as s32
   range crossing sign boundary.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260424-cnums-everywhere-rfc-v1-v3-4-ca434b39a486@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Eduard Zingerman 2026-04-24 15:52:45 -07:00 committed by Alexei Starovoitov
parent bbc6310855
commit 4c0710ab01

View File

@ -2187,4 +2187,84 @@ __naked void tnums_equal_impossible_constant(void *ctx)
: __clobber_all);
}
/*
* 32-bit range starts before 64-bit range low bits in each 2^32 block.
*
* N*2^32 (N+1)*2^32 (N+2)*2^32 (N+3)*2^32
* ||----|=====|--|----------||----|=====|-------------||--|-|=====|-------------||
* |< b >| | |< b >| | |< b >|
* | | | |
* |<---------------+- a -+---------------->|
* | |
* |< t >| refined r0 range
*
* a = u64 [0x1'00000008, 0x3'00000001]
* b = u32 [2, 5]
* t = u64 [0x2'00000002, 0x2'00000005]
*/
SEC("socket")
__success
__flag(BPF_F_TEST_REG_INVARIANTS)
__naked void deduce64_from_32_before_block_start(void)
{
asm volatile (" \
call %[bpf_get_prandom_u32]; \
r1 = 0x100000008 ll; \
if r0 < r1 goto 2f; \
r1 = 0x300000001 ll; \
if r0 > r1 goto 2f; /* u64: [0x1'00000008, 0x3'00000001] */ \
if w0 < 2 goto 2f; \
if w0 > 5 goto 2f; /* u32: [2, 5] */ \
r2 = 0x200000002 ll; \
r3 = 0x200000005 ll; \
if r0 >= r2 goto 1f; /* should be always true */ \
r10 = 0; /* dead code */ \
1: if r0 <= r3 goto 2f; /* should be always true */ \
r10 = 0; /* dead code */ \
2: exit; \
"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
/*
* 32-bit range crossing U32_MAX / 0 boundary.
*
* N*2^32 (N+1)*2^32 (N+2)*2^32 (N+3)*2^32
* ||===|---------|------|===||===|----------------|===||===|---------|------|===||
* |b >| | |< b||b >| |< b||b >| | |< b|
* | | | |
* |<-----+----------------- a --------------+-------->|
* | |
* |<---------------- t ------------->| refined r0 range
*
* a = u64 [0x1'00000006, 0x2'FFFFFFEF]
* b = s32 [-16, 5] (u32 wrapping [0xFFFFFFF0, 0x00000005])
* t = u64 [0x1'FFFFFFF0, 0x2'00000005]
*/
SEC("socket")
__success
__flag(BPF_F_TEST_REG_INVARIANTS)
__naked void deduce64_from_32_wrapping_32bit(void)
{
asm volatile (" \
call %[bpf_get_prandom_u32]; \
r1 = 0x100000006 ll; \
if r0 < r1 goto 2f; \
r1 = 0x2ffffffef ll; \
if r0 > r1 goto 2f; /* u64: [0x1'00000006, 0x2'FFFFFFEF] */ \
if w0 s< -16 goto 2f; \
if w0 s> 5 goto 2f; /* s32: [-16, 5] */ \
r1 = 0x1fffffff0 ll; \
r2 = 0x200000005 ll; \
if r0 >= r1 goto 1f; /* should be always true */ \
r10 = 0; /* dead code */ \
1: if r0 <= r2 goto 2f; /* should be always true */ \
r10 = 0; /* dead code */ \
2: exit; \
"
:: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
char _license[] SEC("license") = "GPL";