| Index: sandbox/linux/seccomp-bpf/codegen_unittest.cc
|
| diff --git a/sandbox/linux/seccomp-bpf/codegen_unittest.cc b/sandbox/linux/seccomp-bpf/codegen_unittest.cc
|
| index 3f1a04bd710c5329df43bba2349234b3f3098063..a001668be6eb066684f2b2c3d3103ed511c7e464 100644
|
| --- a/sandbox/linux/seccomp-bpf/codegen_unittest.cc
|
| +++ b/sandbox/linux/seccomp-bpf/codegen_unittest.cc
|
| @@ -116,13 +116,7 @@ class ProgramTest : public ::testing::Test {
|
| CodeGen::Node res = gen_.MakeInstruction(code, k, jt, jf);
|
| EXPECT_NE(CodeGen::kNullNode, res);
|
|
|
| - Hash digest;
|
| - if (code == BPF_JMP + BPF_JA) {
|
| - // TODO(mdempsky): Disallow use of JA.
|
| - digest = Lookup(jt);
|
| - } else {
|
| - digest = Hash(code, k, Lookup(jt), Lookup(jf));
|
| - }
|
| + Hash digest(code, k, Lookup(jt), Lookup(jf));
|
| auto it = node_hashes_.insert(std::make_pair(res, digest));
|
| EXPECT_EQ(digest, it.first->second);
|
|
|
| @@ -224,12 +218,12 @@ TEST_F(ProgramTest, Complex) {
|
| // RET 42 (insn3+)
|
| CodeGen::Node insn0 = MakeInstruction(BPF_RET + BPF_K, 42);
|
| CodeGen::Node insn1 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, insn0);
|
| - CodeGen::Node insn2 = MakeInstruction(BPF_JMP + BPF_JA, 0, insn1);
|
| + CodeGen::Node insn2 = insn1; // Implicit JUMP
|
|
|
| - // We explicitly duplicate instructions so that MergeTails() can coalesce
|
| - // them later.
|
| + // We explicitly duplicate instructions to test that they're merged.
|
| CodeGen::Node insn3 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42,
|
| MakeInstruction(BPF_RET + BPF_K, 42));
|
| + EXPECT_EQ(insn2, insn3);
|
|
|
| CodeGen::Node insn4 =
|
| MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 42, insn2, insn3);
|
| @@ -328,5 +322,50 @@ TEST_F(ProgramTest, ConfusingTailsMergeable) {
|
| RunTest(i0);
|
| }
|
|
|
| +TEST_F(ProgramTest, InstructionFolding) {
|
| + // Check that simple instructions are folded as expected.
|
| + CodeGen::Node a = MakeInstruction(BPF_RET + BPF_K, 0);
|
| + EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0));
|
| + CodeGen::Node b = MakeInstruction(BPF_RET + BPF_K, 1);
|
| + EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0));
|
| + EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1));
|
| + EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1));
|
| +
|
| + // Check that complex sequences are folded too.
|
| + CodeGen::Node c =
|
| + MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0,
|
| + MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b));
|
| + EXPECT_EQ(c, MakeInstruction(
|
| + BPF_LD + BPF_W + BPF_ABS, 0,
|
| + MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b)));
|
| +
|
| + RunTest(c);
|
| +}
|
| +
|
| +TEST_F(ProgramTest, FarBranches) {
|
| + // BPF instructions use 8-bit fields for branch offsets, which means
|
| + // branch targets must be within 255 instructions of the branch
|
| + // instruction. CodeGen abstracts away this detail by inserting jump
|
| + // instructions as needed, which we test here by generating programs
|
| + // that should trigger any interesting boundary conditions.
|
| +
|
| + // Populate with 260 initial instruction nodes.
|
| + std::vector<CodeGen::Node> nodes;
|
| + nodes.push_back(MakeInstruction(BPF_RET + BPF_K, 0));
|
| + for (size_t i = 1; i < 260; ++i) {
|
| + nodes.push_back(
|
| + MakeInstruction(BPF_ALU + BPF_ADD + BPF_K, i, nodes.back()));
|
| + }
|
| +
|
| + // Exhaustively test branch offsets near BPF's limits.
|
| + for (size_t jt = 250; jt < 260; ++jt) {
|
| + for (size_t jf = 250; jf < 260; ++jf) {
|
| + nodes.push_back(MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 0,
|
| + nodes.rbegin()[jt], nodes.rbegin()[jf]));
|
| + RunTest(nodes.back());
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace
|
| } // namespace sandbox
|
|
|