diff --git a/src/ebpf.rs b/src/ebpf.rs index 400a0007..9c7a545a 100644 --- a/src/ebpf.rs +++ b/src/ebpf.rs @@ -22,8 +22,6 @@ use byteorder::{ByteOrder, LittleEndian}; /// Maximum number of instructions in an eBPF program. pub const PROG_MAX_INSNS: usize = 4096; -/// Maximum number of instructions to execute -pub const MAX_EXECUTED: usize = 32768; /// Size of an eBPF instructions, in bytes. pub const INSN_SIZE: usize = 8; /// Maximum size of an eBPF program, in bytes. diff --git a/src/lib.rs b/src/lib.rs index b7de90f6..bcbb9ed3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,10 +99,12 @@ struct MetaBuff { /// assert_eq!(res, 0x2211); /// ``` pub struct EbpfVmMbuff<'a> { - prog: Option<&'a [u8]>, - verifier: Verifier, - jit: Option, - helpers: HashMap, + prog: Option<&'a [u8]>, + verifier: Verifier, + jit: Option, + helpers: HashMap, + max_insn_count: usize, + last_insn_count: usize, } impl<'a> EbpfVmMbuff<'a> { @@ -128,10 +130,12 @@ impl<'a> EbpfVmMbuff<'a> { } Ok(EbpfVmMbuff { - prog: prog, - verifier: verifier::check, - jit: None, - helpers: HashMap::new(), + prog: prog, + verifier: verifier::check, + jit: None, + helpers: HashMap::new(), + max_insn_count: 0, + last_insn_count: 0, }) } @@ -198,6 +202,68 @@ impl<'a> EbpfVmMbuff<'a> { Ok(()) } + /// Set a cap on the maximum number of instructions that a program may execute. + /// If the maximum is set to zero, then no cap will be applied. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog)).unwrap(); + /// // Set maximum instruction count. + /// vm.set_max_instruction_count(1000).unwrap(); + /// ``` + pub fn set_max_instruction_count(&mut self, count: usize) -> Result<(), Error> { + self.max_insn_count = count; + Ok(()) + } + + /// Returns the number of instructions executed by the last program. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// let mem = &mut [ + /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd + /// ]; + /// + /// // Just for the example we create our metadata buffer from scratch, and we store the + /// // pointers to packet data start and end in it. + /// let mut mbuff = [0u8; 32]; + /// unsafe { + /// let mut data = mbuff.as_ptr().offset(8) as *mut u64; + /// let mut data_end = mbuff.as_ptr().offset(24) as *mut u64; + /// *data = mem.as_ptr() as u64; + /// *data_end = mem.as_ptr() as u64 + mem.len() as u64; + /// } + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog)).unwrap(); + /// // Execute the program. + /// let res = vm.execute_program(mem, &mut mbuff).unwrap(); + /// // Get the number of instructions executed. + /// let count = vm.get_last_instruction_count(); + /// ``` + pub fn get_last_instruction_count(&self) -> usize { + self.last_insn_count + } + /// Register a built-in or user-defined helper function in order to use it later from within /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`. /// @@ -276,7 +342,7 @@ impl<'a> EbpfVmMbuff<'a> { /// ``` #[allow(unknown_lints)] #[allow(cyclomatic_complexity)] - pub fn execute_program(&self, mem: &[u8], mbuff: &[u8]) -> Result { + pub fn execute_program(&mut self, mem: &[u8], mbuff: &[u8]) -> Result { const U32MAX: u64 = u32::MAX as u64; let prog = match self.prog { @@ -306,17 +372,13 @@ impl<'a> EbpfVmMbuff<'a> { // Loop on instructions let mut insn_ptr:usize = 0; - let mut max_executed = 0; + self.last_insn_count = 0; while insn_ptr * ebpf::INSN_SIZE < prog.len() { let insn = ebpf::get_insn(prog, insn_ptr); - insn_ptr += 1; let _dst = insn.dst as usize; let _src = insn.src as usize; - - max_executed += 1; - if max_executed > ebpf::MAX_EXECUTED { - Err(Error::new(ErrorKind::Other,"Error: Execution exceeded maximum number of instructions"))?; - } + insn_ptr += 1; + self.last_insn_count += 1; match insn.opc { @@ -579,6 +641,9 @@ impl<'a> EbpfVmMbuff<'a> { _ => unreachable!() } + if (self.max_insn_count != 0) && (self.last_insn_count >= self.max_insn_count) { + Err(Error::new(ErrorKind::Other, "Error: Execution exceeded maximum number of instructions allowed"))?; + } } unreachable!() @@ -890,6 +955,57 @@ impl<'a> EbpfVmFixedMbuff<'a> { self.parent.set_verifier(verifier) } + /// Set a cap on the maximum number of instructions that a program may execute. + /// If the maximum is set to zero, then no cap will be applied. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog)).unwrap(); + /// // Set maximum instruction count. + /// vm.set_max_instruction_count(1000).unwrap(); + /// ``` + pub fn set_max_instruction_count(&mut self, count: usize) -> Result<(), Error> { + self.parent.set_max_instruction_count(count) + } + + /// Returns the number of instructions executed by the last program. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// let mem = &mut [ + /// 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x09, + /// ]; + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap(); + /// // Execute the program. + /// let res = vm.execute_program(mem).unwrap(); + /// // Get the number of instructions executed. + /// let count = vm.get_last_instruction_count(); + /// ``` + pub fn get_last_instruction_count(&self) -> usize { + self.parent.get_last_instruction_count() + } + /// Register a built-in or user-defined helper function in order to use it later from within /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`. /// @@ -966,7 +1082,7 @@ impl<'a> EbpfVmFixedMbuff<'a> { /// let res = vm.execute_program(mem).unwrap(); /// assert_eq!(res, 0xdd); /// ``` - pub fn execute_program(&mut self, mem: &'a mut [u8]) -> Result { + pub fn execute_program(&mut self, mem: & mut [u8]) -> Result { let l = self.mbuff.buffer.len(); // Can this ever happen? Probably not, should be ensured at mbuff creation. if self.mbuff.data_offset + 8 > l || self.mbuff.data_end_offset + 8 > l { @@ -1099,7 +1215,7 @@ impl<'a> EbpfVmFixedMbuff<'a> { /// ]; /// /// // Instantiate a VM. -/// let vm = solana_rbpf::EbpfVmRaw::new(Some(prog)).unwrap(); +/// let mut vm = solana_rbpf::EbpfVmRaw::new(Some(prog)).unwrap(); /// /// // Provide only a reference to the packet data. /// let res = vm.execute_program(mem).unwrap(); @@ -1199,6 +1315,57 @@ impl<'a> EbpfVmRaw<'a> { self.parent.set_verifier(verifier) } + /// Set a cap on the maximum number of instructions that a program may execute. + /// If the maximum is set to zero, then no cap will be applied. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog)).unwrap(); + /// // Set maximum instruction count. + /// vm.set_max_instruction_count(1000).unwrap(); + /// ``` + pub fn set_max_instruction_count(&mut self, count: usize) -> Result<(), Error> { + self.parent.set_max_instruction_count(count) + } + + /// Returns the number of instructions executed by the last program. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// let mem = &mut [ + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + /// ]; + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog)).unwrap(); + /// // Execute the program. + /// let res = vm.execute_program(mem, mem).unwrap(); + /// // Get the number of instructions executed. + /// let count = vm.get_last_instruction_count(); + /// ``` + pub fn get_last_instruction_count(&self) -> usize { + self.parent.get_last_instruction_count() + } + /// Register a built-in or user-defined helper function in order to use it later from within /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`. /// @@ -1259,7 +1426,7 @@ impl<'a> EbpfVmRaw<'a> { /// let res = vm.execute_program(mem).unwrap(); /// assert_eq!(res, 0x22cc); /// ``` - pub fn execute_program(&self, mem: &'a mut [u8]) -> Result { + pub fn execute_program(&mut self, mem: & mut [u8]) -> Result { self.parent.execute_program(mem, &[]) } @@ -1330,7 +1497,7 @@ impl<'a> EbpfVmRaw<'a> { /// assert_eq!(res, 0x22cc); /// } /// ``` - pub unsafe fn execute_program_jit(&self, mem: &'a mut [u8]) -> Result { + pub unsafe fn execute_program_jit(&self, mem: &mut [u8]) -> Result { let mut mbuff = vec![]; self.parent.execute_program_jit(mem, &mut mbuff) } @@ -1369,7 +1536,7 @@ impl<'a> EbpfVmRaw<'a> { /// ]; /// /// // Instantiate a VM. -/// let vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); +/// let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); /// /// // Provide only a reference to the packet data. /// let res = vm.execute_program().unwrap(); @@ -1467,6 +1634,53 @@ impl<'a> EbpfVmNoData<'a> { self.parent.set_verifier(verifier) } + /// Set a cap on the maximum number of instructions that a program may execute. + /// If the maximum is set to zero, then no cap will be applied. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog)).unwrap(); + /// // Set maximum instruction count. + /// vm.set_max_instruction_count(1000).unwrap(); + /// ``` + pub fn set_max_instruction_count(&mut self, count: usize) -> Result<(), Error> { + self.parent.set_max_instruction_count(count) + } + + /// Returns the number of instruction executed by the last program. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// use solana_rbpf::ebpf; + /// + /// let prog = &[ + /// 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 + /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit + /// ]; + /// + /// // Instantiate a VM. + /// let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); + /// // Execute the program. + /// let res = vm.execute_program().unwrap(); + /// // Get the number of instructions executed. + /// let count = vm.get_last_instruction_count(); + /// ``` + pub fn get_last_instruction_count(&self) -> usize { + self.parent.get_last_instruction_count() + } + /// Register a built-in or user-defined helper function in order to use it later from within /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`. /// @@ -1517,7 +1731,6 @@ impl<'a> EbpfVmNoData<'a> { /// /// let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); /// - /// /// vm.jit_compile(); /// ``` #[cfg(not(windows))] @@ -1536,13 +1749,13 @@ impl<'a> EbpfVmNoData<'a> { /// 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit /// ]; /// - /// let vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); + /// let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); /// /// // For this kind of VM, the `execute_program()` function needs no argument. /// let res = vm.execute_program().unwrap(); /// assert_eq!(res, 0x1122); /// ``` - pub fn execute_program(&self) -> Result<(u64), Error> { + pub fn execute_program(&mut self) -> Result<(u64), Error> { self.parent.execute_program(&mut []) } diff --git a/tests/misc.rs b/tests/misc.rs index 232aa74b..8e4d0b7e 100644 --- a/tests/misc.rs +++ b/tests/misc.rs @@ -281,7 +281,7 @@ fn test_vm_mbuff() { *data_end = mem.as_ptr() as u64 + mem.len() as u64; } - let vm = EbpfVmMbuff::new(Some(prog)).unwrap(); + let mut vm = EbpfVmMbuff::new(Some(prog)).unwrap(); assert_eq!(vm.execute_program(mem, &mbuff).unwrap(), 0x2211); } @@ -308,7 +308,7 @@ fn test_vm_mbuff_with_rust_api() { *data_end = mem.as_ptr() as u64 + mem.len() as u64; } - let vm = EbpfVmMbuff::new(Some(program.into_bytes())).unwrap(); + let mut vm = EbpfVmMbuff::new(Some(program.into_bytes())).unwrap(); assert_eq!(vm.execute_program(mem, &mbuff).unwrap(), 0x2211); } @@ -349,16 +349,17 @@ fn test_vm_jit_ldabsb() { 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 = [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0x33); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0x33); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x33); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0x33); }; } @@ -369,16 +370,17 @@ fn test_vm_jit_ldabsh() { 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 = [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0x4433); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0x4433); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x4433); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0x4433); }; } @@ -389,16 +391,17 @@ fn test_vm_jit_ldabsw() { 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 =[ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0x66554433); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0x66554433); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x66554433); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0x66554433); }; } @@ -409,16 +412,17 @@ fn test_vm_jit_ldabsdw() { 0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 = [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0xaa99887766554433); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0xaa99887766554433); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0xaa99887766554433); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0xaa99887766554433); }; } @@ -433,7 +437,7 @@ fn test_vm_err_ldabsb_oob() { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; - let vm = EbpfVmRaw::new(Some(prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); vm.execute_program(mem).unwrap(); // Memory check not implemented for JIT yet. @@ -446,7 +450,7 @@ fn test_vm_err_ldabsb_nomem() { 0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let vm = EbpfVmNoData::new(Some(prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); vm.execute_program().unwrap(); // Memory check not implemented for JIT yet. @@ -460,16 +464,17 @@ fn test_vm_jit_ldindb() { 0x50, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 = [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0x88); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0x88); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x88); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0x88); }; } @@ -481,16 +486,17 @@ fn test_vm_jit_ldindh() { 0x48, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 = [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0x9988); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0x9988); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x9988); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0x9988); }; } @@ -502,16 +508,17 @@ fn test_vm_jit_ldindw() { 0x40, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 = [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0x88776655); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0x88776655); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0x88776655); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0x88776655); }; } @@ -523,16 +530,17 @@ fn test_vm_jit_ldinddw() { 0x58, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let mem = &mut [ + let mut mem1 = [ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; + let mut mem2 = mem1.clone(); let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); - assert_eq!(vm.execute_program(mem).unwrap(), 0xccbbaa9988776655); + assert_eq!(vm.execute_program(&mut mem1).unwrap(), 0xccbbaa9988776655); vm.jit_compile().unwrap(); unsafe { - assert_eq!(vm.execute_program_jit(mem).unwrap(), 0xccbbaa9988776655); + assert_eq!(vm.execute_program_jit(&mut mem2).unwrap(), 0xccbbaa9988776655); }; } @@ -548,7 +556,7 @@ fn test_vm_err_ldindb_oob() { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, ]; - let vm = EbpfVmRaw::new(Some(prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); vm.execute_program(mem).unwrap(); // Memory check not implemented for JIT yet. @@ -562,7 +570,7 @@ fn test_vm_err_ldindb_nomem() { 0x38, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let vm = EbpfVmNoData::new(Some(prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); vm.execute_program().unwrap(); // Memory check not implemented for JIT yet. @@ -571,7 +579,7 @@ fn test_vm_err_ldindb_nomem() { #[test] #[should_panic(expected = "Error: No program set, call prog_set() to load one")] fn test_vm_exec_no_program() { - let vm = EbpfVmNoData::new(None).unwrap(); + let mut vm = EbpfVmNoData::new(None).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xBEE); } @@ -606,7 +614,7 @@ fn test_verifier_fail() { let mut vm = EbpfVmNoData::new(None).unwrap(); vm.set_verifier(verifier_fail).unwrap(); vm.set_program(&prog).unwrap(); - assert_eq!(vm.execute_program().unwrap(), 0xBEE); + //assert_eq!(vm.execute_program().unwrap(), 0xBEE); } #[test] @@ -626,5 +634,60 @@ fn test_non_terminating() { ]; let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap(); + vm.set_max_instruction_count(1000).unwrap(); vm.execute_program().unwrap(); } + +#[test] +fn test_non_terminate_capped() { + let prog = &[ + 0xb7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbf, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x05, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); + vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap(); + vm.set_max_instruction_count(6).unwrap(); + let _ = vm.execute_program(); + assert!(vm.get_last_instruction_count() == 6); +} + +#[test] +fn test_non_terminate_early() { + let prog = &[ + 0xb7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbf, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x85, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x05, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); + vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap(); + vm.set_max_instruction_count(1000).unwrap(); + let _ = vm.execute_program(); + assert!(vm.get_last_instruction_count() == 1000); +} + +#[test] +fn test_get_last_instruction_count() { + let prog = &[ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); + vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap(); + let _ = vm.execute_program(); + println!("count {:?}", vm.get_last_instruction_count()); + assert!(vm.get_last_instruction_count() == 1); +} diff --git a/tests/ubpf_verifier.rs b/tests/ubpf_verifier.rs index 72523ca2..258d32ab 100644 --- a/tests/ubpf_verifier.rs +++ b/tests/ubpf_verifier.rs @@ -34,7 +34,7 @@ fn test_verifier_err_div_by_zero_imm() { mov32 r0, 1 div32 r0, 0 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -46,7 +46,7 @@ fn test_verifier_err_endian_size() { 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let vm = EbpfVmNoData::new(Some(prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); vm.execute_program().unwrap(); } @@ -57,7 +57,7 @@ fn test_verifier_err_incomplete_lddw() { // Note: ubpf has test-err-incomplete-l 0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let vm = EbpfVmNoData::new(Some(prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); vm.execute_program().unwrap(); } @@ -67,7 +67,7 @@ fn test_verifier_err_infinite_loop() { let prog = assemble(" ja -1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -77,7 +77,7 @@ fn test_verifier_err_invalid_reg_dst() { let prog = assemble(" mov r11, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -87,7 +87,7 @@ fn test_verifier_err_invalid_reg_src() { let prog = assemble(" mov r0, r11 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -98,7 +98,7 @@ fn test_verifier_err_jmp_lddw() { ja +1 lddw r0, 0x1122334455667788 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -108,7 +108,7 @@ fn test_verifier_err_jmp_out() { let prog = assemble(" ja +2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -117,7 +117,7 @@ fn test_verifier_err_jmp_out() { fn test_verifier_err_no_exit() { let prog = assemble(" mov32 r0, 0").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -133,7 +133,7 @@ fn test_verifier_err_too_many_instructions() { }).collect::>(); prog.append(&mut vec![ 0x95, 0, 0, 0, 0, 0, 0, 0 ]); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -144,7 +144,7 @@ fn test_verifier_err_unknown_opcode() { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let vm = EbpfVmNoData::new(Some(prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(prog)).unwrap(); vm.execute_program().unwrap(); } @@ -154,6 +154,6 @@ fn test_verifier_err_write_r10() { let prog = assemble(" mov r10, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } diff --git a/tests/ubpf_vm.rs b/tests/ubpf_vm.rs index 837a4fa0..23449a2f 100644 --- a/tests/ubpf_vm.rs +++ b/tests/ubpf_vm.rs @@ -37,7 +37,7 @@ fn test_vm_add() { add32 r0, 1 add32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x3); } @@ -63,7 +63,7 @@ fn test_vm_alu64_arith() { div r0, 2 div r0, r4 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x2a); } @@ -93,7 +93,7 @@ fn test_vm_alu64_bit() { xor r0, 0x03 xor r0, r2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x11); } @@ -119,7 +119,7 @@ fn test_vm_alu_arith() { div32 r0, 2 div32 r0, r4 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x2a); } @@ -147,7 +147,7 @@ fn test_vm_alu_bit() { xor32 r0, 0x03 xor32 r0, r2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x11); } @@ -158,7 +158,7 @@ fn test_vm_arsh32_high_shift() { lddw r1, 0x100000001 arsh32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x4); } @@ -169,7 +169,7 @@ fn test_vm_arsh() { lsh32 r0, 28 arsh32 r0, 16 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xffff8000); } @@ -182,7 +182,7 @@ fn test_vm_arsh64() { mov32 r1, 5 arsh r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xfffffffffffffff8); } @@ -194,7 +194,7 @@ fn test_vm_arsh_reg() { lsh32 r0, 28 arsh32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xffff8000); } @@ -207,7 +207,7 @@ fn test_vm_be16() { let mem = &mut [ 0x11, 0x22 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1122); } @@ -220,7 +220,7 @@ fn test_vm_be16_high() { let mem = &mut [ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1122); } @@ -233,7 +233,7 @@ fn test_vm_be32() { let mem = &mut [ 0x11, 0x22, 0x33, 0x44 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x11223344); } @@ -246,7 +246,7 @@ fn test_vm_be32_high() { let mem = &mut [ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x11223344); } @@ -259,7 +259,7 @@ fn test_vm_be64() { let mem = &mut [ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1122334455667788); } @@ -325,7 +325,7 @@ fn test_vm_div32_high_divisor() { lddw r1, 0x100000004 div32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x3); } @@ -335,7 +335,7 @@ fn test_vm_div32_imm() { lddw r0, 0x10000000c div32 r0, 4 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x3); } @@ -346,7 +346,7 @@ fn test_vm_div32_reg() { mov r1, 4 div32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x3); } @@ -357,7 +357,7 @@ fn test_vm_div64_imm() { lsh r0, 32 div r0, 4 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x300000000); } @@ -369,7 +369,7 @@ fn test_vm_div64_reg() { mov r1, 4 div r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x300000000); } @@ -380,7 +380,7 @@ fn test_vm_early_exit() { exit mov r0, 4 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x3); } @@ -400,7 +400,7 @@ fn test_vm_err_call_unreg() { mov r5, 5 call 63 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -412,7 +412,7 @@ fn test_vm_err_div64_by_zero_reg() { mov32 r1, 0 div r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -424,7 +424,7 @@ fn test_vm_err_div_by_zero_reg() { mov32 r1, 0 div32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -436,7 +436,7 @@ fn test_vm_err_mod64_by_zero_reg() { mov32 r1, 0 mod r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -448,7 +448,7 @@ fn test_vm_err_mod_by_zero_reg() { mov32 r1, 0 mod32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -458,7 +458,7 @@ fn test_vm_err_stack_out_of_bound() { let prog = assemble(" stb [r10], 0 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); vm.execute_program().unwrap(); } @@ -467,7 +467,7 @@ fn test_vm_exit() { let prog = assemble(" mov r0, 0 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x0); } @@ -478,7 +478,7 @@ fn test_vm_ja() { ja +1 mov r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -493,7 +493,7 @@ fn test_vm_jeq_imm() { jeq r1, 0xb, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -509,7 +509,7 @@ fn test_vm_jeq_reg() { jeq r1, r2, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -524,7 +524,7 @@ fn test_vm_jge_imm() { jge r1, 0xb, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -540,7 +540,7 @@ fn test_vm_jle_imm() { exit mov32 r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -558,7 +558,7 @@ fn test_vm_jle_reg() { exit mov r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -573,7 +573,7 @@ fn test_vm_jgt_imm() { exit mov32 r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -590,7 +590,7 @@ fn test_vm_jgt_reg() { exit mov r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -605,7 +605,7 @@ fn test_vm_jlt_imm() { exit mov32 r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -622,7 +622,7 @@ fn test_vm_jlt_reg() { exit mov r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -636,7 +636,7 @@ fn test_vm_jit_bounce() { mov r9, r8 mov r0, r9 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -652,7 +652,7 @@ fn test_vm_jne_reg() { jne r1, r2, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -667,7 +667,7 @@ fn test_vm_jset_imm() { jset r1, 0x8, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -683,7 +683,7 @@ fn test_vm_jset_reg() { jset r1, r2, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -699,7 +699,7 @@ fn test_vm_jsge_imm() { jsge r1, -1, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -717,7 +717,7 @@ fn test_vm_jsge_reg() { jsge r1, r2, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -733,7 +733,7 @@ fn test_vm_jsle_imm() { jsle r1, -2, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -752,7 +752,7 @@ fn test_vm_jsle_reg() { jsle r1, r2, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -767,7 +767,7 @@ fn test_vm_jsgt_imm() { jsgt r1, -1, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -783,7 +783,7 @@ fn test_vm_jsgt_reg() { jsgt r1, r2, +1 mov32 r0, 2 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -798,7 +798,7 @@ fn test_vm_jslt_imm() { exit mov32 r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -815,7 +815,7 @@ fn test_vm_jslt_reg() { exit mov32 r0, 1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -823,7 +823,7 @@ fn test_vm_jslt_reg() { fn test_vm_lddw() { let prog = assemble("lddw r0, 0x1122334455667788 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1122334455667788); } @@ -832,7 +832,7 @@ fn test_vm_lddw2() { let prog = assemble(" lddw r0, 0x0000000080000000 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x80000000); } @@ -874,7 +874,7 @@ fn test_vm_ldxb_all() { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x9876543210); } @@ -886,7 +886,7 @@ fn test_vm_ldxb() { let mem = &mut [ 0xaa, 0xbb, 0x11, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x11); } @@ -899,7 +899,7 @@ fn test_vm_ldxdw() { 0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x8877665544332211); } @@ -952,7 +952,7 @@ fn test_vm_ldxh_all() { 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x9876543210); } @@ -995,7 +995,7 @@ fn test_vm_ldxh_all2() { 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x3ff); } @@ -1007,7 +1007,7 @@ fn test_vm_ldxh() { let mem = &mut [ 0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x2211); } @@ -1021,7 +1021,7 @@ fn test_vm_ldxh_same_reg() { let mem = &mut [ 0xff, 0xff ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1234); } @@ -1066,7 +1066,7 @@ fn test_vm_ldxw_all() { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x030f0f); } @@ -1078,7 +1078,7 @@ fn test_vm_ldxw() { let mem = &mut [ 0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211); } @@ -1091,7 +1091,7 @@ fn test_vm_le16() { let mem = &mut [ 0x22, 0x11 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1122); } @@ -1104,7 +1104,7 @@ fn test_vm_le32() { let mem = &mut [ 0x44, 0x33, 0x22, 0x11 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x11223344); } @@ -1117,7 +1117,7 @@ fn test_vm_le64() { let mem = &mut [ 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1122334455667788); } @@ -1128,7 +1128,7 @@ fn test_vm_lsh_reg() { mov r7, 4 lsh r0, r7 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x10); } @@ -1140,7 +1140,7 @@ fn test_vm_mod() { mov32 r1, 13 mod32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x5); } @@ -1150,7 +1150,7 @@ fn test_vm_mod32() { lddw r0, 0x100000003 mod32 r0, 3 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x0); } @@ -1166,7 +1166,7 @@ fn test_vm_mod64() { mod r0, r1 mod r0, 0x658f1778 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x30ba5a04); } @@ -1176,7 +1176,7 @@ fn test_vm_mov() { mov32 r1, 1 mov32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -1186,7 +1186,7 @@ fn test_vm_mul32_imm() { mov r0, 3 mul32 r0, 4 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xc); } @@ -1197,7 +1197,7 @@ fn test_vm_mul32_reg() { mov r1, 4 mul32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xc); } @@ -1208,7 +1208,7 @@ fn test_vm_mul32_reg_overflow() { mov r1, 4 mul32 r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x4); } @@ -1218,7 +1218,7 @@ fn test_vm_mul64_imm() { mov r0, 0x40000001 mul r0, 4 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x100000004); } @@ -1229,7 +1229,7 @@ fn test_vm_mul64_reg() { mov r1, 4 mul r0, r1 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x100000004); } @@ -1246,7 +1246,7 @@ fn test_vm_mul_loop() { add r1, -1 jne r1, 0x0, -3 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x75db9c97); } @@ -1256,7 +1256,7 @@ fn test_vm_neg64() { mov32 r0, 2 neg r0 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xfffffffffffffffe); } @@ -1266,7 +1266,7 @@ fn test_vm_neg() { mov32 r0, 2 neg32 r0 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xfffffffe); } @@ -1289,7 +1289,7 @@ fn test_vm_prime() { mov r0, 0x0 jne r4, 0x0, -10 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -1300,7 +1300,7 @@ fn test_vm_rhs32() { sub r0, 1 rsh32 r0, 8 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x00ffffff); } @@ -1311,7 +1311,7 @@ fn test_vm_rsh_reg() { mov r7, 4 rsh r0, r7 exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0x1); } @@ -1327,7 +1327,7 @@ fn test_vm_stack() { add r2, r1 ldxdw r0, [r2-16] exit").unwrap(); - let vm = EbpfVmNoData::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmNoData::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program().unwrap(), 0xcd); } @@ -1365,7 +1365,7 @@ fn test_vm_stb() { let mem = &mut [ 0xaa, 0xbb, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x11); } @@ -1379,7 +1379,7 @@ fn test_vm_stdw() { 0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211); } @@ -1392,7 +1392,7 @@ fn test_vm_sth() { let mem = &mut [ 0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x2211); } @@ -1441,7 +1441,7 @@ fn test_vm_stw() { let mem = &mut [ 0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211); } @@ -1455,7 +1455,7 @@ fn test_vm_stxb() { let mem = &mut [ 0xaa, 0xbb, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x11); } @@ -1484,7 +1484,7 @@ fn test_vm_stxb_all() { let mem = &mut [ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0xf0f2f3f4f5f6f7f8); } @@ -1502,7 +1502,7 @@ fn test_vm_stxb_all2() { let mem = &mut [ 0xff, 0xff ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0xf1f9); } @@ -1534,7 +1534,7 @@ fn test_vm_stxb_chain() { 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x2a); } @@ -1551,7 +1551,7 @@ fn test_vm_stxdw() { 0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x8877665544332211); } @@ -1565,7 +1565,7 @@ fn test_vm_stxh() { let mem = &mut [ 0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x2211); } @@ -1579,7 +1579,7 @@ fn test_vm_stxw() { let mem = &mut [ 0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x44332211); } @@ -1612,7 +1612,7 @@ fn test_vm_subnet() { 0x27, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00 ]; - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1); } @@ -1657,7 +1657,7 @@ fn test_vm_tcp_port80_match() { 0x44, 0x44, 0x44, 0x44 ]; let prog = &PROG_TCP_PORT_80; - let vm = EbpfVmRaw::new(Some(prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x1); } @@ -1679,7 +1679,7 @@ fn test_vm_tcp_port80_nomatch() { 0x44, 0x44, 0x44, 0x44 ]; let prog = &PROG_TCP_PORT_80; - let vm = EbpfVmRaw::new(Some(prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x0); } @@ -1701,7 +1701,7 @@ fn test_vm_tcp_port80_nomatch_ethertype() { 0x44, 0x44, 0x44, 0x44 ]; let prog = &PROG_TCP_PORT_80; - let vm = EbpfVmRaw::new(Some(prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x0); } @@ -1723,7 +1723,7 @@ fn test_vm_tcp_port80_nomatch_proto() { 0x44, 0x44, 0x44, 0x44 ]; let prog = &PROG_TCP_PORT_80; - let vm = EbpfVmRaw::new(Some(prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(prog)).unwrap(); assert_eq!(vm.execute_program(mem).unwrap(), 0x0); } @@ -1731,7 +1731,7 @@ fn test_vm_tcp_port80_nomatch_proto() { fn test_vm_tcp_sack_match() { let mut mem = TCP_SACK_MATCH.to_vec(); let prog = assemble(TCP_SACK_ASM).unwrap(); - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem.as_mut_slice()).unwrap(), 0x1); } @@ -1739,6 +1739,6 @@ fn test_vm_tcp_sack_match() { fn test_vm_tcp_sack_nomatch() { let mut mem = TCP_SACK_NOMATCH.to_vec(); let prog = assemble(TCP_SACK_ASM).unwrap(); - let vm = EbpfVmRaw::new(Some(&prog)).unwrap(); + let mut vm = EbpfVmRaw::new(Some(&prog)).unwrap(); assert_eq!(vm.execute_program(mem.as_mut_slice()).unwrap(), 0x0); }