diff --git a/tests/ubpf_vm.rs b/tests/ubpf_vm.rs index 8918e52b..9f3a2eb9 100644 --- a/tests/ubpf_vm.rs +++ b/tests/ubpf_vm.rs @@ -769,6 +769,38 @@ fn test_vm_jset_imm() { assert_eq!(vm.execute_program().unwrap(), 0x1); } +#[test] +fn test_vm_jmp_unsigned_extend() { + use rbpf::ebpf::{Insn, BE, EXIT, JEQ_IMM, MOV32_IMM, LD_W_REG}; + + // the insn `jeq r2, 0x80000000, +2` will be rejected + assert!(assemble("jeq r2, 0x80000000, +2").is_err()); + // the prog is as follows: + // ldxw r2, [r1] + // be32 r2 + // jeq r2, 0x80000000, +2 # 0x80000000 should be interpreted as 0x0000000080000000 (unsigned) + // mov32 r0, 2 + // exit + // mov32 r0, 1 + // exit + // we build it manually to bypass the verifier in `assemble(...)` + let insns = vec![ + Insn { opc: LD_W_REG, dst: 2, src: 1, off: 0, imm: 0 }, + Insn { opc: BE, dst: 2, src: 0, off: 0, imm: 32 }, + Insn { opc: JEQ_IMM, dst: 2, src: 0, off: 2, imm: 0x80000000u32 as i32 }, + Insn { opc: MOV32_IMM, dst: 0, src: 0, off: 0, imm: 2 }, + Insn { opc: EXIT, dst: 0, src: 0, off: 0, imm: 0 }, + Insn { opc: MOV32_IMM, dst: 0, src: 0, off: 0, imm: 1 }, + Insn { opc: EXIT, dst: 0, src: 0, off: 0, imm: 0 } + ]; + let prog = insns.iter().map(|x| x.to_array()).flatten().collect::>(); + let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut data = vec![ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ]; + assert_eq!(vm.execute_program(&mut data).unwrap(), 1); +} + #[test] fn test_vm_jset_reg() { let prog = assemble("