From b1b4b00a5708b081bee6c5b95c05c8a05d4a6924 Mon Sep 17 00:00:00 2001 From: mohanson Date: Thu, 16 Jan 2025 10:58:32 +0800 Subject: [PATCH] Implement FlattenedArgsReader --- .github/workflows/develop.yml | 2 +- benches/vm_benchmark.rs | 74 ++++++++++++++++-------------- examples/check_real_memory.rs | 10 ++++- examples/ckb_vm_runner.rs | 4 +- src/lib.rs | 6 +-- src/machine/asm/mod.rs | 8 +++- src/machine/mod.rs | 84 +++++++++++++++++++++++++++++++---- src/machine/trace.rs | 8 +++- src/memory/mod.rs | 14 ++++++ tests/machine_build.rs | 12 ++--- tests/test_asm.rs | 81 +++++++++++++++++---------------- tests/test_auipc_fusion.rs | 4 +- tests/test_dy_memory.rs | 4 +- tests/test_misc.rs | 10 ++--- tests/test_reset.rs | 8 ++-- tests/test_resume.rs | 18 +++++--- tests/test_resume2.rs | 61 ++++++++++++++++--------- tests/test_simple.rs | 8 ++-- tests/test_spawn.rs | 76 +++++++++---------------------- tests/test_versions.rs | 16 +++---- 20 files changed, 301 insertions(+), 207 deletions(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 03aff0fc..b6876faf 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -69,7 +69,7 @@ jobs: ln -snf .. ckb-vm-test-suite/ckb-vm docker run --rm -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20210804 cp -r /riscv /code/riscv cd ckb-vm-test-suite - git checkout 2ef749d0f580958043264a798e560fe25fec0c6e + git checkout 898edc351eeb4de974ca4f0ff8d1e4943a95aecb git submodule update --init --recursive RISCV=`pwd`/../riscv ./test.sh diff --git a/benches/vm_benchmark.rs b/benches/vm_benchmark.rs index 81ac8999..e8dbab99 100644 --- a/benches/vm_benchmark.rs +++ b/benches/vm_benchmark.rs @@ -21,12 +21,13 @@ use std::fs; fn interpret_benchmark(c: &mut Criterion) { c.bench_function("interpret secp256k1_bench", |b| { let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let args: Vec = vec!["secp256k1_bench", - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", - "foo", - "bar"].into_iter().map(|a| a.into()).collect(); - + let args: Vec = vec![ + "secp256k1_bench", + "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", + "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", + "foo", + "bar" + ].into_iter().map(|a| a.into()).collect(); b.iter(|| run::>(&buffer, &args[..]).unwrap()); }); } @@ -35,17 +36,18 @@ fn interpret_benchmark(c: &mut Criterion) { fn asm_benchmark(c: &mut Criterion) { c.bench_function("interpret secp256k1_bench via assembly", |b| { let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let args: Vec = vec!["secp256k1_bench", - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", - "foo", - "bar"].into_iter().map(|a| a.into()).collect(); - + let args = [ + Ok("secp256k1_bench".into()), + Ok("033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into()), + Ok("304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into()), + Ok("foo".into()), + Ok("bar".into()), + ].into_iter(); b.iter(|| { let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); - machine.load_program(&buffer, &args[..]).unwrap(); + machine.load_program(&buffer, args.clone()).unwrap(); machine.run().unwrap() }); }); @@ -55,17 +57,19 @@ fn asm_benchmark(c: &mut Criterion) { fn mop_benchmark(c: &mut Criterion) { c.bench_function("interpret secp256k1_bench via assembly mop", |b| { let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let args: Vec = vec!["secp256k1_bench", - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", - "foo", - "bar"].into_iter().map(|a| a.into()).collect(); + let args = [ + Ok("secp256k1_bench".into()), + Ok("033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into()), + Ok("304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into()), + Ok("foo".into()), + Ok("bar".into()), + ].into_iter(); b.iter(|| { let asm_core = AsmCoreMachine::new(ISA_IMC | ISA_B | ISA_MOP, VERSION2, u64::MAX); let core = DefaultMachineBuilder::>::new(asm_core) .build(); let mut machine = AsmMachine::new(core); - machine.load_program(&buffer, &args).unwrap(); + machine.load_program(&buffer, args.clone()).unwrap(); machine.run().unwrap() }); }); @@ -77,17 +81,19 @@ fn mop_memoized_benchmark(c: &mut Criterion) { let isa = ISA_IMC | ISA_B | ISA_MOP; let version = VERSION2; let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let args: Vec = vec!["secp256k1_bench", - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", - "foo", - "bar"].into_iter().map(|a| a.into()).collect(); + let args = [ + Ok("secp256k1_bench".into()), + Ok("033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into()), + Ok("304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into()), + Ok("foo".into()), + Ok("bar".into()), + ].into_iter(); let mut decoder = MemoizedFixedTraceDecoder::new(build_decoder::(isa, version)); let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); let core = DefaultMachineBuilder::>::new(asm_core) .build(); let mut machine = AsmMachine::new(core); - machine.load_program(&buffer, &args).unwrap(); + machine.load_program(&buffer, args.clone()).unwrap(); machine.run_with_decoder(&mut decoder).unwrap(); b.iter(|| { @@ -95,7 +101,7 @@ fn mop_memoized_benchmark(c: &mut Criterion) { let core = DefaultMachineBuilder::>::new(asm_core) .build(); let mut machine = AsmMachine::new(core); - machine.load_program(&buffer, &args).unwrap(); + machine.load_program(&buffer, args.clone()).unwrap(); decoder.clear_traces(); machine.run_with_decoder(&mut decoder).unwrap() }); @@ -108,17 +114,19 @@ fn mop_memoized_dynamic_benchmark(c: &mut Criterion) { let isa = ISA_IMC | ISA_B | ISA_MOP; let version = VERSION2; let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let args: Vec = vec!["secp256k1_bench", - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", - "foo", - "bar"].into_iter().map(|a| a.into()).collect(); + let args = [ + Ok("secp256k1_bench".into()), + Ok("033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into()), + Ok("304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into()), + Ok("foo".into()), + Ok("bar".into()), + ].into_iter(); let mut decoder = MemoizedDynamicTraceDecoder::new(build_decoder::(isa, version)); let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); let core = DefaultMachineBuilder::>::new(asm_core) .build(); let mut machine = AsmMachine::new(core); - machine.load_program(&buffer, &args).unwrap(); + machine.load_program(&buffer, args.clone()).unwrap(); machine.run_with_decoder(&mut decoder).unwrap(); b.iter(|| { @@ -126,7 +134,7 @@ fn mop_memoized_dynamic_benchmark(c: &mut Criterion) { let core = DefaultMachineBuilder::>::new(asm_core) .build(); let mut machine = AsmMachine::new(core); - machine.load_program(&buffer, &args).unwrap(); + machine.load_program(&buffer, args.clone()).unwrap(); decoder.clear_traces(); machine.run_with_decoder(&mut decoder).unwrap() }); diff --git a/examples/check_real_memory.rs b/examples/check_real_memory.rs index c0735ec7..c3a7b9fd 100644 --- a/examples/check_real_memory.rs +++ b/examples/check_real_memory.rs @@ -168,7 +168,10 @@ fn check_asm(memory_size: usize) -> Result<(), ()> { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&Bytes::from(BIN_PATH_BUFFER), &vec![Bytes::from(BIN_NAME)]) + .load_program( + &Bytes::from(BIN_PATH_BUFFER), + [Ok(Bytes::from(BIN_NAME))].into_iter(), + ) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -192,7 +195,10 @@ fn check_asm_in_thread(memory_size: usize) -> Result<(), ()> { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&Bytes::from(BIN_PATH_BUFFER), &vec![Bytes::from(BIN_NAME)]) + .load_program( + &Bytes::from(BIN_PATH_BUFFER), + [Ok(Bytes::from(BIN_NAME))].into_iter(), + ) .unwrap(); let thread_join_handle = thread::spawn(move || { let result = machine.run(); diff --git a/examples/ckb_vm_runner.rs b/examples/ckb_vm_runner.rs index b183d4f2..ac539e82 100644 --- a/examples/ckb_vm_runner.rs +++ b/examples/ckb_vm_runner.rs @@ -49,7 +49,7 @@ fn main_asm(code: Bytes, args: Vec) -> Result<(), Box) -> Result<(), Box + Default>( WXorXMemory::new(M::default()), ); let mut machine = TraceMachine::new(DefaultMachineBuilder::new(core_machine).build()); - machine.load_program(program, args)?; + machine.load_program(program, args.iter().map(|e| Ok(e.clone())))?; machine.run() } @@ -63,7 +63,7 @@ pub fn run_with_memory>( WXorXMemory::new(memory), ); let mut machine = TraceMachine::new(DefaultMachineBuilder::new(core_machine).build()); - machine.load_program(program, args)?; + machine.load_program(program, args.iter().map(|e| Ok(e.clone())))?; machine.run() } diff --git a/src/machine/asm/mod.rs b/src/machine/asm/mod.rs index a5ede118..c0f6a0fb 100644 --- a/src/machine/asm/mod.rs +++ b/src/machine/asm/mod.rs @@ -666,7 +666,11 @@ impl AsmMachine { self.machine.inner.max_cycles = cycles; } - pub fn load_program(&mut self, program: &Bytes, args: &[Bytes]) -> Result { + pub fn load_program( + &mut self, + program: &Bytes, + args: impl ExactSizeIterator>, + ) -> Result { self.machine.load_program(program, args) } @@ -674,7 +678,7 @@ impl AsmMachine { &mut self, program: &Bytes, metadata: &ProgramMetadata, - args: &[Bytes], + args: impl ExactSizeIterator>, ) -> Result { self.machine .load_program_with_metadata(program, metadata, args) diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 8babb792..7dafa615 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -12,7 +12,7 @@ use super::debugger::Debugger; use super::decoder::{build_decoder, InstDecoder}; use super::elf::{parse_elf, LoadingAction, ProgramMetadata}; use super::instructions::{execute, Instruction, Register}; -use super::memory::Memory; +use super::memory::{load_c_string, Memory}; use super::syscalls::Syscalls; use super::{ registers::{A0, A7, REGISTER_ABI_NAMES, SP}, @@ -171,7 +171,7 @@ pub trait SupportMachine: CoreMachine { fn initialize_stack( &mut self, - args: &[Bytes], + args: impl ExactSizeIterator>, stack_start: u64, stack_size: u64, ) -> Result { @@ -183,7 +183,7 @@ pub trait SupportMachine: CoreMachine { // reading "argc" will return an unexpected data. This situation is not very common. // // See https://github.com/nervosnetwork/ckb-vm/issues/106 for more details. - if self.version() >= VERSION1 && args.is_empty() { + if self.version() >= VERSION1 && args.len() == 0 { let argc_size = u64::from(Self::REG::BITS / 8); let origin_sp = stack_start + stack_size; let unaligned_sp_address = origin_sp - argc_size; @@ -200,15 +200,21 @@ pub trait SupportMachine: CoreMachine { // of each argv object. let mut values = vec![Self::REG::from_u64(args.len() as u64)]; for arg in args { + let arg = arg?; let len = Self::REG::from_u64(arg.len() as u64 + 1); let address = self.registers()[SP].overflowing_sub(&len); - self.memory_mut().store_bytes(address.to_u64(), arg)?; + self.memory_mut().store_bytes(address.to_u64(), &arg)?; self.memory_mut() .store_byte(address.to_u64() + arg.len() as u64, 1, 0)?; values.push(address.clone()); - self.set_register(SP, address); + self.set_register(SP, address.clone()); + + if self.version() >= VERSION2 && address.to_u64() < stack_start { + // Provides an early exit to large argv array. + return Err(Error::MemOutOfStack); + } } if self.version() >= VERSION1 { // There are 2 standard requirements of the initialized stack: @@ -246,7 +252,7 @@ pub trait SupportMachine: CoreMachine { self.set_register(SP, address); } if self.registers()[SP].to_u64() < stack_start { - // args exceed stack size + // Args exceed stack size. return Err(Error::MemOutOfStack); } Ok(stack_start + stack_size - self.registers()[SP].to_u64()) @@ -575,7 +581,11 @@ impl Display for DefaultMachine { } impl DefaultMachine { - pub fn load_program(&mut self, program: &Bytes, args: &[Bytes]) -> Result { + pub fn load_program( + &mut self, + program: &Bytes, + args: impl ExactSizeIterator>, + ) -> Result { let elf_bytes = self.load_elf(program, true)?; let stack_bytes = self.initialize(args)?; let bytes = elf_bytes.checked_add(stack_bytes).ok_or_else(|| { @@ -590,7 +600,7 @@ impl DefaultMachine { &mut self, program: &Bytes, metadata: &ProgramMetadata, - args: &[Bytes], + args: impl ExactSizeIterator>, ) -> Result { let elf_bytes = self.load_binary(program, metadata, true)?; let stack_bytes = self.initialize(args)?; @@ -602,7 +612,10 @@ impl DefaultMachine { Ok(bytes) } - fn initialize(&mut self, args: &[Bytes]) -> Result { + fn initialize( + &mut self, + args: impl ExactSizeIterator>, + ) -> Result { for syscall in &mut self.syscalls { syscall.initialize(&mut self.inner)?; } @@ -766,6 +779,59 @@ impl Pause { } } +pub struct FlattenedArgsReader<'a, M: Memory> { + memory: &'a mut M, + argc: M::REG, + argv: M::REG, + cidx: M::REG, +} + +impl<'a, M: Memory> FlattenedArgsReader<'a, M> { + pub fn new(memory: &'a mut M, argc: M::REG, argv: M::REG) -> Self { + Self { + memory, + argc, + argv, + cidx: M::REG::zero(), + } + } +} + +impl<'a, M: Memory> Iterator for FlattenedArgsReader<'a, M> { + type Item = Result; + + fn next(&mut self) -> Option { + if self.cidx.ge(&self.argc).to_u8() == 1 { + return None; + } + let addr = match M::REG::BITS { + 32 => self.memory.load32(&self.argv), + 64 => self.memory.load64(&self.argv), + _ => unreachable!(), + }; + if let Err(err) = addr { + return Some(Err(err)); + }; + let addr = addr.unwrap(); + let cstr = load_c_string(self.memory, &addr); + if let Err(err) = cstr { + return Some(Err(err)); + }; + let cstr = cstr.unwrap(); + self.cidx = self.cidx.overflowing_add(&M::REG::from_u8(1)); + self.argv = self + .argv + .overflowing_add(&M::REG::from_u8(M::REG::BITS / 8)); + Some(Ok(cstr)) + } +} + +impl<'a, M: Memory> ExactSizeIterator for FlattenedArgsReader<'a, M> { + fn len(&self) -> usize { + self.argc.to_u64() as usize + } +} + #[cfg(test)] mod tests { use std::sync::atomic::AtomicU8; diff --git a/src/machine/trace.rs b/src/machine/trace.rs index 9b500f23..7978272b 100644 --- a/src/machine/trace.rs +++ b/src/machine/trace.rs @@ -113,7 +113,11 @@ impl TraceMachine { } } - pub fn load_program(&mut self, program: &Bytes, args: &[Bytes]) -> Result { + pub fn load_program( + &mut self, + program: &Bytes, + args: impl ExactSizeIterator>, + ) -> Result { self.machine.load_program(program, args) } @@ -121,7 +125,7 @@ impl TraceMachine { &mut self, program: &Bytes, metadata: &ProgramMetadata, - args: &[Bytes], + args: impl ExactSizeIterator>, ) -> Result { self.machine .load_program_with_metadata(program, metadata, args) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index bde9e784..3f6cc63b 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -151,3 +151,17 @@ pub(crate) fn memset(slice: &mut [u8], value: u8) { ptr::write_bytes(p, value, slice.len()); } } + +pub fn load_c_string(memory: &mut M, addr: &M::REG) -> Result { + let mut buffer = Vec::new(); + let mut addr = addr.clone(); + loop { + let byte = memory.load8(&addr)?.to_u8(); + if byte == 0 { + break; + } + buffer.push(byte); + addr = addr.overflowing_add(&M::REG::from_u8(1)); + } + Ok(Bytes::from(buffer)) +} diff --git a/tests/machine_build.rs b/tests/machine_build.rs index cb4fcc57..2c50704f 100644 --- a/tests/machine_build.rs +++ b/tests/machine_build.rs @@ -37,9 +37,9 @@ pub fn asm(path: &str, args: Vec, version: u32, isa: u8) -> AsmMachine { .syscall(Box::new(SleepSyscall {})) .build(); let mut machine = AsmMachine::new(core); - let mut argv = vec![Bytes::from("main")]; - argv.extend_from_slice(&args); - machine.load_program(&buffer, &argv).unwrap(); + let mut argv = vec![Ok(Bytes::from("main"))]; + argv.extend(args.into_iter().map(Ok)); + machine.load_program(&buffer, argv.into_iter()).unwrap(); machine } @@ -58,8 +58,8 @@ pub fn int( .syscall(Box::new(SleepSyscall {})) .build(), ); - let mut argv = vec![Bytes::from("main")]; - argv.extend_from_slice(&args); - machine.load_program(&buffer, &argv).unwrap(); + let mut argv = vec![Ok(Bytes::from("main"))]; + argv.extend(args.into_iter().map(Ok)); + machine.load_program(&buffer, argv.into_iter()).unwrap(); machine } diff --git a/tests/test_asm.rs b/tests/test_asm.rs index 14e0e2b7..46b6133f 100644 --- a/tests/test_asm.rs +++ b/tests/test_asm.rs @@ -1,5 +1,4 @@ #![cfg(has_asm)] -use bytes::Bytes; use ckb_vm::cost_model::constant_cycles; use ckb_vm::decoder::build_decoder; use ckb_vm::error::OutOfBoundKind; @@ -22,7 +21,7 @@ pub fn test_asm_simple64() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["simple".into()]) + .load_program(&buffer, [Ok("simple".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -61,7 +60,7 @@ pub fn test_asm_with_custom_syscall() { .build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["syscall".into()]) + .load_program(&buffer, [Ok("syscall".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -97,7 +96,7 @@ pub fn test_asm_ebreak() { .build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["ebreak".into()]) + .load_program(&buffer, [Ok("ebreak".into())].into_iter()) .unwrap(); assert_eq!(value.load(Ordering::Relaxed), 1); let result = machine.run(); @@ -114,7 +113,7 @@ pub fn test_asm_simple_cycles() { .build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["syscall".into()]) + .load_program(&buffer, [Ok("syscall".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -133,7 +132,7 @@ pub fn test_asm_simple_max_cycles_reached() { .build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["syscall".into()]) + .load_program(&buffer, [Ok("syscall".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -147,7 +146,7 @@ pub fn test_asm_trace() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["simple".into()]) + .load_program(&buffer, [Ok("simple".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -161,7 +160,7 @@ pub fn test_asm_jump0() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["jump0_64".into()]) + .load_program(&buffer, [Ok("jump0_64".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -177,7 +176,7 @@ pub fn test_asm_write_large_address() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["write_large_address64".into()]) + .load_program(&buffer, [Ok("write_large_address64".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -194,7 +193,7 @@ pub fn test_misaligned_jump64() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["misaligned_jump64".into()]) + .load_program(&buffer, [Ok("misaligned_jump64".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -207,7 +206,7 @@ pub fn test_mulw64() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["mulw64".into()]) + .load_program(&buffer, [Ok("mulw64".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -221,7 +220,7 @@ pub fn test_invalid_read64() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["invalid_read64".into()]) + .load_program(&buffer, [Ok("invalid_read64".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -241,7 +240,7 @@ pub fn test_asm_load_elf_crash_64() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["load_elf_crash_64".into()]) + .load_program(&buffer, [Ok("load_elf_crash_64".into())].into_iter()) .unwrap(); let result = machine.run(); assert_eq!(result.err(), Some(Error::MemWriteOnExecutablePage(16))); @@ -254,7 +253,7 @@ pub fn test_asm_wxorx_crash_64() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["wxorx_crash_64".into()]) + .load_program(&buffer, [Ok("wxorx_crash_64".into())].into_iter()) .unwrap(); let result = machine.run(); assert_eq!( @@ -273,7 +272,7 @@ pub fn test_asm_alloc_many() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result = machine.run(); assert_eq!(result.unwrap(), 0); @@ -288,7 +287,7 @@ pub fn test_asm_chaos_seed() { let core1 = DefaultMachineBuilder::>::new(asm_core1).build(); let mut machine1 = AsmMachine::new(core1); machine1 - .load_program(&buffer, &vec!["read_memory".into()]) + .load_program(&buffer, [Ok("read_memory".into())].into_iter()) .unwrap(); let result1 = machine1.run(); let exit1 = result1.unwrap(); @@ -299,7 +298,7 @@ pub fn test_asm_chaos_seed() { let core2 = DefaultMachineBuilder::>::new(asm_core2).build(); let mut machine2 = AsmMachine::new(core2); machine2 - .load_program(&buffer, &vec!["read_memory".into()]) + .load_program(&buffer, [Ok("read_memory".into())].into_iter()) .unwrap(); let result2 = machine2.run(); let exit2 = result2.unwrap(); @@ -317,7 +316,7 @@ pub fn test_asm_rvc_pageend() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["rvc_pageend".into()]) + .load_program(&buffer, [Ok("rvc_pageend".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -358,7 +357,7 @@ pub fn test_asm_outofcycles_in_syscall() { .build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["syscall".into()]) + .load_program(&buffer, [Ok("syscall".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -377,7 +376,7 @@ pub fn test_asm_cycles_overflow() { let mut machine = AsmMachine::new(core); machine.machine.set_cycles(u64::MAX - 10); machine - .load_program(&buffer, &vec!["simple64".into()]) + .load_program(&buffer, [Ok("simple64".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -396,7 +395,7 @@ pub fn test_decoder_instructions_cache_pc_out_of_bound_timeout() { let mut machine = AsmMachine::new(core); machine.machine.set_cycles(u64::MAX - 10); machine - .load_program(&buffer, &vec!["simple64".into()]) + .load_program(&buffer, [Ok("simple64".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -413,7 +412,7 @@ fn test_asm_step() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["simple64".into()]) + .load_program(&buffer, [Ok("simple64".into())].into_iter()) .unwrap(); let result = || -> Result { @@ -436,7 +435,7 @@ fn test_asm_thread_safe() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["mulw64".into()]) + .load_program(&buffer, [Ok("mulw64".into())].into_iter()) .unwrap(); let thread_join_handle = thread::spawn(move || { let result = machine.run(); @@ -452,7 +451,9 @@ fn test_zero_address() { let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION1, u64::MAX); let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); - machine.load_program(&buffer, &vec!["zero".into()]).unwrap(); + machine + .load_program(&buffer, [Ok("zero".into())].into_iter()) + .unwrap(); let result = machine.run(); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0); @@ -466,12 +467,13 @@ fn test_memoized_secp256k1() { let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); - let args: Vec = vec!["secp256k1_bench", - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", - "foo", - "bar"].into_iter().map(|a| a.into()).collect(); - machine.load_program(&buffer, &args).unwrap(); + let args = [Ok("secp256k1_bench".into()), + Ok("033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into()), + Ok("304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into()), + Ok("foo".into()), + Ok("bar".into()), + ].into_iter(); + machine.load_program(&buffer, args).unwrap(); let mut decoder = MemoizedFixedTraceDecoder::new(build_decoder::(isa, version)); let result = machine.run_with_decoder(&mut decoder); assert_eq!(result.unwrap(), 0); @@ -485,12 +487,13 @@ fn test_memoized_dynamic_secp256k1() { let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); - let args: Vec = vec!["secp256k1_bench", - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3", - "foo", - "bar"].into_iter().map(|a| a.into()).collect(); - machine.load_program(&buffer, &args).unwrap(); + let args = [Ok("secp256k1_bench".into()), + Ok("033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into()), + Ok("304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into()), + Ok("foo".into()), + Ok("bar".into()), + ].into_iter(); + machine.load_program(&buffer, args).unwrap(); let mut decoder = MemoizedDynamicTraceDecoder::new(build_decoder::(isa, version)); let result = machine.run_with_decoder(&mut decoder); assert_eq!(result.unwrap(), 0); @@ -502,7 +505,7 @@ pub fn test_big_binary() { let asm_core = AsmCoreMachine::new_with_memory(ISA_IMC, VERSION2, u64::MAX, 1024 * 512); let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); - let result = machine.load_program(&buffer, &vec!["simple".into()]); + let result = machine.load_program(&buffer, [Ok("simple".into())].into_iter()); assert_eq!( result, Err(Error::MemOutOfBound(0x111000, OutOfBoundKind::Memory)) @@ -522,7 +525,7 @@ fn test_fast_memory_initialization_bug() { let memory = machine.machine.inner_mut().memory_ptr as *mut u8; memory.write(0x01); } - machine.load_program(&buffer, &[]).unwrap(); + machine.load_program(&buffer, [].into_iter()).unwrap(); assert_eq!(machine.machine.memory_mut().load8(&0).unwrap(), 0); } @@ -532,6 +535,6 @@ pub fn test_memory_load_crash() { let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); - let result = machine.load_program(&buffer, &vec!["memory_crash".into()]); + let result = machine.load_program(&buffer, [Ok("memory_crash".into())].into_iter()); assert_eq!(result.unwrap_err(), Error::MemWriteOnExecutablePage(1023)); } diff --git a/tests/test_auipc_fusion.rs b/tests/test_auipc_fusion.rs index 4a0b6396..65e287c0 100644 --- a/tests/test_auipc_fusion.rs +++ b/tests/test_auipc_fusion.rs @@ -58,7 +58,7 @@ pub fn test_rust_auipc_fusion() { DefaultCoreMachine::>::new(ISA_IMC, VERSION1, u64::MAX); let mut machine = DefaultMachineBuilder::new(core_machine).build(); machine - .load_program(&buffer, &vec!["auipc_no_sign_extend".into()]) + .load_program(&buffer, [Ok("auipc_no_sign_extend".into())].into_iter()) .unwrap(); let mut decoder = AuxDecoder::new(build_decoder::(machine.isa(), machine.version())); @@ -77,7 +77,7 @@ pub fn test_asm_auipc_fusion() { let core = DefaultMachineBuilder::>::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["auipc_no_sign_extend".into()]) + .load_program(&buffer, [Ok("auipc_no_sign_extend".into())].into_iter()) .unwrap(); let decoder = AuxDecoder::new(build_decoder::( diff --git a/tests/test_dy_memory.rs b/tests/test_dy_memory.rs index 732f60ac..21094e12 100644 --- a/tests/test_dy_memory.rs +++ b/tests/test_dy_memory.rs @@ -33,7 +33,7 @@ fn run_memory_suc(memory_size: usize, bin_path: String, bin_name: String) { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec![bin_name.into()]) + .load_program(&buffer, [Ok(bin_name.into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -87,7 +87,7 @@ fn test_memory_out_of_bounds() { let core = DefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); diff --git a/tests/test_misc.rs b/tests/test_misc.rs index bfc855ab..3d36f2fe 100644 --- a/tests/test_misc.rs +++ b/tests/test_misc.rs @@ -63,7 +63,7 @@ pub fn test_custom_syscall() { .syscall(Box::new(CustomSyscall {})) .build(); machine - .load_program(&buffer, &vec!["syscall".into()]) + .load_program(&buffer, [Ok("syscall".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -98,7 +98,7 @@ pub fn test_ebreak() { })) .build(); machine - .load_program(&buffer, &vec!["ebreak".into()]) + .load_program(&buffer, [Ok("ebreak".into())].into_iter()) .unwrap(); assert_eq!(value.load(Ordering::Relaxed), 1); let result = machine.run(); @@ -203,7 +203,7 @@ pub fn test_flat_crash_64() { let buffer = fs::read("tests/programs/flat_crash_64").unwrap().into(); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); let mut machine = DefaultMachineBuilder::new(core_machine).build(); - let result = machine.load_program(&buffer, &vec!["flat_crash_64".into()]); + let result = machine.load_program(&buffer, [Ok("flat_crash_64".into())].into_iter()); assert_eq!( result.err(), Some(Error::MemOutOfBound(0x1100000000, OutOfBoundKind::Memory)) @@ -369,7 +369,7 @@ pub fn test_rvc_pageend() { DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); let mut machine = DefaultMachineBuilder::new(core_machine).build(); machine - .load_program(&buffer, &vec!["rvc_end".into()]) + .load_program(&buffer, [Ok("rvc_end".into())].into_iter()) .unwrap(); let anchor_pc: u64 = 69630; @@ -423,7 +423,7 @@ pub fn test_outofcycles_in_syscall() { .syscall(Box::new(OutOfCyclesSyscall {})) .build(); machine - .load_program(&buffer, &vec!["syscall".into()]) + .load_program(&buffer, [Ok("syscall".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); diff --git a/tests/test_reset.rs b/tests/test_reset.rs index 442d6e70..b4eff886 100644 --- a/tests/test_reset.rs +++ b/tests/test_reset.rs @@ -30,7 +30,7 @@ impl Syscalls for CustomSyscall { let code = Bytes::from(code_data); machine.load_elf(&code, true).unwrap(); machine.initialize_stack( - &[], + [].into_iter(), (DEFAULT_MEMORY_SIZE - DEFAULT_MEMORY_SIZE / 4) as u64, (DEFAULT_MEMORY_SIZE / 4) as u64, )?; @@ -52,7 +52,7 @@ fn test_reset_int() { .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(CustomSyscall {})) .build(); - machine.load_program(&code, &vec![]).unwrap(); + machine.load_program(&code, [].into_iter()).unwrap(); let result = machine.run(); let cycles = machine.cycles(); assert!(result.is_ok()); @@ -76,7 +76,7 @@ fn test_reset_int_with_trace() { .syscall(Box::new(CustomSyscall {})) .build(), ); - machine.load_program(&code, &vec![]).unwrap(); + machine.load_program(&code, [].into_iter()).unwrap(); let result = machine.run(); let cycles = machine.machine.cycles(); assert!(result.is_ok()); @@ -96,7 +96,7 @@ fn test_reset_asm() { .syscall(Box::new(CustomSyscall {})) .build(); let mut machine = AsmMachine::new(core); - machine.load_program(&code, &vec![]).unwrap(); + machine.load_program(&code, [].into_iter()).unwrap(); let result = machine.run(); let cycles = machine.machine.cycles(); diff --git a/tests/test_resume.rs b/tests/test_resume.rs index b42c95dd..ee957ef9 100644 --- a/tests/test_resume.rs +++ b/tests/test_resume.rs @@ -55,7 +55,7 @@ pub fn resume_asm_2_asm(version: u32, except_cycles: u64) { // The cycles required for complete execution is 4194622 let mut machine1 = MachineTy::Asm.build(version, except_cycles - 30); machine1 - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result1 = machine1.run(); let cycles1 = machine1.cycles(); @@ -77,7 +77,7 @@ pub fn resume_asm_2_asm_2_asm(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Asm.build(version, 1000000); machine1 - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result1 = machine1.run(); let cycles1 = machine1.cycles(); @@ -107,7 +107,7 @@ pub fn resume_asm_2_interpreter(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Asm.build(version, except_cycles - 30); machine1 - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result1 = machine1.run(); let cycles1 = machine1.cycles(); @@ -130,7 +130,7 @@ pub fn resume_interpreter_2_interpreter(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Interpreter.build(version, except_cycles - 30); machine1 - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result1 = machine1.run(); let cycles1 = machine1.cycles(); @@ -152,7 +152,7 @@ pub fn resume_interpreter_2_asm(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Interpreter.build(version, except_cycles - 30); machine1 - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result1 = machine1.run(); let cycles1 = machine1.cycles(); @@ -174,7 +174,7 @@ pub fn resume_interpreter_with_trace_2_asm_inner(version: u32, except_cycles: u6 let mut machine1 = MachineTy::InterpreterWithTrace.build(version, except_cycles - 30); machine1 - .load_program(&buffer, &vec!["alloc_many".into()]) + .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) .unwrap(); let result1 = machine1.run(); let cycles1 = machine1.cycles(); @@ -251,7 +251,11 @@ enum Machine { } impl Machine { - fn load_program(&mut self, program: &Bytes, args: &[Bytes]) -> Result { + fn load_program( + &mut self, + program: &Bytes, + args: impl ExactSizeIterator>, + ) -> Result { use Machine::*; match self { Asm(inner) => inner.load_program(program, args), diff --git a/tests/test_resume2.rs b/tests/test_resume2.rs index d1078cb9..480e63be 100644 --- a/tests/test_resume2.rs +++ b/tests/test_resume2.rs @@ -64,15 +64,13 @@ fn test_resume2_secp256k1_asm_2_interpreter_2_asm() { let mut machine1 = MachineTy::Asm.build(data_source.clone(), version); machine1.set_max_cycles(100000); - machine1 - .load_program(&vec![ - "secp256k1_bench".into(), - "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into(), - "304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into(), - "foo".into(), - "bar".into(), - ]) - .unwrap(); + machine1.load_program([ + Ok("secp256k1_bench".into()), + Ok("033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f".into()), + Ok("304402203679d909f43f073c7c1dcf8468a485090589079ee834e6eed92fea9b09b06a2402201e46f1075afa18f306715e7db87493e7b7e779569aa13c64ab3d09980b3560a3".into()), + Ok("foo".into()), + Ok("bar".into()), + ].into_iter()).unwrap(); let result1 = machine1.run(); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); let snapshot1 = machine1.snapshot().unwrap(); @@ -117,7 +115,7 @@ fn test_resume2_load_data_asm_2_interpreter() { let mut machine1 = MachineTy::Asm.build(data_source.clone(), version); machine1.set_max_cycles(300000); machine1 - .load_program(&vec!["resume2_load_data".into()]) + .load_program([Ok("resume2_load_data".into())].into_iter()) .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); @@ -151,7 +149,7 @@ fn test_resume2_load_data_interpreter_2_asm() { let mut machine1 = MachineTy::Interpreter.build(data_source.clone(), version); machine1.set_max_cycles(300000); machine1 - .load_program(&vec!["resume2_load_data".into()]) + .load_program([Ok("resume2_load_data".into())].into_iter()) .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); @@ -181,7 +179,9 @@ pub fn resume_asm_2_asm(version: u32, except_cycles: u64) { // The cycles required for complete execution is 4194622 let mut machine1 = MachineTy::Asm.build(data_source.clone(), version); machine1.set_max_cycles(except_cycles - 30); - machine1.load_program(&vec!["alloc_many".into()]).unwrap(); + machine1 + .load_program([Ok("alloc_many".into())].into_iter()) + .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); @@ -201,7 +201,9 @@ pub fn resume_asm_2_asm_2_asm(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Asm.build(data_source.clone(), version); machine1.set_max_cycles(1000000); - machine1.load_program(&vec!["alloc_many".into()]).unwrap(); + machine1 + .load_program([Ok("alloc_many".into())].into_iter()) + .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); @@ -229,7 +231,9 @@ pub fn resume_asm_2_interpreter(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Asm.build(data_source.clone(), version); machine1.set_max_cycles(except_cycles - 30); - machine1.load_program(&vec!["alloc_many".into()]).unwrap(); + machine1 + .load_program([Ok("alloc_many".into())].into_iter()) + .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); @@ -250,7 +254,9 @@ pub fn resume_interpreter_2_interpreter(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Interpreter.build(data_source.clone(), version); machine1.set_max_cycles(except_cycles - 30); - machine1.load_program(&vec!["alloc_many".into()]).unwrap(); + machine1 + .load_program([Ok("alloc_many".into())].into_iter()) + .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); @@ -270,7 +276,9 @@ pub fn resume_interpreter_2_asm(version: u32, except_cycles: u64) { let mut machine1 = MachineTy::Interpreter.build(data_source.clone(), version); machine1.set_max_cycles(except_cycles - 30); - machine1.load_program(&vec!["alloc_many".into()]).unwrap(); + machine1 + .load_program([Ok("alloc_many".into())].into_iter()) + .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); @@ -290,7 +298,9 @@ pub fn resume_interpreter_with_trace_2_asm_inner(version: u32, except_cycles: u6 let mut machine1 = MachineTy::InterpreterWithTrace.build(data_source.clone(), version); machine1.set_max_cycles(except_cycles - 30); - machine1.load_program(&vec!["alloc_many".into()]).unwrap(); + machine1 + .load_program([Ok("alloc_many".into())].into_iter()) + .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); @@ -444,7 +454,10 @@ enum Machine { } impl Machine { - fn load_program(&mut self, args: &[Bytes]) -> Result { + fn load_program( + &mut self, + args: impl ExactSizeIterator>, + ) -> Result { use Machine::*; match self { Asm(inner, context) => { @@ -609,7 +622,9 @@ pub fn test_sc_after_snapshot2() { let mut machine1 = MachineTy::Interpreter.build(data_source.clone(), VERSION2); machine1.set_max_cycles(5); - machine1.load_program(&vec!["main".into()]).unwrap(); + machine1 + .load_program([Ok("main".into())].into_iter()) + .unwrap(); let result1 = machine1.run(); assert!(result1.is_err()); assert_eq!(result1.unwrap_err(), Error::CyclesExceeded); @@ -630,7 +645,9 @@ pub fn test_store_bytes_twice() { let mut machine = MachineTy::Asm.build(data_source.clone(), VERSION2); machine.set_max_cycles(u64::MAX); - machine.load_program(&vec!["main".into()]).unwrap(); + machine + .load_program([Ok("main".into())].into_iter()) + .unwrap(); match machine { Machine::Asm(ref mut inner, ref ctx) => { @@ -663,7 +680,9 @@ pub fn test_mixing_snapshot2_writes_with_machine_raw_writes() { let mut machine = MachineTy::Asm.build(data_source.clone(), VERSION2); machine.set_max_cycles(u64::MAX); - machine.load_program(&vec!["main".into()]).unwrap(); + machine + .load_program([Ok("main".into())].into_iter()) + .unwrap(); match machine { Machine::Asm(ref mut inner, ref ctx) => { diff --git a/tests/test_simple.rs b/tests/test_simple.rs index f11daf57..b32161cf 100644 --- a/tests/test_simple.rs +++ b/tests/test_simple.rs @@ -42,7 +42,7 @@ pub fn test_simple_cycles() { .instruction_cycle_func(Box::new(dummy_cycle_func)) .build(); machine - .load_program(&buffer, &vec!["simple".into()]) + .load_program(&buffer, [Ok("simple".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_ok()); @@ -61,7 +61,7 @@ pub fn test_simple_max_cycles_reached() { .instruction_cycle_func(Box::new(dummy_cycle_func)) .build(); machine - .load_program(&buffer, &vec!["simple".into()]) + .load_program(&buffer, [Ok("simple".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); @@ -83,7 +83,7 @@ pub fn test_simple_loaded_bytes() { DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); let mut machine = DefaultMachineBuilder::new(core_machine).build(); let bytes = machine - .load_program(&buffer, &vec!["simple".into()]) + .load_program(&buffer, [Ok("simple".into())].into_iter()) .unwrap(); assert_eq!(bytes, 3831); } @@ -99,7 +99,7 @@ pub fn test_simple_cycles_overflow() { .build(); machine.set_cycles(u64::MAX - 10); machine - .load_program(&buffer, &vec!["simple".into()]) + .load_program(&buffer, [Ok("simple".into())].into_iter()) .unwrap(); let result = machine.run(); assert!(result.is_err()); diff --git a/tests/test_spawn.rs b/tests/test_spawn.rs index 4909275f..e1eb70ff 100644 --- a/tests/test_spawn.rs +++ b/tests/test_spawn.rs @@ -3,34 +3,16 @@ use ckb_vm::cost_model::constant_cycles; #[cfg(has_asm)] use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; use ckb_vm::machine::{trace::TraceMachine, DefaultCoreMachine, VERSION2}; +use ckb_vm::memory::load_c_string; use ckb_vm::registers::{A0, A1, A2, A7}; use ckb_vm::{ - DefaultMachineBuilder, Error, Memory, Register, SparseMemory, SupportMachine, Syscalls, - WXorXMemory, ISA_B, ISA_IMC, ISA_MOP, + DefaultMachineBuilder, Error, FlattenedArgsReader, Register, SparseMemory, SupportMachine, + Syscalls, WXorXMemory, ISA_B, ISA_IMC, ISA_MOP, }; use std::sync::{Arc, Mutex}; // There is a spawn system call in ckb, we must ensure that in the worst case, ckb will not crashed by stack overflow. -pub fn load_c_string(machine: &mut Mac, addr: u64) -> Result { - let mut buffer = Vec::new(); - let mut addr = addr; - - loop { - let byte = machine - .memory_mut() - .load8(&Mac::REG::from_u64(addr))? - .to_u8(); - if byte == 0 { - break; - } - buffer.push(byte); - addr += 1; - } - - Ok(Bytes::from(buffer)) -} - fn stack_depth() -> u64 { let x = 0; unsafe { @@ -62,22 +44,12 @@ impl Syscalls for IntSpawnSyscall { } } - let addr = &machine.registers()[A0]; - let path_byte = load_c_string(machine, addr.to_u64()).unwrap(); + let addr = machine.registers()[A0].clone(); + let path_byte = load_c_string(machine.memory_mut(), &addr).unwrap(); let path = std::str::from_utf8(&path_byte).unwrap(); - let argc = &machine.registers()[A1]; - let argv = &machine.registers()[A2]; - let mut addr = argv.to_u64(); - let mut argv_vec = Vec::new(); - for _ in 0..argc.to_u64() { - let target_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(addr))? - .to_u64(); - let cstr = load_c_string(machine, target_addr)?; - argv_vec.push(cstr); - addr += 8; - } + let argc = machine.registers()[A1].clone(); + let argv = machine.registers()[A2].clone(); + let args_iter = FlattenedArgsReader::new(machine.memory_mut(), argc.clone(), argv); let buffer: Bytes = std::fs::read(path).unwrap().into(); let machine_core = DefaultCoreMachine::>>::new( ISA_IMC | ISA_B | ISA_MOP, @@ -92,7 +64,7 @@ impl Syscalls for IntSpawnSyscall { })) .build(), ); - machine_child.load_program(&buffer, &argv_vec).unwrap(); + machine_child.load_program(&buffer, args_iter).unwrap(); let exit = machine_child.run().unwrap(); machine.set_register(A0, Mac::REG::from_i8(exit)); Ok(true) @@ -124,22 +96,12 @@ impl Syscalls for AsmSpawnSyscall { } } - let addr = &machine.registers()[A0]; - let path_byte = load_c_string(machine, addr.to_u64()).unwrap(); + let addr = machine.registers()[A0].clone(); + let path_byte = load_c_string(machine.memory_mut(), &addr).unwrap(); let path = std::str::from_utf8(&path_byte).unwrap(); - let argc = &machine.registers()[A1]; - let argv = &machine.registers()[A2]; - let mut addr = argv.to_u64(); - let mut argv_vec = Vec::new(); - for _ in 0..argc.to_u64() { - let target_addr = machine - .memory_mut() - .load64(&Mac::REG::from_u64(addr))? - .to_u64(); - let cstr = load_c_string(machine, target_addr)?; - argv_vec.push(cstr); - addr += 8; - } + let argc = machine.registers()[A1].clone(); + let argv = machine.registers()[A2].clone(); + let args_iter = FlattenedArgsReader::new(machine.memory_mut(), argc.clone(), argv); let buffer: Bytes = std::fs::read(path).unwrap().into(); let machine_core_asm = AsmCoreMachine::new(ISA_IMC | ISA_B | ISA_MOP, VERSION2, u64::MAX); let machine_core = DefaultMachineBuilder::>::new(machine_core_asm) @@ -149,7 +111,7 @@ impl Syscalls for AsmSpawnSyscall { })) .build(); let mut machine_child = AsmMachine::new(machine_core); - machine_child.load_program(&buffer, &argv_vec).unwrap(); + machine_child.load_program(&buffer, args_iter).unwrap(); let exit = machine_child.run().unwrap(); machine.set_register(A0, Mac::REG::from_i8(exit)); Ok(true) @@ -174,7 +136,9 @@ pub fn test_spawn_int() { })) .build(), ); - machine.load_program(&buffer, &["main".into()]).unwrap(); + machine + .load_program(&buffer, [Ok("main".into())].into_iter()) + .unwrap(); let result = machine.run(); assert!(result.is_ok()); assert!(result.unwrap() == 0); @@ -197,7 +161,9 @@ pub fn test_spawn_asm() { })) .build(); let mut machine = AsmMachine::new(machine_core); - machine.load_program(&buffer, &["main".into()]).unwrap(); + machine + .load_program(&buffer, [Ok("main".into())].into_iter()) + .unwrap(); let result = machine.run(); assert!(result.is_ok()); assert!(result.unwrap() == 0); diff --git a/tests/test_versions.rs b/tests/test_versions.rs index cdc8b040..589fd9cf 100644 --- a/tests/test_versions.rs +++ b/tests/test_versions.rs @@ -22,7 +22,7 @@ fn create_rust_machine( let mut machine = DefaultMachineBuilder::>::new(core_machine).build(); machine - .load_program(&buffer, &vec![program.into()]) + .load_program(&buffer, [Ok(program.into())].into_iter()) .unwrap(); machine } @@ -34,7 +34,7 @@ fn create_asm_machine(program: String, version: u32) -> AsmMachine { let core = DefaultMachineBuilder::>::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine - .load_program(&buffer, &vec![program.into()]) + .load_program(&buffer, [Ok(program.into())].into_iter()) .unwrap(); machine } @@ -246,7 +246,7 @@ pub fn test_rust_version0_unaligned64() { let core_machine = DefaultCoreMachine::::new(ISA_IMC, VERSION0, u64::MAX); let mut machine = DefaultMachineBuilder::>::new(core_machine).build(); - let result = machine.load_program(&buffer, &vec![program.into()]); + let result = machine.load_program(&buffer, [Ok(program.into())].into_iter()); assert!(result.is_err()); assert_eq!(result.err(), Some(Error::MemWriteOnExecutablePage(16))); } @@ -268,7 +268,7 @@ pub fn test_asm_version0_unaligned64() { let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); let core = DefaultMachineBuilder::>::new(asm_core).build(); let mut machine = AsmMachine::new(core); - let result = machine.load_program(&buffer, &vec![program.into()]); + let result = machine.load_program(&buffer, [Ok(program.into())].into_iter()); assert!(result.is_err()); assert_eq!(result.err(), Some(Error::MemWriteOnExecutablePage(16))); } @@ -351,7 +351,7 @@ pub fn test_asm_version1_asm_trace_bug() { .build(); AsmMachine::new(machine) }; - machine.load_program(&buffer, &[]).unwrap(); + machine.load_program(&buffer, [].into_iter()).unwrap(); let result = machine.run(); assert_eq!(result, Err(Error::CyclesExceeded)); @@ -368,7 +368,7 @@ pub fn test_asm_version2_asm_trace_bug() { .build(); AsmMachine::new(machine) }; - machine.load_program(&buffer, &[]).unwrap(); + machine.load_program(&buffer, [].into_iter()).unwrap(); let result = machine.run(); assert_eq!( @@ -393,7 +393,7 @@ pub fn test_trace_version1_asm_trace_bug() { .build(), ) }; - machine.load_program(&buffer, &[]).unwrap(); + machine.load_program(&buffer, [].into_iter()).unwrap(); let result = machine.run(); assert_eq!(result, Err(Error::CyclesExceeded)); @@ -415,7 +415,7 @@ pub fn test_trace_version2_asm_trace_bug() { .build(), ) }; - machine.load_program(&buffer, &[]).unwrap(); + machine.load_program(&buffer, [].into_iter()).unwrap(); let result = machine.run(); assert_eq!(