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  }