github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/bpf/decoder_test.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bpf 16 17 import ( 18 "testing" 19 20 "github.com/SagerNet/gvisor/pkg/abi/linux" 21 ) 22 23 func TestDecode(t *testing.T) { 24 for _, test := range []struct { 25 filter linux.BPFInstruction 26 expected string 27 fail bool 28 }{ 29 {filter: Stmt(Ld+Imm, 10), expected: "A <- 10"}, 30 {filter: Stmt(Ld+Abs+W, 10), expected: "A <- P[10:4]"}, 31 {filter: Stmt(Ld+Ind+H, 10), expected: "A <- P[X+10:2]"}, 32 {filter: Stmt(Ld+Ind+B, 10), expected: "A <- P[X+10:1]"}, 33 {filter: Stmt(Ld+Mem, 10), expected: "A <- M[10]"}, 34 {filter: Stmt(Ld+Len, 0), expected: "A <- len"}, 35 {filter: Stmt(Ldx+Imm, 10), expected: "X <- 10"}, 36 {filter: Stmt(Ldx+Mem, 10), expected: "X <- M[10]"}, 37 {filter: Stmt(Ldx+Len, 0), expected: "X <- len"}, 38 {filter: Stmt(Ldx+Msh, 10), expected: "X <- 4*(P[10:1]&0xf)"}, 39 {filter: Stmt(St, 10), expected: "M[10] <- A"}, 40 {filter: Stmt(Stx, 10), expected: "M[10] <- X"}, 41 {filter: Stmt(Alu+Add+K, 10), expected: "A <- A + 10"}, 42 {filter: Stmt(Alu+Sub+K, 10), expected: "A <- A - 10"}, 43 {filter: Stmt(Alu+Mul+K, 10), expected: "A <- A * 10"}, 44 {filter: Stmt(Alu+Div+K, 10), expected: "A <- A / 10"}, 45 {filter: Stmt(Alu+Or+K, 10), expected: "A <- A | 10"}, 46 {filter: Stmt(Alu+And+K, 10), expected: "A <- A & 10"}, 47 {filter: Stmt(Alu+Lsh+K, 10), expected: "A <- A << 10"}, 48 {filter: Stmt(Alu+Rsh+K, 10), expected: "A <- A >> 10"}, 49 {filter: Stmt(Alu+Mod+K, 10), expected: "A <- A % 10"}, 50 {filter: Stmt(Alu+Xor+K, 10), expected: "A <- A ^ 10"}, 51 {filter: Stmt(Alu+Add+X, 0), expected: "A <- A + X"}, 52 {filter: Stmt(Alu+Sub+X, 0), expected: "A <- A - X"}, 53 {filter: Stmt(Alu+Mul+X, 0), expected: "A <- A * X"}, 54 {filter: Stmt(Alu+Div+X, 0), expected: "A <- A / X"}, 55 {filter: Stmt(Alu+Or+X, 0), expected: "A <- A | X"}, 56 {filter: Stmt(Alu+And+X, 0), expected: "A <- A & X"}, 57 {filter: Stmt(Alu+Lsh+X, 0), expected: "A <- A << X"}, 58 {filter: Stmt(Alu+Rsh+X, 0), expected: "A <- A >> X"}, 59 {filter: Stmt(Alu+Mod+X, 0), expected: "A <- A % X"}, 60 {filter: Stmt(Alu+Xor+X, 0), expected: "A <- A ^ X"}, 61 {filter: Stmt(Alu+Neg, 0), expected: "A <- -A"}, 62 {filter: Stmt(Jmp+Ja, 10), expected: "pc += 10"}, 63 {filter: Jump(Jmp+Jeq+K, 10, 2, 5), expected: "pc += (A == 10) ? 2 : 5"}, 64 {filter: Jump(Jmp+Jgt+K, 10, 2, 5), expected: "pc += (A > 10) ? 2 : 5"}, 65 {filter: Jump(Jmp+Jge+K, 10, 2, 5), expected: "pc += (A >= 10) ? 2 : 5"}, 66 {filter: Jump(Jmp+Jset+K, 10, 2, 5), expected: "pc += (A & 10) ? 2 : 5"}, 67 {filter: Jump(Jmp+Jeq+X, 0, 2, 5), expected: "pc += (A == X) ? 2 : 5"}, 68 {filter: Jump(Jmp+Jgt+X, 0, 2, 5), expected: "pc += (A > X) ? 2 : 5"}, 69 {filter: Jump(Jmp+Jge+X, 0, 2, 5), expected: "pc += (A >= X) ? 2 : 5"}, 70 {filter: Jump(Jmp+Jset+X, 0, 2, 5), expected: "pc += (A & X) ? 2 : 5"}, 71 {filter: Stmt(Ret+K, 10), expected: "ret 10"}, 72 {filter: Stmt(Ret+A, 0), expected: "ret A"}, 73 {filter: Stmt(Misc+Tax, 0), expected: "X <- A"}, 74 {filter: Stmt(Misc+Txa, 0), expected: "A <- X"}, 75 {filter: Stmt(Ld+Ind+Msh, 0), fail: true}, 76 } { 77 got, err := Decode(test.filter) 78 if test.fail { 79 if err == nil { 80 t.Errorf("Decode(%v) failed, expected: 'error', got: %q", test.filter, got) 81 continue 82 } 83 } else { 84 if err != nil { 85 t.Errorf("Decode(%v) failed for test %q, error: %q", test.filter, test.expected, err) 86 continue 87 } 88 if got != test.expected { 89 t.Errorf("Decode(%v) failed, expected: %q, got: %q", test.filter, test.expected, got) 90 continue 91 } 92 } 93 } 94 } 95 96 func TestDecodeInstructions(t *testing.T) { 97 for _, test := range []struct { 98 name string 99 program []linux.BPFInstruction 100 expected string 101 fail bool 102 }{ 103 {name: "basic with jump indexes", 104 program: []linux.BPFInstruction{ 105 Stmt(Ld+Abs+W, 10), 106 Stmt(Ldx+Mem, 10), 107 Stmt(St, 10), 108 Stmt(Stx, 10), 109 Stmt(Alu+Add+K, 10), 110 Stmt(Jmp+Ja, 10), 111 Jump(Jmp+Jeq+K, 10, 2, 5), 112 Jump(Jmp+Jset+X, 0, 0, 5), 113 Stmt(Misc+Tax, 0), 114 }, 115 expected: "0: A <- P[10:4]\n" + 116 "1: X <- M[10]\n" + 117 "2: M[10] <- A\n" + 118 "3: M[10] <- X\n" + 119 "4: A <- A + 10\n" + 120 "5: pc += 10 [16]\n" + 121 "6: pc += (A == 10) ? 2 [9] : 5 [12]\n" + 122 "7: pc += (A & X) ? 0 [8] : 5 [13]\n" + 123 "8: X <- A\n", 124 }, 125 {name: "invalid instruction", 126 program: []linux.BPFInstruction{Stmt(Ld+Abs+W, 10), Stmt(Ld+Len+Mem, 0)}, 127 fail: true}, 128 } { 129 got, err := DecodeInstructions(test.program) 130 if test.fail { 131 if err == nil { 132 t.Errorf("%s: Decode(...) failed, expected: 'error', got: %q", test.name, got) 133 continue 134 } 135 } else { 136 if err != nil { 137 t.Errorf("%s: Decode failed: %v", test.name, err) 138 continue 139 } 140 if got != test.expected { 141 t.Errorf("%s: Decode(...) failed, expected: %q, got: %q", test.name, test.expected, got) 142 continue 143 } 144 } 145 } 146 }