fluentbase_runtime/syscall_handler/host/
forward_output.rs1use crate::RuntimeContext;
3use fluentbase_types::ExitCode;
4use rwasm::{StoreTr, TrapCode, Value};
5
6pub fn syscall_forward_output_handler(
8 caller: &mut impl StoreTr<RuntimeContext>,
9 params: &[Value],
10 _result: &mut [Value],
11) -> Result<(), TrapCode> {
12 let (offset, length) = (
13 params[0].i32().unwrap() as u32,
14 params[1].i32().unwrap() as u32,
15 );
16 syscall_forward_output_impl(caller.data_mut(), offset, length).map_err(|err| {
17 caller.data_mut().execution_result.exit_code = err.into_i32();
18 TrapCode::ExecutionHalted
19 })
20}
21
22pub fn syscall_forward_output_impl(
23 ctx: &mut RuntimeContext,
24 offset: u32,
25 length: u32,
26) -> Result<(), ExitCode> {
27 let offset_length = offset
28 .checked_add(length)
29 .ok_or(ExitCode::InputOutputOutOfBounds)?;
30 if offset_length <= ctx.execution_result.return_data.len() as u32 {
31 let ret_data = &ctx.execution_result.return_data
32 [(offset as usize)..(offset as usize + length as usize)]
33 .to_vec();
34 ctx.execution_result.output.extend_from_slice(ret_data);
35 Ok(())
36 } else {
37 Err(ExitCode::InputOutputOutOfBounds)
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn test_offset_overflow_causes_memory_out_of_bounds() {
47 let mut ctx = RuntimeContext::default();
48 let exit_code = syscall_forward_output_impl(&mut ctx, u32::MAX, 100).unwrap_err();
49 assert_eq!(exit_code, ExitCode::InputOutputOutOfBounds);
50 }
51}