Skip to content

Commit

Permalink
Add check_initializing_stack to check mem issues
Browse files Browse the repository at this point in the history
  • Loading branch information
doitian committed Dec 23, 2024
1 parent 68a5331 commit ed6a8f6
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/machine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use super::memory::Memory;
use super::syscalls::Syscalls;
use super::{
registers::{A0, A7, REGISTER_ABI_NAMES, SP},
error::OutOfBoundKind,
Error, ISA_MOP, RISCV_GENERAL_REGISTER_NUMBER,
};

Expand Down Expand Up @@ -252,6 +253,43 @@ pub trait SupportMachine: CoreMachine {
Ok(stack_start + stack_size - self.registers()[SP].to_u64())
}

// Dry run initialize_stack to see whether it will cause memorh errors.
//
// Returns `Ok(())` when the stack is enough. Returns `Err` when `initialize_stack` will fail because of
// `MemOutOfStack` or `MemOutOfBound`.
fn check_initializing_stack(
&mut self,
args_lens: &[u64],
stack_start: u64,
stack_size: u64,
) -> Result<(), Error> {
if self.version() >= VERSION1 && args_lens.is_empty() {
return Ok(());
}

let mut sp = stack_start + stack_size;
let mut values_len = args_lens.len() as u64 + 1;
for arg_len in args_lens {
sp = wrapping_sub_address_or_mem_out_of_bound(sp, arg_len + 1)?;
}
if self.version() >= VERSION1 {
values_len += 1;
let values_bytes = Self::REG::BITS as u64 / 8 * values_len;
let unaligned_sp_address = wrapping_sub_address_or_mem_out_of_bound(sp, values_bytes)?;
let aligned_sp_address = unaligned_sp_address & (!15);
let aligned_bytes = unaligned_sp_address - aligned_sp_address;
sp = wrapping_sub_address_or_mem_out_of_bound(sp, aligned_bytes)?;
}

sp = wrapping_sub_address_or_mem_out_of_bound(sp, Self::REG::BITS as u64 / 8 * values_len)?;
if sp >= stack_start {
Ok(())
} else {
// args exceed stack size
Err(Error::MemOutOfStack)
}
}

#[cfg(feature = "pprof")]
fn code(&self) -> &Bytes;
}
Expand Down Expand Up @@ -766,6 +804,13 @@ impl Pause {
}
}

fn wrapping_sub_address_or_mem_out_of_bound(lhs: u64, rhs: u64) -> Result<u64, Error> {
match lhs.overflowing_sub(rhs) {
(result, false) => Ok(result),
(result, true) => Err(Error::MemOutOfBound(result, OutOfBoundKind::Memory)),
}
}

#[cfg(test)]
mod tests {
use std::sync::atomic::AtomicU8;
Expand Down

0 comments on commit ed6a8f6

Please sign in to comment.