1 /*-
2 * Copyright (c) 2011-2012 Alexander Nasonov.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <bpfjit.h>
31
32 #include <stdint.h>
33
34 #include "util.h"
35 #include "tests.h"
36
37 static void
test_alu_add_k(void)38 test_alu_add_k(void)
39 {
40 static struct bpf_insn insns[] = {
41 BPF_STMT(BPF_LD+BPF_IMM, 3),
42 BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, 2),
43 BPF_STMT(BPF_RET+BPF_A, 0)
44 };
45
46 bpfjit_func_t code;
47 uint8_t pkt[1]; /* the program doesn't read any data */
48
49 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
50
51 CHECK(bpf_validate(insns, insn_count));
52
53 code = bpfjit_generate_code(NULL, insns, insn_count);
54 REQUIRE(code != NULL);
55
56 CHECK(jitcall(code, pkt, 1, 1) == 5);
57
58 bpfjit_free_code(code);
59 }
60
61 static void
test_alu_sub_k(void)62 test_alu_sub_k(void)
63 {
64 static struct bpf_insn insns[] = {
65 BPF_STMT(BPF_LD+BPF_IMM, 1),
66 BPF_STMT(BPF_ALU+BPF_SUB+BPF_K, 2),
67 BPF_STMT(BPF_RET+BPF_A, 0)
68 };
69
70 bpfjit_func_t code;
71 uint8_t pkt[1]; /* the program doesn't read any data */
72
73 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
74
75 CHECK(bpf_validate(insns, insn_count));
76
77 code = bpfjit_generate_code(NULL, insns, insn_count);
78 REQUIRE(code != NULL);
79
80 CHECK(jitcall(code, pkt, 1, 1) == UINT32_MAX);
81
82 bpfjit_free_code(code);
83 }
84
85 static void
test_alu_mul_k(void)86 test_alu_mul_k(void)
87 {
88 static struct bpf_insn insns[] = {
89 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
90 BPF_STMT(BPF_ALU+BPF_MUL+BPF_K, 3),
91 BPF_STMT(BPF_RET+BPF_A, 0)
92 };
93
94 bpfjit_func_t code;
95 uint8_t pkt[1]; /* the program doesn't read any data */
96
97 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
98
99 CHECK(bpf_validate(insns, insn_count));
100
101 code = bpfjit_generate_code(NULL, insns, insn_count);
102 REQUIRE(code != NULL);
103
104 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0xfffffffd));
105
106 bpfjit_free_code(code);
107 }
108
109 static void
test_alu_div0_k(void)110 test_alu_div0_k(void)
111 {
112 static struct bpf_insn insns[] = {
113 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 0),
114 BPF_STMT(BPF_RET+BPF_A, 0)
115 };
116
117 bpfjit_func_t code;
118 uint8_t pkt[1]; /* the program doesn't read any data */
119
120 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
121
122 //CHECK(bpf_validate(insns, insn_count));
123
124 code = bpfjit_generate_code(NULL, insns, insn_count);
125 REQUIRE(code != NULL);
126
127 CHECK(jitcall(code, pkt, 1, 1) == 0);
128
129 bpfjit_free_code(code);
130 }
131
132 static void
test_alu_div1_k(void)133 test_alu_div1_k(void)
134 {
135 static struct bpf_insn insns[] = {
136 BPF_STMT(BPF_LD+BPF_IMM, 7),
137 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 1),
138 BPF_STMT(BPF_RET+BPF_A, 0)
139 };
140
141 bpfjit_func_t code;
142 uint8_t pkt[1]; /* the program doesn't read any data */
143
144 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
145
146 CHECK(bpf_validate(insns, insn_count));
147
148 code = bpfjit_generate_code(NULL, insns, insn_count);
149 REQUIRE(code != NULL);
150
151 CHECK(jitcall(code, pkt, 1, 1) == 7);
152
153 bpfjit_free_code(code);
154 }
155
156 static void
test_alu_div2_k(void)157 test_alu_div2_k(void)
158 {
159 static struct bpf_insn insns[] = {
160 BPF_STMT(BPF_LD+BPF_IMM, 7),
161 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 2),
162 BPF_STMT(BPF_RET+BPF_A, 0)
163 };
164
165 bpfjit_func_t code;
166 uint8_t pkt[1]; /* the program doesn't read any data */
167
168 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
169
170 CHECK(bpf_validate(insns, insn_count));
171
172 code = bpfjit_generate_code(NULL, insns, insn_count);
173 REQUIRE(code != NULL);
174
175 CHECK(jitcall(code, pkt, 1, 1) == 3);
176
177 bpfjit_free_code(code);
178 }
179
180 static void
test_alu_div4_k(void)181 test_alu_div4_k(void)
182 {
183 static struct bpf_insn insns[] = {
184 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
185 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 4),
186 BPF_STMT(BPF_RET+BPF_A, 0)
187 };
188
189 bpfjit_func_t code;
190 uint8_t pkt[1]; /* the program doesn't read any data */
191
192 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
193
194 CHECK(bpf_validate(insns, insn_count));
195
196 code = bpfjit_generate_code(NULL, insns, insn_count);
197 REQUIRE(code != NULL);
198
199 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x3fffffff));
200
201 bpfjit_free_code(code);
202 }
203
204 static void
test_alu_div10_k(void)205 test_alu_div10_k(void)
206 {
207 static struct bpf_insn insns[] = {
208 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
209 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 10),
210 BPF_STMT(BPF_RET+BPF_A, 0)
211 };
212
213 bpfjit_func_t code;
214 uint8_t pkt[1]; /* the program doesn't read any data */
215
216 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
217
218 CHECK(bpf_validate(insns, insn_count));
219
220 code = bpfjit_generate_code(NULL, insns, insn_count);
221 REQUIRE(code != NULL);
222
223 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484384));
224
225 bpfjit_free_code(code);
226 }
227
228 static void
test_alu_div10000_k(void)229 test_alu_div10000_k(void)
230 {
231 static struct bpf_insn insns[] = {
232 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
233 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, 10000),
234 BPF_STMT(BPF_RET+BPF_A, 0)
235 };
236
237 bpfjit_func_t code;
238 uint8_t pkt[1]; /* the program doesn't read any data */
239
240 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
241
242 CHECK(bpf_validate(insns, insn_count));
243
244 code = bpfjit_generate_code(NULL, insns, insn_count);
245 REQUIRE(code != NULL);
246
247 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484));
248
249 bpfjit_free_code(code);
250 }
251
252 static void
test_alu_div7609801_k(void)253 test_alu_div7609801_k(void)
254 {
255 static struct bpf_insn insns[] = {
256 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294967295)),
257 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, UINT32_C(7609801)),
258 BPF_STMT(BPF_RET+BPF_A, 0)
259 };
260
261 bpfjit_func_t code;
262 uint8_t pkt[1]; /* the program doesn't read any data */
263
264 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
265
266 CHECK(bpf_validate(insns, insn_count));
267
268 code = bpfjit_generate_code(NULL, insns, insn_count);
269 REQUIRE(code != NULL);
270
271 CHECK(jitcall(code, pkt, 1, 1) == 564);
272
273 bpfjit_free_code(code);
274 }
275
276 static void
test_alu_div0x80000000_k(void)277 test_alu_div0x80000000_k(void)
278 {
279 static struct bpf_insn insns[] = {
280 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffde)),
281 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, UINT32_C(0x80000000)),
282 BPF_STMT(BPF_RET+BPF_A, 0)
283 };
284
285 bpfjit_func_t code;
286 uint8_t pkt[1]; /* the program doesn't read any data */
287
288 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
289
290 CHECK(bpf_validate(insns, insn_count));
291
292 code = bpfjit_generate_code(NULL, insns, insn_count);
293 REQUIRE(code != NULL);
294
295 CHECK(jitcall(code, pkt, 1, 1) == 1);
296
297 bpfjit_free_code(code);
298 }
299
300 static void
test_alu_and_k(void)301 test_alu_and_k(void)
302 {
303 static struct bpf_insn insns[] = {
304 BPF_STMT(BPF_LD+BPF_IMM, 0xdead),
305 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, 0xbeef),
306 BPF_STMT(BPF_RET+BPF_A, 0)
307 };
308
309 bpfjit_func_t code;
310 uint8_t pkt[1]; /* the program doesn't read any data */
311
312 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
313
314 CHECK(bpf_validate(insns, insn_count));
315
316 code = bpfjit_generate_code(NULL, insns, insn_count);
317 REQUIRE(code != NULL);
318
319 CHECK(jitcall(code, pkt, 1, 1) == (0xdead&0xbeef));
320
321 bpfjit_free_code(code);
322 }
323
324 static void
test_alu_or_k(void)325 test_alu_or_k(void)
326 {
327 static struct bpf_insn insns[] = {
328 BPF_STMT(BPF_LD+BPF_IMM, 0xdead0000),
329 BPF_STMT(BPF_ALU+BPF_OR+BPF_K, 0x0000beef),
330 BPF_STMT(BPF_RET+BPF_A, 0)
331 };
332
333 bpfjit_func_t code;
334 uint8_t pkt[1]; /* the program doesn't read any data */
335
336 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
337
338 CHECK(bpf_validate(insns, insn_count));
339
340 code = bpfjit_generate_code(NULL, insns, insn_count);
341 REQUIRE(code != NULL);
342
343 CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
344
345 bpfjit_free_code(code);
346 }
347
348 static void
test_alu_lsh_k(void)349 test_alu_lsh_k(void)
350 {
351 static struct bpf_insn insns[] = {
352 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
353 BPF_STMT(BPF_ALU+BPF_LSH+BPF_K, 16),
354 BPF_STMT(BPF_RET+BPF_A, 0)
355 };
356
357 bpfjit_func_t code;
358 uint8_t pkt[1]; /* the program doesn't read any data */
359
360 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
361
362 CHECK(bpf_validate(insns, insn_count));
363
364 code = bpfjit_generate_code(NULL, insns, insn_count);
365 REQUIRE(code != NULL);
366
367 CHECK(jitcall(code, pkt, 1, 1) == 0xbeef0000);
368
369 bpfjit_free_code(code);
370 }
371
372 static void
test_alu_lsh0_k(void)373 test_alu_lsh0_k(void)
374 {
375 static struct bpf_insn insns[] = {
376 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
377 BPF_STMT(BPF_ALU+BPF_LSH+BPF_K, 0),
378 BPF_STMT(BPF_RET+BPF_A, 0)
379 };
380
381 bpfjit_func_t code;
382 uint8_t pkt[1]; /* the program doesn't read any data */
383
384 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
385
386 CHECK(bpf_validate(insns, insn_count));
387
388 code = bpfjit_generate_code(NULL, insns, insn_count);
389 REQUIRE(code != NULL);
390
391 CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
392
393 bpfjit_free_code(code);
394 }
395
396 static void
test_alu_rsh_k(void)397 test_alu_rsh_k(void)
398 {
399 static struct bpf_insn insns[] = {
400 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
401 BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 16),
402 BPF_STMT(BPF_RET+BPF_A, 0)
403 };
404
405 bpfjit_func_t code;
406 uint8_t pkt[1]; /* the program doesn't read any data */
407
408 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
409
410 CHECK(bpf_validate(insns, insn_count));
411
412 code = bpfjit_generate_code(NULL, insns, insn_count);
413 REQUIRE(code != NULL);
414
415 CHECK(jitcall(code, pkt, 1, 1) == 0x0000dead);
416
417 bpfjit_free_code(code);
418 }
419
420 static void
test_alu_rsh0_k(void)421 test_alu_rsh0_k(void)
422 {
423 static struct bpf_insn insns[] = {
424 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
425 BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 0),
426 BPF_STMT(BPF_RET+BPF_A, 0)
427 };
428
429 bpfjit_func_t code;
430 uint8_t pkt[1]; /* the program doesn't read any data */
431
432 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
433
434 CHECK(bpf_validate(insns, insn_count));
435
436 code = bpfjit_generate_code(NULL, insns, insn_count);
437 REQUIRE(code != NULL);
438
439 CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
440
441 bpfjit_free_code(code);
442 }
443
444 static void
test_alu_modulo_k(void)445 test_alu_modulo_k(void)
446 {
447 static struct bpf_insn insns[] = {
448 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0x7fffff77)),
449
450 /* (7FFFFF77 * 0FFFFF77) = 07FFFFB2,F0004951 */
451 BPF_STMT(BPF_ALU+BPF_MUL+BPF_K, UINT32_C(0x0fffff77)),
452
453 /* 07FFFFB2,F0004951 << 1 = 0FFFFF65,E00092A2 */
454 BPF_STMT(BPF_ALU+BPF_LSH+BPF_K, 1),
455
456 /* 0FFFFF65,E00092A2 + DDDDDDDD = 0FFFFF66,BDDE707F */
457 BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, UINT32_C(0xdddddddd)),
458
459 /* 0FFFFF66,BDDE707F - FFFFFFFF = 0FFFFF65,BDDE7080 */
460 BPF_STMT(BPF_ALU+BPF_SUB+BPF_K, UINT32_C(0xffffffff)),
461
462 /* 0FFFFF65,BDDE7080 | 0000030C = 0FFFFF65,BDDE738C */
463 BPF_STMT(BPF_ALU+BPF_OR+BPF_K, UINT32_C(0x0000030c)),
464
465 /* -0FFFFF65,BDDE738C mod(2^64) = F000009A,42218C74 */
466 BPF_STMT(BPF_ALU+BPF_NEG, 0),
467
468 /* F000009A,42218C74 & FFFFFF0F = F000009A,42218C04 */
469 BPF_STMT(BPF_ALU+BPF_AND+BPF_K, UINT32_C(0xffffff0f)),
470
471 /* F000009A,42218C74 >> 3 = 1E000013,48443180 */
472 /* 00000000,42218C74 >> 3 = 00000000,08443180 */
473 BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 3),
474
475 /* 00000000,08443180 * 7FFFFF77 = 042218BB,93818280 */
476 BPF_STMT(BPF_ALU+BPF_MUL+BPF_K, UINT32_C(0x7fffff77)),
477
478 /* 042218BB,93818280 / DEAD = 000004C0,71CBBBC3 */
479 /* 00000000,93818280 / DEAD = 00000000,0000A994 */
480 BPF_STMT(BPF_ALU+BPF_DIV+BPF_K, UINT32_C(0xdead)),
481
482 BPF_STMT(BPF_RET+BPF_A, 0)
483 };
484
485 bpfjit_func_t code;
486 uint8_t pkt[1]; /* the program doesn't read any data */
487
488 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
489
490 CHECK(bpf_validate(insns, insn_count));
491
492 code = bpfjit_generate_code(NULL, insns, insn_count);
493 REQUIRE(code != NULL);
494
495 CHECK(jitcall(code, pkt, 1, 1) != UINT32_C(0x71cbbbc3));
496 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x0000a994));
497
498
499 bpfjit_free_code(code);
500 }
501
502 static void
test_alu_add_x(void)503 test_alu_add_x(void)
504 {
505 static struct bpf_insn insns[] = {
506 BPF_STMT(BPF_LD+BPF_IMM, 3),
507 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2),
508 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
509 BPF_STMT(BPF_RET+BPF_A, 0)
510 };
511
512 bpfjit_func_t code;
513 uint8_t pkt[1]; /* the program doesn't read any data */
514
515 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
516
517 CHECK(bpf_validate(insns, insn_count));
518
519 code = bpfjit_generate_code(NULL, insns, insn_count);
520 REQUIRE(code != NULL);
521
522 CHECK(jitcall(code, pkt, 1, 1) == 5);
523
524 bpfjit_free_code(code);
525 }
526
527 static void
test_alu_sub_x(void)528 test_alu_sub_x(void)
529 {
530 static struct bpf_insn insns[] = {
531 BPF_STMT(BPF_LD+BPF_IMM, 1),
532 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2),
533 BPF_STMT(BPF_ALU+BPF_SUB+BPF_X, 0),
534 BPF_STMT(BPF_RET+BPF_A, 0)
535 };
536
537 bpfjit_func_t code;
538 uint8_t pkt[1]; /* the program doesn't read any data */
539
540 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
541
542 CHECK(bpf_validate(insns, insn_count));
543
544 code = bpfjit_generate_code(NULL, insns, insn_count);
545 REQUIRE(code != NULL);
546
547 CHECK(jitcall(code, pkt, 1, 1) == UINT32_MAX);
548
549 bpfjit_free_code(code);
550 }
551
552 static void
test_alu_mul_x(void)553 test_alu_mul_x(void)
554 {
555 static struct bpf_insn insns[] = {
556 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
557 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 3),
558 BPF_STMT(BPF_ALU+BPF_MUL+BPF_X, 0),
559 BPF_STMT(BPF_RET+BPF_A, 0)
560 };
561
562 bpfjit_func_t code;
563 uint8_t pkt[1]; /* the program doesn't read any data */
564
565 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
566
567 CHECK(bpf_validate(insns, insn_count));
568
569 code = bpfjit_generate_code(NULL, insns, insn_count);
570 REQUIRE(code != NULL);
571
572 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0xfffffffd));
573
574 bpfjit_free_code(code);
575 }
576
577 static void
test_alu_div0_x(void)578 test_alu_div0_x(void)
579 {
580 static struct bpf_insn insns[] = {
581 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0),
582 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
583 BPF_STMT(BPF_RET+BPF_A, 0)
584 };
585
586 bpfjit_func_t code;
587 uint8_t pkt[1]; /* the program doesn't read any data */
588
589 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
590
591 CHECK(bpf_validate(insns, insn_count));
592
593 code = bpfjit_generate_code(NULL, insns, insn_count);
594 REQUIRE(code != NULL);
595
596 CHECK(jitcall(code, pkt, 1, 1) == 0);
597
598 bpfjit_free_code(code);
599 }
600
601 static void
test_alu_div1_x(void)602 test_alu_div1_x(void)
603 {
604 static struct bpf_insn insns[] = {
605 BPF_STMT(BPF_LD+BPF_IMM, 7),
606 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 1),
607 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
608 BPF_STMT(BPF_RET+BPF_A, 0)
609 };
610
611 bpfjit_func_t code;
612 uint8_t pkt[1]; /* the program doesn't read any data */
613
614 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
615
616 CHECK(bpf_validate(insns, insn_count));
617
618 code = bpfjit_generate_code(NULL, insns, insn_count);
619 REQUIRE(code != NULL);
620
621 CHECK(jitcall(code, pkt, 1, 1) == 7);
622
623 bpfjit_free_code(code);
624 }
625
626 static void
test_alu_div2_x(void)627 test_alu_div2_x(void)
628 {
629 static struct bpf_insn insns[] = {
630 BPF_STMT(BPF_LD+BPF_IMM, 7),
631 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2),
632 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
633 BPF_STMT(BPF_RET+BPF_A, 0)
634 };
635
636 bpfjit_func_t code;
637 uint8_t pkt[1]; /* the program doesn't read any data */
638
639 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
640
641 CHECK(bpf_validate(insns, insn_count));
642
643 code = bpfjit_generate_code(NULL, insns, insn_count);
644 REQUIRE(code != NULL);
645
646 CHECK(jitcall(code, pkt, 1, 1) == 3);
647
648 bpfjit_free_code(code);
649 }
650
651 static void
test_alu_div4_x(void)652 test_alu_div4_x(void)
653 {
654 static struct bpf_insn insns[] = {
655 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0xffffffff)),
656 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 4),
657 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
658 BPF_STMT(BPF_RET+BPF_A, 0)
659 };
660
661 bpfjit_func_t code;
662 uint8_t pkt[1]; /* the program doesn't read any data */
663
664 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
665
666 CHECK(bpf_validate(insns, insn_count));
667
668 code = bpfjit_generate_code(NULL, insns, insn_count);
669 REQUIRE(code != NULL);
670
671 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x3fffffff));
672
673 bpfjit_free_code(code);
674 }
675
676 static void
test_alu_div10_x(void)677 test_alu_div10_x(void)
678 {
679 static struct bpf_insn insns[] = {
680 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
681 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 10),
682 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
683 BPF_STMT(BPF_RET+BPF_A, 0)
684 };
685
686 bpfjit_func_t code;
687 uint8_t pkt[1]; /* the program doesn't read any data */
688
689 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
690
691 CHECK(bpf_validate(insns, insn_count));
692
693 code = bpfjit_generate_code(NULL, insns, insn_count);
694 REQUIRE(code != NULL);
695
696 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484384));
697
698 bpfjit_free_code(code);
699 }
700
701 static void
test_alu_div10000_x(void)702 test_alu_div10000_x(void)
703 {
704 static struct bpf_insn insns[] = {
705 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294843849)),
706 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 10000),
707 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
708 BPF_STMT(BPF_RET+BPF_A, 0)
709 };
710
711 bpfjit_func_t code;
712 uint8_t pkt[1]; /* the program doesn't read any data */
713
714 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
715
716 CHECK(bpf_validate(insns, insn_count));
717
718 code = bpfjit_generate_code(NULL, insns, insn_count);
719 REQUIRE(code != NULL);
720
721 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(429484));
722
723 bpfjit_free_code(code);
724 }
725
726 static void
test_alu_div7609801_x(void)727 test_alu_div7609801_x(void)
728 {
729 static struct bpf_insn insns[] = {
730 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(4294967295)),
731 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, UINT32_C(7609801)),
732 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
733 BPF_STMT(BPF_RET+BPF_A, 0)
734 };
735
736 bpfjit_func_t code;
737 uint8_t pkt[1]; /* the program doesn't read any data */
738
739 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
740
741 CHECK(bpf_validate(insns, insn_count));
742
743 code = bpfjit_generate_code(NULL, insns, insn_count);
744 REQUIRE(code != NULL);
745
746 CHECK(jitcall(code, pkt, 1, 1) == 564);
747
748 bpfjit_free_code(code);
749 }
750
751 static void
test_alu_div0x80000000_x(void)752 test_alu_div0x80000000_x(void)
753 {
754 static struct bpf_insn insns[] = {
755 BPF_STMT(BPF_LD+BPF_IMM, UINT32_MAX - 33),
756 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, UINT32_C(0x80000000)),
757 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
758 BPF_STMT(BPF_RET+BPF_A, 0)
759 };
760
761 bpfjit_func_t code;
762 uint8_t pkt[1]; /* the program doesn't read any data */
763
764 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
765
766 CHECK(bpf_validate(insns, insn_count));
767
768 code = bpfjit_generate_code(NULL, insns, insn_count);
769 REQUIRE(code != NULL);
770
771 CHECK(jitcall(code, pkt, 1, 1) == 1);
772
773 bpfjit_free_code(code);
774 }
775
776 static void
test_alu_and_x(void)777 test_alu_and_x(void)
778 {
779 static struct bpf_insn insns[] = {
780 BPF_STMT(BPF_LD+BPF_IMM, 0xdead),
781 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0xbeef),
782 BPF_STMT(BPF_ALU+BPF_AND+BPF_X, 0),
783 BPF_STMT(BPF_RET+BPF_A, 0)
784 };
785
786 bpfjit_func_t code;
787 uint8_t pkt[1]; /* the program doesn't read any data */
788
789 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
790
791 CHECK(bpf_validate(insns, insn_count));
792
793 code = bpfjit_generate_code(NULL, insns, insn_count);
794 REQUIRE(code != NULL);
795
796 CHECK(jitcall(code, pkt, 1, 1) == (0xdead&0xbeef));
797
798 bpfjit_free_code(code);
799 }
800
801 static void
test_alu_or_x(void)802 test_alu_or_x(void)
803 {
804 static struct bpf_insn insns[] = {
805 BPF_STMT(BPF_LD+BPF_IMM, 0xdead0000),
806 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0x0000beef),
807 BPF_STMT(BPF_ALU+BPF_OR+BPF_X, 0),
808 BPF_STMT(BPF_RET+BPF_A, 0)
809 };
810
811 bpfjit_func_t code;
812 uint8_t pkt[1]; /* the program doesn't read any data */
813
814 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
815
816 CHECK(bpf_validate(insns, insn_count));
817
818 code = bpfjit_generate_code(NULL, insns, insn_count);
819 REQUIRE(code != NULL);
820
821 CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
822
823 bpfjit_free_code(code);
824 }
825
826 static void
test_alu_lsh_x(void)827 test_alu_lsh_x(void)
828 {
829 static struct bpf_insn insns[] = {
830 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
831 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 16),
832 BPF_STMT(BPF_ALU+BPF_LSH+BPF_X, 0),
833 BPF_STMT(BPF_RET+BPF_A, 0)
834 };
835
836 bpfjit_func_t code;
837 uint8_t pkt[1]; /* the program doesn't read any data */
838
839 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
840
841 CHECK(bpf_validate(insns, insn_count));
842
843 code = bpfjit_generate_code(NULL, insns, insn_count);
844 REQUIRE(code != NULL);
845
846 CHECK(jitcall(code, pkt, 1, 1) == 0xbeef0000);
847
848 bpfjit_free_code(code);
849 }
850
851 static void
test_alu_lsh0_x(void)852 test_alu_lsh0_x(void)
853 {
854 static struct bpf_insn insns[] = {
855 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
856 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0),
857 BPF_STMT(BPF_ALU+BPF_LSH+BPF_X, 0),
858 BPF_STMT(BPF_RET+BPF_A, 0)
859 };
860
861 bpfjit_func_t code;
862 uint8_t pkt[1]; /* the program doesn't read any data */
863
864 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
865
866 CHECK(bpf_validate(insns, insn_count));
867
868 code = bpfjit_generate_code(NULL, insns, insn_count);
869 REQUIRE(code != NULL);
870
871 CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
872
873 bpfjit_free_code(code);
874 }
875
876 static void
test_alu_rsh_x(void)877 test_alu_rsh_x(void)
878 {
879 static struct bpf_insn insns[] = {
880 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
881 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 16),
882 BPF_STMT(BPF_ALU+BPF_RSH+BPF_X, 0),
883 BPF_STMT(BPF_RET+BPF_A, 0)
884 };
885
886 bpfjit_func_t code;
887 uint8_t pkt[1]; /* the program doesn't read any data */
888
889 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
890
891 CHECK(bpf_validate(insns, insn_count));
892
893 code = bpfjit_generate_code(NULL, insns, insn_count);
894 REQUIRE(code != NULL);
895
896 CHECK(jitcall(code, pkt, 1, 1) == 0x0000dead);
897
898 bpfjit_free_code(code);
899 }
900
901 static void
test_alu_rsh0_x(void)902 test_alu_rsh0_x(void)
903 {
904 static struct bpf_insn insns[] = {
905 BPF_STMT(BPF_LD+BPF_IMM, 0xdeadbeef),
906 BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 0),
907 BPF_STMT(BPF_ALU+BPF_RSH+BPF_X, 0),
908 BPF_STMT(BPF_RET+BPF_A, 0)
909 };
910
911 bpfjit_func_t code;
912 uint8_t pkt[1]; /* the program doesn't read any data */
913
914 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
915
916 CHECK(bpf_validate(insns, insn_count));
917
918 code = bpfjit_generate_code(NULL, insns, insn_count);
919 REQUIRE(code != NULL);
920
921 CHECK(jitcall(code, pkt, 1, 1) == 0xdeadbeef);
922
923 bpfjit_free_code(code);
924 }
925
926 static void
test_alu_neg(void)927 test_alu_neg(void)
928 {
929 static struct bpf_insn insns[] = {
930 BPF_STMT(BPF_LD+BPF_IMM, 777),
931 BPF_STMT(BPF_ALU+BPF_NEG, 0),
932 BPF_STMT(BPF_RET+BPF_A, 0)
933 };
934
935 bpfjit_func_t code;
936 uint8_t pkt[1]; /* the program doesn't read any data */
937
938 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
939
940 CHECK(bpf_validate(insns, insn_count));
941
942 code = bpfjit_generate_code(NULL, insns, insn_count);
943 REQUIRE(code != NULL);
944
945 CHECK(jitcall(code, pkt, 1, 1) == 0u-777u);
946
947 bpfjit_free_code(code);
948 }
949
950 static void
test_alu_modulo_x(void)951 test_alu_modulo_x(void)
952 {
953 static struct bpf_insn insns[] = {
954 BPF_STMT(BPF_LD+BPF_IMM, UINT32_C(0x7fffff77)),
955
956 /* (7FFFFF77 * 0FFFFF77) = 07FFFFB2,F0004951 */
957 BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0x0fffff77)),
958 BPF_STMT(BPF_ALU+BPF_MUL+BPF_X, 0),
959
960 /* 07FFFFB2,F0004951 << 1 = 0FFFFF65,E00092A2 */
961 BPF_STMT(BPF_LDX+BPF_W+BPF_K, 1),
962 BPF_STMT(BPF_ALU+BPF_LSH+BPF_X, 0),
963
964 /* 0FFFFF65,E00092A2 + DDDDDDDD = 0FFFFF66,BDDE707F */
965 BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xdddddddd)),
966 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
967
968 /* 0FFFFF66,BDDE707F - FFFFFFFF = 0FFFFF65,BDDE7080 */
969 BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xffffffff)),
970 BPF_STMT(BPF_ALU+BPF_SUB+BPF_X, 0),
971
972 /* 0FFFFF65,BDDE7080 | 0000030C = 0FFFFF65,BDDE738C */
973 BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0x0000030c)),
974 BPF_STMT(BPF_ALU+BPF_OR+BPF_X, 0),
975
976 /* -0FFFFF65,BDDE738C mod(2^64) = F000009A,42218C74 */
977 BPF_STMT(BPF_ALU+BPF_NEG, 0),
978
979 /* F000009A,42218C74 & FFFFFF0F = F000009A,42218C04 */
980 BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xffffff0f)),
981 BPF_STMT(BPF_ALU+BPF_AND+BPF_X, 0),
982
983 /* F000009A,42218C74 >> 3 = 1E000013,48443180 */
984 /* 00000000,42218C74 >> 3 = 00000000,08443180 */
985 BPF_STMT(BPF_LDX+BPF_W+BPF_K, 3),
986 BPF_STMT(BPF_ALU+BPF_RSH+BPF_X, 0),
987
988 /* 00000000,08443180 * 7FFFFF77 = 042218BB,93818280 */
989 BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0x7fffff77)),
990 BPF_STMT(BPF_ALU+BPF_MUL+BPF_X, 0),
991
992 /* 042218BB,93818280 / DEAD = 000004C0,71CBBBC3 */
993 /* 00000000,93818280 / DEAD = 00000000,0000A994 */
994 BPF_STMT(BPF_LDX+BPF_W+BPF_K, UINT32_C(0xdead)),
995 BPF_STMT(BPF_ALU+BPF_DIV+BPF_X, 0),
996
997 BPF_STMT(BPF_RET+BPF_A, 0)
998 };
999
1000 bpfjit_func_t code;
1001 uint8_t pkt[1]; /* the program doesn't read any data */
1002
1003 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
1004
1005 CHECK(bpf_validate(insns, insn_count));
1006
1007 code = bpfjit_generate_code(NULL, insns, insn_count);
1008 REQUIRE(code != NULL);
1009
1010 CHECK(jitcall(code, pkt, 1, 1) != UINT32_C(0x71cbbbc3));
1011 CHECK(jitcall(code, pkt, 1, 1) == UINT32_C(0x0000a994));
1012
1013
1014 bpfjit_free_code(code);
1015 }
1016
1017 void
test_alu(void)1018 test_alu(void)
1019 {
1020
1021 test_alu_add_k();
1022 test_alu_sub_k();
1023 test_alu_mul_k();
1024 test_alu_div0_k();
1025 test_alu_div1_k();
1026 test_alu_div2_k();
1027 test_alu_div4_k();
1028 test_alu_div10_k();
1029 test_alu_div10000_k();
1030 test_alu_div7609801_k();
1031 test_alu_div0x80000000_k();
1032 test_alu_and_k();
1033 test_alu_or_k();
1034 test_alu_lsh_k();
1035 test_alu_lsh0_k();
1036 test_alu_rsh_k();
1037 test_alu_rsh0_k();
1038 test_alu_modulo_k();
1039
1040 test_alu_add_x();
1041 test_alu_sub_x();
1042 test_alu_mul_x();
1043 test_alu_div0_x();
1044 test_alu_div1_x();
1045 test_alu_div2_x();
1046 test_alu_div4_x();
1047 test_alu_div10_x();
1048 test_alu_div10000_x();
1049 test_alu_div7609801_x();
1050 test_alu_div0x80000000_x();
1051 test_alu_and_x();
1052 test_alu_or_x();
1053 test_alu_lsh_x();
1054 test_alu_lsh0_x();
1055 test_alu_rsh_x();
1056 test_alu_rsh0_x();
1057 test_alu_modulo_x();
1058
1059 test_alu_neg();
1060 }
1061