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 }