2 #include <linux/types.h>
12 #include <linux/unistd.h>
13 #include <linux/filter.h>
14 #include <linux/bpf_perf_event.h>
15 #include <linux/bpf.h>
19 #include "../../../include/linux/filter.h"
22 # define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
26 #define MAX_MATCHES 16
28 struct bpf_align_test {
30 struct bpf_insn insns[MAX_INSNS];
36 enum bpf_prog_type prog_type;
37 const char *matches[MAX_MATCHES];
40 static struct bpf_align_test tests[] = {
44 BPF_MOV64_IMM(BPF_REG_3, 2),
45 BPF_MOV64_IMM(BPF_REG_3, 4),
46 BPF_MOV64_IMM(BPF_REG_3, 8),
47 BPF_MOV64_IMM(BPF_REG_3, 16),
48 BPF_MOV64_IMM(BPF_REG_3, 32),
49 BPF_MOV64_IMM(BPF_REG_0, 0),
52 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
54 "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
55 "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
56 "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
57 "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
58 "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
64 BPF_MOV64_IMM(BPF_REG_3, 1),
65 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
66 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
67 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
68 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
69 BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4),
70 BPF_MOV64_IMM(BPF_REG_4, 32),
71 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
72 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
73 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
74 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
75 BPF_MOV64_IMM(BPF_REG_0, 0),
78 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
80 "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
81 "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
82 "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
83 "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
84 "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
85 "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
86 "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
87 "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
88 "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
89 "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
90 "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
96 BPF_MOV64_IMM(BPF_REG_3, 4),
97 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4),
98 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2),
99 BPF_MOV64_IMM(BPF_REG_4, 8),
100 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
101 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
102 BPF_MOV64_IMM(BPF_REG_0, 0),
105 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
107 "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
108 "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp",
109 "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp",
110 "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
111 "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp",
112 "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
118 BPF_MOV64_IMM(BPF_REG_3, 7),
119 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1),
120 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2),
121 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4),
122 BPF_MOV64_IMM(BPF_REG_0, 0),
125 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
127 "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
128 "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
129 "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
130 "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp",
134 #define PREP_PKT_POINTERS \
135 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
136 offsetof(struct __sk_buff, data)), \
137 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \
138 offsetof(struct __sk_buff, data_end))
140 #define LOAD_UNKNOWN(DST_REG) \
142 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \
143 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \
144 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \
146 BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0)
149 .descr = "unknown shift",
151 LOAD_UNKNOWN(BPF_REG_3),
152 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
153 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
154 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
155 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
156 LOAD_UNKNOWN(BPF_REG_4),
157 BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5),
158 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
159 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
160 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
161 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
162 BPF_MOV64_IMM(BPF_REG_0, 0),
165 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
167 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
168 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp",
169 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp",
170 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp",
171 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp",
172 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp",
173 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp",
174 "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp",
175 "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp",
176 "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp",
177 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp",
181 .descr = "unknown mul",
183 LOAD_UNKNOWN(BPF_REG_3),
184 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
185 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1),
186 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
187 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
188 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
189 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4),
190 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
191 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8),
192 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
193 BPF_MOV64_IMM(BPF_REG_0, 0),
196 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
198 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
199 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
200 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp",
201 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
202 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp",
203 "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
204 "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp",
205 "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
206 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp",
207 "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp"
211 .descr = "packet const offset",
214 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
216 BPF_MOV64_IMM(BPF_REG_0, 0),
218 /* Skip over ethernet header. */
219 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
220 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
221 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
222 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
225 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0),
226 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1),
227 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2),
228 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3),
229 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0),
230 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2),
231 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
233 BPF_MOV64_IMM(BPF_REG_0, 0),
236 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
238 "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp",
239 "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp",
240 "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp",
241 "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp",
242 "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
243 "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
247 .descr = "packet variable offset",
249 LOAD_UNKNOWN(BPF_REG_6),
250 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
252 /* First, add a constant to the R5 packet pointer,
253 * then a variable with a known alignment.
255 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
256 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
257 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
258 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
259 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
260 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
262 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
264 /* Now, test in the other direction. Adding first
265 * the variable offset to R5, then the constant.
267 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
268 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
269 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
270 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
271 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
272 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
274 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
276 /* Test multiple accumulations of unknown values
277 * into a packet pointer.
279 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
280 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
281 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
282 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4),
283 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
284 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
285 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
286 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
288 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
290 BPF_MOV64_IMM(BPF_REG_0, 0),
293 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
295 /* Calculated offset in R6 has unknown value, but known
298 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp",
300 /* Offset is added to packet pointer R5, resulting in known
301 * auxiliary alignment and offset.
303 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
305 /* At the time the word size load is performed from R5,
306 * it's total offset is NET_IP_ALIGN + reg->off (0) +
307 * reg->aux_off (14) which is 16. Then the variable
308 * offset is considered using reg->aux_off_align which
309 * is 4 and meets the load's requirements.
311 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
314 /* Variable offset is added to R5 packet pointer,
315 * resulting in auxiliary alignment of 4.
317 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
319 /* Constant offset is added to R5, resulting in
322 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
324 /* At the time the word size load is performed from R5,
325 * it's total offset is NET_IP_ALIGN + reg->off (14) which
326 * is 16. Then the variable offset is considered using
327 * reg->aux_off_align which is 4 and meets the load's
330 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
332 /* Constant offset is added to R5 packet pointer,
333 * resulting in reg->off value of 14.
335 "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp",
336 /* Variable offset is added to R5, resulting in an
337 * auxiliary offset of 14, and an auxiliary alignment of 4.
339 "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
340 /* Constant is added to R5 again, setting reg->off to 4. */
341 "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
342 /* And once more we add a variable, which causes an accumulation
343 * of reg->off into reg->aux_off_align, with resulting value of
344 * 18. The auxiliary alignment stays at 4.
346 "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
347 /* At the time the word size load is performed from R5,
348 * it's total offset is NET_IP_ALIGN + reg->off (0) +
349 * reg->aux_off (18) which is 20. Then the variable offset
350 * is considered using reg->aux_off_align which is 4 and meets
351 * the load's requirements.
353 "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
358 static int probe_filter_length(const struct bpf_insn *fp)
362 for (len = MAX_INSNS - 1; len > 0; --len)
363 if (fp[len].code != 0 || fp[len].imm != 0)
368 static char bpf_vlog[32768];
370 static int do_test_single(struct bpf_align_test *test)
372 struct bpf_insn *prog = test->insns;
373 int prog_type = test->prog_type;
378 prog_len = probe_filter_length(prog);
379 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
380 prog, prog_len, 1, "GPL", 0,
381 bpf_vlog, sizeof(bpf_vlog));
383 printf("Failed to load program.\n");
384 printf("%s", bpf_vlog);
388 for (i = 0; i < MAX_MATCHES; i++) {
389 const char *t, *m = test->matches[i];
393 t = strstr(bpf_vlog, m);
395 printf("Failed to find match: %s\n", m);
397 printf("%s", bpf_vlog);
406 static int do_test(unsigned int from, unsigned int to)
412 for (i = from; i < to; i++) {
413 struct bpf_align_test *test = &tests[i];
416 printf("Test %3d: %s ... ",
418 fail = do_test_single(test);
427 printf("Results: %d pass %d fail\n",
432 int main(int argc, char **argv)
434 unsigned int from = 0, to = ARRAY_SIZE(tests);
437 unsigned int l = atoi(argv[argc - 2]);
438 unsigned int u = atoi(argv[argc - 1]);
440 if (l < to && u < to) {
444 } else if (argc == 2) {
445 unsigned int t = atoi(argv[argc - 1]);
452 return do_test(from, to);