github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/bpf/vm_scratch_test.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package bpf_test
     6  
     7  import (
     8  	"testing"
     9  
    10  	"github.com/Andyfoo/golang/x/net/bpf"
    11  )
    12  
    13  func TestVMStoreScratchInvalidScratchRegisterTooSmall(t *testing.T) {
    14  	_, _, err := testVM(t, []bpf.Instruction{
    15  		bpf.StoreScratch{
    16  			Src: bpf.RegA,
    17  			N:   -1,
    18  		},
    19  		bpf.RetA{},
    20  	})
    21  	if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
    22  		t.Fatalf("unexpected error: %v", err)
    23  	}
    24  }
    25  
    26  func TestVMStoreScratchInvalidScratchRegisterTooLarge(t *testing.T) {
    27  	_, _, err := testVM(t, []bpf.Instruction{
    28  		bpf.StoreScratch{
    29  			Src: bpf.RegA,
    30  			N:   16,
    31  		},
    32  		bpf.RetA{},
    33  	})
    34  	if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
    35  		t.Fatalf("unexpected error: %v", err)
    36  	}
    37  }
    38  
    39  func TestVMStoreScratchUnknownSourceRegister(t *testing.T) {
    40  	_, _, err := testVM(t, []bpf.Instruction{
    41  		bpf.StoreScratch{
    42  			Src: 100,
    43  			N:   0,
    44  		},
    45  		bpf.RetA{},
    46  	})
    47  	if errStr(err) != "assembling instruction 1: invalid source register 100" {
    48  		t.Fatalf("unexpected error: %v", err)
    49  	}
    50  }
    51  
    52  func TestVMLoadScratchInvalidScratchRegisterTooSmall(t *testing.T) {
    53  	_, _, err := testVM(t, []bpf.Instruction{
    54  		bpf.LoadScratch{
    55  			Dst: bpf.RegX,
    56  			N:   -1,
    57  		},
    58  		bpf.RetA{},
    59  	})
    60  	if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
    61  		t.Fatalf("unexpected error: %v", err)
    62  	}
    63  }
    64  
    65  func TestVMLoadScratchInvalidScratchRegisterTooLarge(t *testing.T) {
    66  	_, _, err := testVM(t, []bpf.Instruction{
    67  		bpf.LoadScratch{
    68  			Dst: bpf.RegX,
    69  			N:   16,
    70  		},
    71  		bpf.RetA{},
    72  	})
    73  	if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
    74  		t.Fatalf("unexpected error: %v", err)
    75  	}
    76  }
    77  
    78  func TestVMLoadScratchUnknownDestinationRegister(t *testing.T) {
    79  	_, _, err := testVM(t, []bpf.Instruction{
    80  		bpf.LoadScratch{
    81  			Dst: 100,
    82  			N:   0,
    83  		},
    84  		bpf.RetA{},
    85  	})
    86  	if errStr(err) != "assembling instruction 1: invalid target register 100" {
    87  		t.Fatalf("unexpected error: %v", err)
    88  	}
    89  }
    90  
    91  func TestVMStoreScratchLoadScratchOneValue(t *testing.T) {
    92  	vm, done, err := testVM(t, []bpf.Instruction{
    93  		// Load byte 255
    94  		bpf.LoadAbsolute{
    95  			Off:  8,
    96  			Size: 1,
    97  		},
    98  		// Copy to X and store in scratch[0]
    99  		bpf.TAX{},
   100  		bpf.StoreScratch{
   101  			Src: bpf.RegX,
   102  			N:   0,
   103  		},
   104  		// Load byte 1
   105  		bpf.LoadAbsolute{
   106  			Off:  9,
   107  			Size: 1,
   108  		},
   109  		// Overwrite 1 with 255 from scratch[0]
   110  		bpf.LoadScratch{
   111  			Dst: bpf.RegA,
   112  			N:   0,
   113  		},
   114  		// Return 255
   115  		bpf.RetA{},
   116  	})
   117  	if err != nil {
   118  		t.Fatalf("failed to load BPF program: %v", err)
   119  	}
   120  	defer done()
   121  
   122  	out, err := vm.Run([]byte{
   123  		0xff, 0xff, 0xff, 0xff,
   124  		0xff, 0xff, 0xff, 0xff,
   125  		255, 1, 2,
   126  	})
   127  	if err != nil {
   128  		t.Fatalf("unexpected error while running program: %v", err)
   129  	}
   130  	if want, got := 3, out; want != got {
   131  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   132  			want, got)
   133  	}
   134  }
   135  
   136  func TestVMStoreScratchLoadScratchMultipleValues(t *testing.T) {
   137  	vm, done, err := testVM(t, []bpf.Instruction{
   138  		// Load byte 10
   139  		bpf.LoadAbsolute{
   140  			Off:  8,
   141  			Size: 1,
   142  		},
   143  		// Store in scratch[0]
   144  		bpf.StoreScratch{
   145  			Src: bpf.RegA,
   146  			N:   0,
   147  		},
   148  		// Load byte 20
   149  		bpf.LoadAbsolute{
   150  			Off:  9,
   151  			Size: 1,
   152  		},
   153  		// Store in scratch[1]
   154  		bpf.StoreScratch{
   155  			Src: bpf.RegA,
   156  			N:   1,
   157  		},
   158  		// Load byte 30
   159  		bpf.LoadAbsolute{
   160  			Off:  10,
   161  			Size: 1,
   162  		},
   163  		// Store in scratch[2]
   164  		bpf.StoreScratch{
   165  			Src: bpf.RegA,
   166  			N:   2,
   167  		},
   168  		// Load byte 1
   169  		bpf.LoadAbsolute{
   170  			Off:  11,
   171  			Size: 1,
   172  		},
   173  		// Store in scratch[3]
   174  		bpf.StoreScratch{
   175  			Src: bpf.RegA,
   176  			N:   3,
   177  		},
   178  		// Load in byte 10 to X
   179  		bpf.LoadScratch{
   180  			Dst: bpf.RegX,
   181  			N:   0,
   182  		},
   183  		// Copy X -> A
   184  		bpf.TXA{},
   185  		// Verify value is 10
   186  		bpf.JumpIf{
   187  			Cond:     bpf.JumpEqual,
   188  			Val:      10,
   189  			SkipTrue: 1,
   190  		},
   191  		// Fail test if incorrect
   192  		bpf.RetConstant{
   193  			Val: 0,
   194  		},
   195  		// Load in byte 20 to A
   196  		bpf.LoadScratch{
   197  			Dst: bpf.RegA,
   198  			N:   1,
   199  		},
   200  		// Verify value is 20
   201  		bpf.JumpIf{
   202  			Cond:     bpf.JumpEqual,
   203  			Val:      20,
   204  			SkipTrue: 1,
   205  		},
   206  		// Fail test if incorrect
   207  		bpf.RetConstant{
   208  			Val: 0,
   209  		},
   210  		// Load in byte 30 to A
   211  		bpf.LoadScratch{
   212  			Dst: bpf.RegA,
   213  			N:   2,
   214  		},
   215  		// Verify value is 30
   216  		bpf.JumpIf{
   217  			Cond:     bpf.JumpEqual,
   218  			Val:      30,
   219  			SkipTrue: 1,
   220  		},
   221  		// Fail test if incorrect
   222  		bpf.RetConstant{
   223  			Val: 0,
   224  		},
   225  		// Return first two bytes on success
   226  		bpf.RetConstant{
   227  			Val: 10,
   228  		},
   229  	})
   230  	if err != nil {
   231  		t.Fatalf("failed to load BPF program: %v", err)
   232  	}
   233  	defer done()
   234  
   235  	out, err := vm.Run([]byte{
   236  		0xff, 0xff, 0xff, 0xff,
   237  		0xff, 0xff, 0xff, 0xff,
   238  		10, 20, 30, 1,
   239  	})
   240  	if err != nil {
   241  		t.Fatalf("unexpected error while running program: %v", err)
   242  	}
   243  	if want, got := 2, out; want != got {
   244  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   245  			want, got)
   246  	}
   247  }