Skip to main content

fluentbase_runtime/syscall_handler/host/
read_input.rs

1//! Builtin to copy a slice of the input buffer into linear memory.
2use crate::syscall_handler::syscall_process_exit_code;
3use crate::RuntimeContext;
4use fluentbase_types::ExitCode;
5use rwasm::{StoreTr, TrapCode, Value};
6
7/// Reads [offset, offset+length) from `ctx.input` and writes it at target_ptr.
8pub fn syscall_read_input_handler(
9    ctx: &mut impl StoreTr<RuntimeContext>,
10    params: &[Value],
11    _result: &mut [Value],
12) -> Result<(), TrapCode> {
13    let (target_ptr, offset, length) = (
14        params[0].i32().unwrap() as usize,
15        params[1].i32().unwrap() as u32,
16        params[2].i32().unwrap() as u32,
17    );
18    let input = syscall_read_input_impl(ctx.data_mut(), offset, length)
19        .map_err(|exit_code| syscall_process_exit_code(ctx, exit_code))?;
20    ctx.memory_write(target_ptr, &input)?;
21    Ok(())
22}
23
24pub fn syscall_read_input_impl(
25    ctx: &mut RuntimeContext,
26    offset: u32,
27    length: u32,
28) -> Result<Vec<u8>, ExitCode> {
29    let offset_length = offset
30        .checked_add(length)
31        .ok_or(ExitCode::InputOutputOutOfBounds)?;
32    if offset_length <= ctx.input.len() as u32 {
33        Ok(ctx.input[(offset as usize)..(offset as usize + length as usize)].to_vec())
34    } else {
35        Err(ExitCode::InputOutputOutOfBounds)
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn test_offset_overflow_causes_memory_out_of_bounds() {
45        let mut ctx = RuntimeContext::default();
46        let exit_code = syscall_read_input_impl(&mut ctx, u32::MAX, 100).unwrap_err();
47        assert_eq!(exit_code, ExitCode::InputOutputOutOfBounds);
48    }
49}