github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/bpf/vm_aluop_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/hxx258456/ccgo/net/bpf"
    11  )
    12  
    13  func TestVMALUOpAdd(t *testing.T) {
    14  	vm, done, err := testVM(t, []bpf.Instruction{
    15  		bpf.LoadAbsolute{
    16  			Off:  8,
    17  			Size: 1,
    18  		},
    19  		bpf.ALUOpConstant{
    20  			Op:  bpf.ALUOpAdd,
    21  			Val: 3,
    22  		},
    23  		bpf.RetA{},
    24  	})
    25  	if err != nil {
    26  		t.Fatalf("failed to load BPF program: %v", err)
    27  	}
    28  	defer done()
    29  
    30  	out, err := vm.Run([]byte{
    31  		0xff, 0xff, 0xff, 0xff,
    32  		0xff, 0xff, 0xff, 0xff,
    33  		8, 2, 3,
    34  	})
    35  	if err != nil {
    36  		t.Fatalf("unexpected error while running program: %v", err)
    37  	}
    38  	if want, got := 3, out; want != got {
    39  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
    40  			want, got)
    41  	}
    42  }
    43  
    44  func TestVMALUOpSub(t *testing.T) {
    45  	vm, done, err := testVM(t, []bpf.Instruction{
    46  		bpf.LoadAbsolute{
    47  			Off:  8,
    48  			Size: 1,
    49  		},
    50  		bpf.TAX{},
    51  		bpf.ALUOpX{
    52  			Op: bpf.ALUOpSub,
    53  		},
    54  		bpf.RetA{},
    55  	})
    56  	if err != nil {
    57  		t.Fatalf("failed to load BPF program: %v", err)
    58  	}
    59  	defer done()
    60  
    61  	out, err := vm.Run([]byte{
    62  		0xff, 0xff, 0xff, 0xff,
    63  		0xff, 0xff, 0xff, 0xff,
    64  		1, 2, 3,
    65  	})
    66  	if err != nil {
    67  		t.Fatalf("unexpected error while running program: %v", err)
    68  	}
    69  	if want, got := 0, out; want != got {
    70  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
    71  			want, got)
    72  	}
    73  }
    74  
    75  func TestVMALUOpMul(t *testing.T) {
    76  	vm, done, err := testVM(t, []bpf.Instruction{
    77  		bpf.LoadAbsolute{
    78  			Off:  8,
    79  			Size: 1,
    80  		},
    81  		bpf.ALUOpConstant{
    82  			Op:  bpf.ALUOpMul,
    83  			Val: 2,
    84  		},
    85  		bpf.RetA{},
    86  	})
    87  	if err != nil {
    88  		t.Fatalf("failed to load BPF program: %v", err)
    89  	}
    90  	defer done()
    91  
    92  	out, err := vm.Run([]byte{
    93  		0xff, 0xff, 0xff, 0xff,
    94  		0xff, 0xff, 0xff, 0xff,
    95  		6, 2, 3, 4,
    96  	})
    97  	if err != nil {
    98  		t.Fatalf("unexpected error while running program: %v", err)
    99  	}
   100  	if want, got := 4, out; want != got {
   101  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   102  			want, got)
   103  	}
   104  }
   105  
   106  func TestVMALUOpDiv(t *testing.T) {
   107  	vm, done, err := testVM(t, []bpf.Instruction{
   108  		bpf.LoadAbsolute{
   109  			Off:  8,
   110  			Size: 1,
   111  		},
   112  		bpf.ALUOpConstant{
   113  			Op:  bpf.ALUOpDiv,
   114  			Val: 2,
   115  		},
   116  		bpf.RetA{},
   117  	})
   118  	if err != nil {
   119  		t.Fatalf("failed to load BPF program: %v", err)
   120  	}
   121  	defer done()
   122  
   123  	out, err := vm.Run([]byte{
   124  		0xff, 0xff, 0xff, 0xff,
   125  		0xff, 0xff, 0xff, 0xff,
   126  		20, 2, 3, 4,
   127  	})
   128  	if err != nil {
   129  		t.Fatalf("unexpected error while running program: %v", err)
   130  	}
   131  	if want, got := 2, out; want != got {
   132  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   133  			want, got)
   134  	}
   135  }
   136  
   137  func TestVMALUOpDivByZeroALUOpConstant(t *testing.T) {
   138  	_, _, err := testVM(t, []bpf.Instruction{
   139  		bpf.ALUOpConstant{
   140  			Op:  bpf.ALUOpDiv,
   141  			Val: 0,
   142  		},
   143  		bpf.RetA{},
   144  	})
   145  	if errStr(err) != "cannot divide by zero using ALUOpConstant" {
   146  		t.Fatalf("unexpected error: %v", err)
   147  	}
   148  }
   149  
   150  func TestVMALUOpDivByZeroALUOpX(t *testing.T) {
   151  	vm, done, err := testVM(t, []bpf.Instruction{
   152  		// Load byte 0 into X
   153  		bpf.LoadAbsolute{
   154  			Off:  8,
   155  			Size: 1,
   156  		},
   157  		bpf.TAX{},
   158  		// Load byte 1 into A
   159  		bpf.LoadAbsolute{
   160  			Off:  9,
   161  			Size: 1,
   162  		},
   163  		// Attempt to perform 1/0
   164  		bpf.ALUOpX{
   165  			Op: bpf.ALUOpDiv,
   166  		},
   167  		// Return 4 bytes if program does not terminate
   168  		bpf.LoadConstant{
   169  			Val: 12,
   170  		},
   171  		bpf.RetA{},
   172  	})
   173  	if err != nil {
   174  		t.Fatalf("failed to load BPF program: %v", err)
   175  	}
   176  	defer done()
   177  
   178  	out, err := vm.Run([]byte{
   179  		0xff, 0xff, 0xff, 0xff,
   180  		0xff, 0xff, 0xff, 0xff,
   181  		0, 1, 3, 4,
   182  	})
   183  	if err != nil {
   184  		t.Fatalf("unexpected error while running program: %v", err)
   185  	}
   186  	if want, got := 0, out; want != got {
   187  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   188  			want, got)
   189  	}
   190  }
   191  
   192  func TestVMALUOpOr(t *testing.T) {
   193  	vm, done, err := testVM(t, []bpf.Instruction{
   194  		bpf.LoadAbsolute{
   195  			Off:  8,
   196  			Size: 2,
   197  		},
   198  		bpf.ALUOpConstant{
   199  			Op:  bpf.ALUOpOr,
   200  			Val: 0x01,
   201  		},
   202  		bpf.RetA{},
   203  	})
   204  	if err != nil {
   205  		t.Fatalf("failed to load BPF program: %v", err)
   206  	}
   207  	defer done()
   208  
   209  	out, err := vm.Run([]byte{
   210  		0xff, 0xff, 0xff, 0xff,
   211  		0xff, 0xff, 0xff, 0xff,
   212  		0x00, 0x10, 0x03, 0x04,
   213  		0x05, 0x06, 0x07, 0x08,
   214  		0x09, 0xff,
   215  	})
   216  	if err != nil {
   217  		t.Fatalf("unexpected error while running program: %v", err)
   218  	}
   219  	if want, got := 9, out; want != got {
   220  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   221  			want, got)
   222  	}
   223  }
   224  
   225  func TestVMALUOpAnd(t *testing.T) {
   226  	vm, done, err := testVM(t, []bpf.Instruction{
   227  		bpf.LoadAbsolute{
   228  			Off:  8,
   229  			Size: 2,
   230  		},
   231  		bpf.ALUOpConstant{
   232  			Op:  bpf.ALUOpAnd,
   233  			Val: 0x0019,
   234  		},
   235  		bpf.RetA{},
   236  	})
   237  	if err != nil {
   238  		t.Fatalf("failed to load BPF program: %v", err)
   239  	}
   240  	defer done()
   241  
   242  	out, err := vm.Run([]byte{
   243  		0xff, 0xff, 0xff, 0xff,
   244  		0xff, 0xff, 0xff, 0xff,
   245  		0xaa, 0x09,
   246  	})
   247  	if err != nil {
   248  		t.Fatalf("unexpected error while running program: %v", err)
   249  	}
   250  	if want, got := 1, out; want != got {
   251  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   252  			want, got)
   253  	}
   254  }
   255  
   256  func TestVMALUOpShiftLeft(t *testing.T) {
   257  	vm, done, err := testVM(t, []bpf.Instruction{
   258  		bpf.LoadAbsolute{
   259  			Off:  8,
   260  			Size: 1,
   261  		},
   262  		bpf.ALUOpConstant{
   263  			Op:  bpf.ALUOpShiftLeft,
   264  			Val: 0x01,
   265  		},
   266  		bpf.JumpIf{
   267  			Cond:     bpf.JumpEqual,
   268  			Val:      0x02,
   269  			SkipTrue: 1,
   270  		},
   271  		bpf.RetConstant{
   272  			Val: 0,
   273  		},
   274  		bpf.RetConstant{
   275  			Val: 9,
   276  		},
   277  	})
   278  	if err != nil {
   279  		t.Fatalf("failed to load BPF program: %v", err)
   280  	}
   281  	defer done()
   282  
   283  	out, err := vm.Run([]byte{
   284  		0xff, 0xff, 0xff, 0xff,
   285  		0xff, 0xff, 0xff, 0xff,
   286  		0x01, 0xaa,
   287  	})
   288  	if err != nil {
   289  		t.Fatalf("unexpected error while running program: %v", err)
   290  	}
   291  	if want, got := 1, out; want != got {
   292  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   293  			want, got)
   294  	}
   295  }
   296  
   297  func TestVMALUOpShiftRight(t *testing.T) {
   298  	vm, done, err := testVM(t, []bpf.Instruction{
   299  		bpf.LoadAbsolute{
   300  			Off:  8,
   301  			Size: 1,
   302  		},
   303  		bpf.ALUOpConstant{
   304  			Op:  bpf.ALUOpShiftRight,
   305  			Val: 0x01,
   306  		},
   307  		bpf.JumpIf{
   308  			Cond:     bpf.JumpEqual,
   309  			Val:      0x04,
   310  			SkipTrue: 1,
   311  		},
   312  		bpf.RetConstant{
   313  			Val: 0,
   314  		},
   315  		bpf.RetConstant{
   316  			Val: 9,
   317  		},
   318  	})
   319  	if err != nil {
   320  		t.Fatalf("failed to load BPF program: %v", err)
   321  	}
   322  	defer done()
   323  
   324  	out, err := vm.Run([]byte{
   325  		0xff, 0xff, 0xff, 0xff,
   326  		0xff, 0xff, 0xff, 0xff,
   327  		0x08, 0xff, 0xff,
   328  	})
   329  	if err != nil {
   330  		t.Fatalf("unexpected error while running program: %v", err)
   331  	}
   332  	if want, got := 1, out; want != got {
   333  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   334  			want, got)
   335  	}
   336  }
   337  
   338  func TestVMALUOpMod(t *testing.T) {
   339  	vm, done, err := testVM(t, []bpf.Instruction{
   340  		bpf.LoadAbsolute{
   341  			Off:  8,
   342  			Size: 1,
   343  		},
   344  		bpf.ALUOpConstant{
   345  			Op:  bpf.ALUOpMod,
   346  			Val: 20,
   347  		},
   348  		bpf.RetA{},
   349  	})
   350  	if err != nil {
   351  		t.Fatalf("failed to load BPF program: %v", err)
   352  	}
   353  	defer done()
   354  
   355  	out, err := vm.Run([]byte{
   356  		0xff, 0xff, 0xff, 0xff,
   357  		0xff, 0xff, 0xff, 0xff,
   358  		30, 0, 0,
   359  	})
   360  	if err != nil {
   361  		t.Fatalf("unexpected error while running program: %v", err)
   362  	}
   363  	if want, got := 2, out; want != got {
   364  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   365  			want, got)
   366  	}
   367  }
   368  
   369  func TestVMALUOpModByZeroALUOpConstant(t *testing.T) {
   370  	_, _, err := testVM(t, []bpf.Instruction{
   371  		bpf.LoadAbsolute{
   372  			Off:  8,
   373  			Size: 1,
   374  		},
   375  		bpf.ALUOpConstant{
   376  			Op:  bpf.ALUOpMod,
   377  			Val: 0,
   378  		},
   379  		bpf.RetA{},
   380  	})
   381  	if errStr(err) != "cannot divide by zero using ALUOpConstant" {
   382  		t.Fatalf("unexpected error: %v", err)
   383  	}
   384  }
   385  
   386  func TestVMALUOpModByZeroALUOpX(t *testing.T) {
   387  	vm, done, err := testVM(t, []bpf.Instruction{
   388  		// Load byte 0 into X
   389  		bpf.LoadAbsolute{
   390  			Off:  8,
   391  			Size: 1,
   392  		},
   393  		bpf.TAX{},
   394  		// Load byte 1 into A
   395  		bpf.LoadAbsolute{
   396  			Off:  9,
   397  			Size: 1,
   398  		},
   399  		// Attempt to perform 1%0
   400  		bpf.ALUOpX{
   401  			Op: bpf.ALUOpMod,
   402  		},
   403  		// Return 4 bytes if program does not terminate
   404  		bpf.LoadConstant{
   405  			Val: 12,
   406  		},
   407  		bpf.RetA{},
   408  	})
   409  	if err != nil {
   410  		t.Fatalf("failed to load BPF program: %v", err)
   411  	}
   412  	defer done()
   413  
   414  	out, err := vm.Run([]byte{
   415  		0xff, 0xff, 0xff, 0xff,
   416  		0xff, 0xff, 0xff, 0xff,
   417  		0, 1, 3, 4,
   418  	})
   419  	if err != nil {
   420  		t.Fatalf("unexpected error while running program: %v", err)
   421  	}
   422  	if want, got := 0, out; want != got {
   423  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   424  			want, got)
   425  	}
   426  }
   427  
   428  func TestVMALUOpXor(t *testing.T) {
   429  	vm, done, err := testVM(t, []bpf.Instruction{
   430  		bpf.LoadAbsolute{
   431  			Off:  8,
   432  			Size: 1,
   433  		},
   434  		bpf.ALUOpConstant{
   435  			Op:  bpf.ALUOpXor,
   436  			Val: 0x0a,
   437  		},
   438  		bpf.JumpIf{
   439  			Cond:     bpf.JumpEqual,
   440  			Val:      0x01,
   441  			SkipTrue: 1,
   442  		},
   443  		bpf.RetConstant{
   444  			Val: 0,
   445  		},
   446  		bpf.RetConstant{
   447  			Val: 9,
   448  		},
   449  	})
   450  	if err != nil {
   451  		t.Fatalf("failed to load BPF program: %v", err)
   452  	}
   453  	defer done()
   454  
   455  	out, err := vm.Run([]byte{
   456  		0xff, 0xff, 0xff, 0xff,
   457  		0xff, 0xff, 0xff, 0xff,
   458  		0x0b, 0x00, 0x00, 0x00,
   459  	})
   460  	if err != nil {
   461  		t.Fatalf("unexpected error while running program: %v", err)
   462  	}
   463  	if want, got := 1, out; want != got {
   464  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   465  			want, got)
   466  	}
   467  }
   468  
   469  func TestVMALUOpUnknown(t *testing.T) {
   470  	vm, done, err := testVM(t, []bpf.Instruction{
   471  		bpf.LoadAbsolute{
   472  			Off:  8,
   473  			Size: 1,
   474  		},
   475  		bpf.ALUOpConstant{
   476  			Op:  bpf.ALUOpAdd,
   477  			Val: 1,
   478  		},
   479  		// Verify that an unknown operation is a no-op
   480  		bpf.ALUOpConstant{
   481  			Op: 100,
   482  		},
   483  		bpf.JumpIf{
   484  			Cond:     bpf.JumpEqual,
   485  			Val:      0x02,
   486  			SkipTrue: 1,
   487  		},
   488  		bpf.RetConstant{
   489  			Val: 0,
   490  		},
   491  		bpf.RetConstant{
   492  			Val: 9,
   493  		},
   494  	})
   495  	if err != nil {
   496  		t.Fatalf("failed to load BPF program: %v", err)
   497  	}
   498  	defer done()
   499  
   500  	out, err := vm.Run([]byte{
   501  		0xff, 0xff, 0xff, 0xff,
   502  		0xff, 0xff, 0xff, 0xff,
   503  		1,
   504  	})
   505  	if err != nil {
   506  		t.Fatalf("unexpected error while running program: %v", err)
   507  	}
   508  	if want, got := 1, out; want != got {
   509  		t.Fatalf("unexpected number of output bytes:\n- want: %d\n-  got: %d",
   510  			want, got)
   511  	}
   512  }