1// SPDX-License-Identifier: GPL-2.0
2/* Converted from tools/testing/selftests/bpf/verifier/div_overflow.c */
3
4#include <linux/bpf.h>
5#include <bpf/bpf_helpers.h>
6#include <limits.h>
7#include "bpf_misc.h"
8
9/* Just make sure that JITs used udiv/umod as otherwise we get
10 * an exception from INT_MIN/-1 overflow similarly as with div
11 * by zero.
12 */
13
14SEC("tc")
15__description("DIV32 overflow, check 1")
16__success __retval(0)
17__naked void div32_overflow_check_1(void)
18{
19	asm volatile ("					\
20	w1 = -1;					\
21	w0 = %[int_min];				\
22	w0 /= w1;					\
23	exit;						\
24"	:
25	: __imm_const(int_min, INT_MIN)
26	: __clobber_all);
27}
28
29SEC("tc")
30__description("DIV32 overflow, check 2")
31__success __retval(0)
32__naked void div32_overflow_check_2(void)
33{
34	asm volatile ("					\
35	w0 = %[int_min];				\
36	w0 /= -1;					\
37	exit;						\
38"	:
39	: __imm_const(int_min, INT_MIN)
40	: __clobber_all);
41}
42
43SEC("tc")
44__description("DIV64 overflow, check 1")
45__success __retval(0)
46__naked void div64_overflow_check_1(void)
47{
48	asm volatile ("					\
49	r1 = -1;					\
50	r2 = %[llong_min] ll;				\
51	r2 /= r1;					\
52	w0 = 0;						\
53	if r0 == r2 goto l0_%=;				\
54	w0 = 1;						\
55l0_%=:	exit;						\
56"	:
57	: __imm_const(llong_min, LLONG_MIN)
58	: __clobber_all);
59}
60
61SEC("tc")
62__description("DIV64 overflow, check 2")
63__success __retval(0)
64__naked void div64_overflow_check_2(void)
65{
66	asm volatile ("					\
67	r1 = %[llong_min] ll;				\
68	r1 /= -1;					\
69	w0 = 0;						\
70	if r0 == r1 goto l0_%=;				\
71	w0 = 1;						\
72l0_%=:	exit;						\
73"	:
74	: __imm_const(llong_min, LLONG_MIN)
75	: __clobber_all);
76}
77
78SEC("tc")
79__description("MOD32 overflow, check 1")
80__success __retval(INT_MIN)
81__naked void mod32_overflow_check_1(void)
82{
83	asm volatile ("					\
84	w1 = -1;					\
85	w0 = %[int_min];				\
86	w0 %%= w1;					\
87	exit;						\
88"	:
89	: __imm_const(int_min, INT_MIN)
90	: __clobber_all);
91}
92
93SEC("tc")
94__description("MOD32 overflow, check 2")
95__success __retval(INT_MIN)
96__naked void mod32_overflow_check_2(void)
97{
98	asm volatile ("					\
99	w0 = %[int_min];				\
100	w0 %%= -1;					\
101	exit;						\
102"	:
103	: __imm_const(int_min, INT_MIN)
104	: __clobber_all);
105}
106
107SEC("tc")
108__description("MOD64 overflow, check 1")
109__success __retval(1)
110__naked void mod64_overflow_check_1(void)
111{
112	asm volatile ("					\
113	r1 = -1;					\
114	r2 = %[llong_min] ll;				\
115	r3 = r2;					\
116	r2 %%= r1;					\
117	w0 = 0;						\
118	if r3 != r2 goto l0_%=;				\
119	w0 = 1;						\
120l0_%=:	exit;						\
121"	:
122	: __imm_const(llong_min, LLONG_MIN)
123	: __clobber_all);
124}
125
126SEC("tc")
127__description("MOD64 overflow, check 2")
128__success __retval(1)
129__naked void mod64_overflow_check_2(void)
130{
131	asm volatile ("					\
132	r2 = %[llong_min] ll;				\
133	r3 = r2;					\
134	r2 %%= -1;					\
135	w0 = 0;						\
136	if r3 != r2 goto l0_%=;				\
137	w0 = 1;						\
138l0_%=:	exit;						\
139"	:
140	: __imm_const(llong_min, LLONG_MIN)
141	: __clobber_all);
142}
143
144char _license[] SEC("license") = "GPL";
145