vm_scratch_test.go 4.7 KB

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