sbpf_runtime/syscalls/
memory.rs1use {
2 crate::config::ExecutionCost,
3 sbpf_vm::{
4 compute::ComputeMeter,
5 errors::{SbpfVmError, SbpfVmResult},
6 memory::Memory,
7 },
8};
9
10fn mem_op_consume(n: u64, compute: &ComputeMeter, costs: &ExecutionCost) -> SbpfVmResult<()> {
11 let cost = costs
12 .mem_op_base_cost
13 .max(n.checked_div(costs.cpi_bytes_per_unit).unwrap_or(u64::MAX));
14 compute.consume(cost)
15}
16
17fn is_nonoverlapping(src: u64, src_len: u64, dst: u64, dst_len: u64) -> bool {
18 if src > dst {
19 src.saturating_sub(dst) >= dst_len
20 } else {
21 dst.saturating_sub(src) >= src_len
22 }
23}
24
25pub fn sol_memcpy(
26 registers: [u64; 5],
27 memory: &mut Memory,
28 compute: &ComputeMeter,
29 costs: &ExecutionCost,
30) -> SbpfVmResult<u64> {
31 let dst = registers[0];
32 let src = registers[1];
33 let n = registers[2];
34
35 mem_op_consume(n, compute, costs)?;
36
37 if !is_nonoverlapping(src, n, dst, n) {
38 return Err(SbpfVmError::OverlappingMemoryRegions);
39 }
40
41 let data = memory.read_bytes(src, n as usize)?.to_vec();
42 memory.write_bytes(dst, &data)?;
43 Ok(0)
44}
45
46pub fn sol_memmove(
47 registers: [u64; 5],
48 memory: &mut Memory,
49 compute: &ComputeMeter,
50 costs: &ExecutionCost,
51) -> SbpfVmResult<u64> {
52 let dst = registers[0];
53 let src = registers[1];
54 let n = registers[2];
55
56 mem_op_consume(n, compute, costs)?;
57
58 let data = memory.read_bytes(src, n as usize)?.to_vec();
59 memory.write_bytes(dst, &data)?;
60 Ok(0)
61}
62
63pub fn sol_memset(
64 registers: [u64; 5],
65 memory: &mut Memory,
66 compute: &ComputeMeter,
67 costs: &ExecutionCost,
68) -> SbpfVmResult<u64> {
69 let dst = registers[0];
70 let c = registers[1] as u8;
71 let n = registers[2];
72
73 mem_op_consume(n, compute, costs)?;
74
75 let data = vec![c; n as usize];
76 memory.write_bytes(dst, &data)?;
77 Ok(0)
78}
79
80pub fn sol_memcmp(
81 registers: [u64; 5],
82 memory: &mut Memory,
83 compute: &ComputeMeter,
84 costs: &ExecutionCost,
85) -> SbpfVmResult<u64> {
86 let s1 = registers[0];
87 let s2 = registers[1];
88 let n = registers[2];
89 let result_ptr = registers[3];
90
91 mem_op_consume(n, compute, costs)?;
92
93 let s1_bytes = memory.read_bytes(s1, n as usize)?;
94 let s2_bytes = memory.read_bytes(s2, n as usize)?;
95
96 let mut result: i32 = 0;
97 for i in 0..n as usize {
98 if s1_bytes[i] != s2_bytes[i] {
99 result = (s1_bytes[i] as i32).saturating_sub(s2_bytes[i] as i32);
100 break;
101 }
102 }
103
104 memory.write_u32(result_ptr, result as u32)?;
105 Ok(0)
106}