1 /*-
2 * Copyright (c) 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 #include <string.h>
34
35 #include "util.h"
36 #include "tests.h"
37
38 static void
test_stx1(void)39 test_stx1(void)
40 {
41 static struct bpf_insn insns[] = {
42 BPF_STMT(BPF_LDX+BPF_W+BPF_LEN, 0),
43 BPF_STMT(BPF_STX, 0),
44 BPF_STMT(BPF_LDX+BPF_W+BPF_MEM, 0),
45 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
46 BPF_STMT(BPF_RET+BPF_A, 0)
47 };
48
49 size_t i;
50 bpfjit_func_t code;
51 uint8_t pkt[16]; /* the program doesn't read any data */
52
53 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
54
55 CHECK(bpf_validate(insns, insn_count));
56
57 code = bpfjit_generate_code(NULL, insns, insn_count);
58 REQUIRE(code != NULL);
59
60 for (i = 1; i <= sizeof(pkt); i++)
61 CHECK(jitcall(code, pkt, i, sizeof(pkt)) == i);
62
63 bpfjit_free_code(code);
64 }
65
66 static void
test_stx2(void)67 test_stx2(void)
68 {
69 static struct bpf_insn insns[] = {
70 BPF_STMT(BPF_LDX+BPF_W+BPF_LEN, 0),
71 BPF_STMT(BPF_STX, BPF_MEMWORDS-1),
72 BPF_STMT(BPF_LDX+BPF_W+BPF_MEM, 0),
73 BPF_STMT(BPF_MISC+BPF_TXA, 0),
74 BPF_STMT(BPF_RET+BPF_A, 0)
75 };
76
77 bpfjit_func_t code;
78 uint8_t pkt[1]; /* the program doesn't read any data */
79
80 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
81
82 CHECK(bpf_validate(insns, insn_count));
83
84 code = bpfjit_generate_code(NULL, insns, insn_count);
85 REQUIRE(code != NULL);
86
87 CHECK(jitcall(code, pkt, 1, 1) == 0);
88
89 bpfjit_free_code(code);
90 }
91
92 static void
test_stx3(void)93 test_stx3(void)
94 {
95 static struct bpf_insn insns[] = {
96 BPF_STMT(BPF_LDX+BPF_W+BPF_LEN, 0),
97 BPF_STMT(BPF_STX, 5),
98 BPF_STMT(BPF_STX, 2),
99 BPF_STMT(BPF_STX, 3),
100 BPF_STMT(BPF_LDX+BPF_W+BPF_MEM, 1),
101 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
102 BPF_STMT(BPF_LDX+BPF_W+BPF_MEM, 2),
103 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
104 BPF_STMT(BPF_LDX+BPF_W+BPF_MEM, 3),
105 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
106 BPF_STMT(BPF_LDX+BPF_W+BPF_MEM, 5),
107 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
108 BPF_STMT(BPF_LDX+BPF_W+BPF_MEM, 6),
109 BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0),
110 BPF_STMT(BPF_RET+BPF_A, 0)
111 };
112
113 size_t i;
114 bpfjit_func_t code;
115 uint8_t pkt[16]; /* the program doesn't read any data */
116
117 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
118
119 CHECK(bpf_validate(insns, insn_count));
120
121 code = bpfjit_generate_code(NULL, insns, insn_count);
122 REQUIRE(code != NULL);
123
124 for (i = 1; i <= sizeof(pkt); i++)
125 CHECK(jitcall(code, pkt, i, sizeof(pkt)) == 3 * i);
126
127 bpfjit_free_code(code);
128 }
129
130 static void
test_stx4(void)131 test_stx4(void)
132 {
133 struct bpf_insn insns[5*BPF_MEMWORDS+2];
134 size_t insn_count = sizeof(insns) / sizeof(insns[0]);
135
136 size_t k;
137 bpfjit_func_t code;
138 uint8_t pkt[BPF_MEMWORDS]; /* the program doesn't read any data */
139
140 memset(insns, 0, sizeof(insns));
141
142 /* for each k do M[k] = k */
143 for (k = 0; k < BPF_MEMWORDS; k++) {
144 insns[2*k].code = BPF_LDX+BPF_W+BPF_IMM;
145 insns[2*k].k = 3*k;
146 insns[2*k+1].code = BPF_STX;
147 insns[2*k+1].k = k;
148 }
149
150 /* load wirelen into A */
151 insns[2*BPF_MEMWORDS].code = BPF_LD+BPF_W+BPF_LEN;
152
153 /* for each k, if (A == k + 1) return M[k] */
154 for (k = 0; k < BPF_MEMWORDS; k++) {
155 insns[2*BPF_MEMWORDS+3*k+1].code = BPF_JMP+BPF_JEQ+BPF_K;
156 insns[2*BPF_MEMWORDS+3*k+1].k = k+1;
157 insns[2*BPF_MEMWORDS+3*k+1].jt = 0;
158 insns[2*BPF_MEMWORDS+3*k+1].jf = 2;
159 insns[2*BPF_MEMWORDS+3*k+2].code = BPF_LD+BPF_MEM;
160 insns[2*BPF_MEMWORDS+3*k+2].k = k;
161 insns[2*BPF_MEMWORDS+3*k+3].code = BPF_RET+BPF_A;
162 insns[2*BPF_MEMWORDS+3*k+3].k = 0;
163 }
164
165 insns[5*BPF_MEMWORDS+1].code = BPF_RET+BPF_K;
166 insns[5*BPF_MEMWORDS+1].k = UINT32_MAX;
167
168 CHECK(bpf_validate(insns, insn_count));
169
170 code = bpfjit_generate_code(NULL, insns, insn_count);
171 REQUIRE(code != NULL);
172
173 for (k = 1; k <= sizeof(pkt); k++)
174 CHECK(jitcall(code, pkt, k, k) == 3*(k-1));
175
176 bpfjit_free_code(code);
177 }
178
179 void
test_stx(void)180 test_stx(void)
181 {
182
183 test_stx1();
184 test_stx2();
185 test_stx3();
186 test_stx4();
187 }
188