Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(335)

Side by Side Diff: sandbox/linux/seccomp-bpf/codegen_unittest.cc

Issue 754433003: Update from https://crrev.com/305340 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/linux/seccomp-bpf/codegen.cc ('k') | sandbox/linux/seccomp-bpf/instruction.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sandbox/linux/seccomp-bpf/codegen.h" 5 #include "sandbox/linux/seccomp-bpf/codegen.h"
6 6
7 #include <linux/filter.h> 7 #include <linux/filter.h>
8 8
9 #include <map> 9 #include <map>
10 #include <utility> 10 #include <utility>
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 109
110 // MakeInstruction calls CodeGen::MakeInstruction() and associated 110 // MakeInstruction calls CodeGen::MakeInstruction() and associated
111 // the returned address with a hash of the instruction. 111 // the returned address with a hash of the instruction.
112 CodeGen::Node MakeInstruction(uint16_t code, 112 CodeGen::Node MakeInstruction(uint16_t code,
113 uint32_t k, 113 uint32_t k,
114 CodeGen::Node jt = CodeGen::kNullNode, 114 CodeGen::Node jt = CodeGen::kNullNode,
115 CodeGen::Node jf = CodeGen::kNullNode) { 115 CodeGen::Node jf = CodeGen::kNullNode) {
116 CodeGen::Node res = gen_.MakeInstruction(code, k, jt, jf); 116 CodeGen::Node res = gen_.MakeInstruction(code, k, jt, jf);
117 EXPECT_NE(CodeGen::kNullNode, res); 117 EXPECT_NE(CodeGen::kNullNode, res);
118 118
119 Hash digest; 119 Hash digest(code, k, Lookup(jt), Lookup(jf));
120 if (code == BPF_JMP + BPF_JA) {
121 // TODO(mdempsky): Disallow use of JA.
122 digest = Lookup(jt);
123 } else {
124 digest = Hash(code, k, Lookup(jt), Lookup(jf));
125 }
126 auto it = node_hashes_.insert(std::make_pair(res, digest)); 120 auto it = node_hashes_.insert(std::make_pair(res, digest));
127 EXPECT_EQ(digest, it.first->second); 121 EXPECT_EQ(digest, it.first->second);
128 122
129 return res; 123 return res;
130 } 124 }
131 125
132 // RunTest compiles the program and verifies that the output matches 126 // RunTest compiles the program and verifies that the output matches
133 // what is expected. It should be called at the end of each program 127 // what is expected. It should be called at the end of each program
134 // test case. 128 // test case.
135 void RunTest(CodeGen::Node head) { 129 void RunTest(CodeGen::Node head) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 // JUMP if eq 42 the $0 else $1 (insn6) 211 // JUMP if eq 42 the $0 else $1 (insn6)
218 // 0: LD 23 (insn5) 212 // 0: LD 23 (insn5)
219 // 1: JUMP if eq 42 then $2 else $4 (insn4) 213 // 1: JUMP if eq 42 then $2 else $4 (insn4)
220 // 2: JUMP to $3 (insn2) 214 // 2: JUMP to $3 (insn2)
221 // 3: LD 42 (insn1) 215 // 3: LD 42 (insn1)
222 // RET 42 (insn0) 216 // RET 42 (insn0)
223 // 4: LD 42 (insn3) 217 // 4: LD 42 (insn3)
224 // RET 42 (insn3+) 218 // RET 42 (insn3+)
225 CodeGen::Node insn0 = MakeInstruction(BPF_RET + BPF_K, 42); 219 CodeGen::Node insn0 = MakeInstruction(BPF_RET + BPF_K, 42);
226 CodeGen::Node insn1 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, insn0); 220 CodeGen::Node insn1 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, insn0);
227 CodeGen::Node insn2 = MakeInstruction(BPF_JMP + BPF_JA, 0, insn1); 221 CodeGen::Node insn2 = insn1; // Implicit JUMP
228 222
229 // We explicitly duplicate instructions so that MergeTails() can coalesce 223 // We explicitly duplicate instructions to test that they're merged.
230 // them later.
231 CodeGen::Node insn3 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, 224 CodeGen::Node insn3 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42,
232 MakeInstruction(BPF_RET + BPF_K, 42)); 225 MakeInstruction(BPF_RET + BPF_K, 42));
226 EXPECT_EQ(insn2, insn3);
233 227
234 CodeGen::Node insn4 = 228 CodeGen::Node insn4 =
235 MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 42, insn2, insn3); 229 MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 42, insn2, insn3);
236 CodeGen::Node insn5 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 23, insn4); 230 CodeGen::Node insn5 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 23, insn4);
237 231
238 // Force a basic block that ends in neither a jump instruction nor a return 232 // Force a basic block that ends in neither a jump instruction nor a return
239 // instruction. It only contains "insn5". This exercises one of the less 233 // instruction. It only contains "insn5". This exercises one of the less
240 // common code paths in the topo-sort algorithm. 234 // common code paths in the topo-sort algorithm.
241 // This also gives us a diamond-shaped pattern in our graph, which stresses 235 // This also gives us a diamond-shaped pattern in our graph, which stresses
242 // another aspect of the topo-sort algorithm (namely, the ability to 236 // another aspect of the topo-sort algorithm (namely, the ability to
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 CodeGen::Node i5 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7); 315 CodeGen::Node i5 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7);
322 CodeGen::Node i4 = MakeInstruction(BPF_RET + BPF_K, 42); 316 CodeGen::Node i4 = MakeInstruction(BPF_RET + BPF_K, 42);
323 CodeGen::Node i3 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); 317 CodeGen::Node i3 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5);
324 CodeGen::Node i2 = MakeInstruction(BPF_RET + BPF_K, 42); 318 CodeGen::Node i2 = MakeInstruction(BPF_RET + BPF_K, 42);
325 CodeGen::Node i1 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); 319 CodeGen::Node i1 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3);
326 CodeGen::Node i0 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); 320 CodeGen::Node i0 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1);
327 321
328 RunTest(i0); 322 RunTest(i0);
329 } 323 }
330 324
325 TEST_F(ProgramTest, InstructionFolding) {
326 // Check that simple instructions are folded as expected.
327 CodeGen::Node a = MakeInstruction(BPF_RET + BPF_K, 0);
328 EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0));
329 CodeGen::Node b = MakeInstruction(BPF_RET + BPF_K, 1);
330 EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0));
331 EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1));
332 EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1));
333
334 // Check that complex sequences are folded too.
335 CodeGen::Node c =
336 MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0,
337 MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b));
338 EXPECT_EQ(c, MakeInstruction(
339 BPF_LD + BPF_W + BPF_ABS, 0,
340 MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b)));
341
342 RunTest(c);
343 }
344
345 TEST_F(ProgramTest, FarBranches) {
346 // BPF instructions use 8-bit fields for branch offsets, which means
347 // branch targets must be within 255 instructions of the branch
348 // instruction. CodeGen abstracts away this detail by inserting jump
349 // instructions as needed, which we test here by generating programs
350 // that should trigger any interesting boundary conditions.
351
352 // Populate with 260 initial instruction nodes.
353 std::vector<CodeGen::Node> nodes;
354 nodes.push_back(MakeInstruction(BPF_RET + BPF_K, 0));
355 for (size_t i = 1; i < 260; ++i) {
356 nodes.push_back(
357 MakeInstruction(BPF_ALU + BPF_ADD + BPF_K, i, nodes.back()));
358 }
359
360 // Exhaustively test branch offsets near BPF's limits.
361 for (size_t jt = 250; jt < 260; ++jt) {
362 for (size_t jf = 250; jf < 260; ++jf) {
363 nodes.push_back(MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 0,
364 nodes.rbegin()[jt], nodes.rbegin()[jf]));
365 RunTest(nodes.back());
366 }
367 }
368 }
369
331 } // namespace 370 } // namespace
332 } // namespace sandbox 371 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/codegen.cc ('k') | sandbox/linux/seccomp-bpf/instruction.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698