vm_aluop_test.go 9.7 KB

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