use {super::*, crate::declare_syscall}; fn mem_op_consume(invoke_context: &mut InvokeContext, n: u64) -> Result<(), Error> { let compute_budget = invoke_context.get_compute_budget(); let cost = compute_budget .mem_op_base_cost .max(n.saturating_div(compute_budget.cpi_bytes_per_unit)); consume_compute_meter(invoke_context, cost) } declare_syscall!( /// memcpy SyscallMemcpy, fn inner_call( invoke_context: &mut InvokeContext, dst_addr: u64, src_addr: u64, n: u64, _arg4: u64, _arg5: u64, memory_mapping: &mut MemoryMapping, ) -> Result { mem_op_consume(invoke_context, n)?; if !is_nonoverlapping(src_addr, n, dst_addr, n) { return Err(SyscallError::CopyOverlapping.into()); } let dst_ptr = translate_slice_mut::( memory_mapping, dst_addr, n, invoke_context.get_check_aligned(), invoke_context.get_check_size(), )? .as_mut_ptr(); let src_ptr = translate_slice::( memory_mapping, src_addr, n, invoke_context.get_check_aligned(), invoke_context.get_check_size(), )? .as_ptr(); if !is_nonoverlapping(src_ptr as usize, n as usize, dst_ptr as usize, n as usize) { unsafe { std::ptr::copy(src_ptr, dst_ptr, n as usize); } } else { unsafe { std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, n as usize); } } Ok(0) } ); declare_syscall!( /// memmove SyscallMemmove, fn inner_call( invoke_context: &mut InvokeContext, dst_addr: u64, src_addr: u64, n: u64, _arg4: u64, _arg5: u64, memory_mapping: &mut MemoryMapping, ) -> Result { mem_op_consume(invoke_context, n)?; let dst = translate_slice_mut::( memory_mapping, dst_addr, n, invoke_context.get_check_aligned(), invoke_context.get_check_size(), )?; let src = translate_slice::( memory_mapping, src_addr, n, invoke_context.get_check_aligned(), invoke_context.get_check_size(), )?; unsafe { std::ptr::copy(src.as_ptr(), dst.as_mut_ptr(), n as usize); } Ok(0) } ); declare_syscall!( /// memcmp SyscallMemcmp, fn inner_call( invoke_context: &mut InvokeContext, s1_addr: u64, s2_addr: u64, n: u64, cmp_result_addr: u64, _arg5: u64, memory_mapping: &mut MemoryMapping, ) -> Result { mem_op_consume(invoke_context, n)?; let s1 = translate_slice::( memory_mapping, s1_addr, n, invoke_context.get_check_aligned(), invoke_context.get_check_size(), )?; let s2 = translate_slice::( memory_mapping, s2_addr, n, invoke_context.get_check_aligned(), invoke_context.get_check_size(), )?; let cmp_result = translate_type_mut::( memory_mapping, cmp_result_addr, invoke_context.get_check_aligned(), )?; let mut i = 0; while i < n as usize { let a = *s1.get(i).ok_or(SyscallError::InvalidLength)?; let b = *s2.get(i).ok_or(SyscallError::InvalidLength)?; if a != b { *cmp_result = (a as i32).saturating_sub(b as i32); return Ok(0); }; i = i.saturating_add(1); } *cmp_result = 0; Ok(0) } ); declare_syscall!( /// memset SyscallMemset, fn inner_call( invoke_context: &mut InvokeContext, s_addr: u64, c: u64, n: u64, _arg4: u64, _arg5: u64, memory_mapping: &mut MemoryMapping, ) -> Result { mem_op_consume(invoke_context, n)?; let s = translate_slice_mut::( memory_mapping, s_addr, n, invoke_context.get_check_aligned(), invoke_context.get_check_size(), )?; for val in s.iter_mut().take(n as usize) { *val = c as u8; } Ok(0) } );