Added runtime bound checking

This commit is contained in:
Erin 2023-07-26 00:01:25 +02:00 committed by ondra05
parent 8b132dffe3
commit 77d807a17d
2 changed files with 25 additions and 2 deletions

View file

@ -59,14 +59,16 @@ macro_rules! gen_valider {
let start = program; let start = program;
loop { loop {
use crate::opcode::*; use crate::opcode::*;
extern crate std;
program = match program { program = match program {
// End of program // End of program
[] => return Ok(()), [] => return Ok(()),
// Memory load/store cannot go out-of-bounds register array // Memory load/store cannot go out-of-bounds register array
[LD..=ST, reg, _, _, _, _, _, _, _, _, count_0, count_1, ..] // B B D1 D2 D3 D4 D5 D6 D7 D8 H1 H2
[LD..=ST, reg, _, _, _, _, _, _, _, _, _, count_0, count_1, ..]
if usize::from(*reg) * 8 if usize::from(*reg) * 8
+ usize::from(u16::from_le_bytes([*count_1, *count_0])) + usize::from(u16::from_le_bytes([*count_0, *count_1]))
> 2048 => > 2048 =>
{ {
return Err(Error { return Err(Error {

View file

@ -215,6 +215,8 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
LD => { LD => {
// Load. If loading more than register size, continue on adjecent registers // Load. If loading more than register size, continue on adjecent registers
let ParamBBDH(dst, base, off, count) = self.decode(); let ParamBBDH(dst, base, off, count) = self.decode();
ldst_bound_check(dst, count)?;
let n: usize = match dst { let n: usize = match dst {
0 => 1, 0 => 1,
_ => 0, _ => 0,
@ -230,6 +232,8 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
ST => { ST => {
// Store. Same rules apply as to LD // Store. Same rules apply as to LD
let ParamBBDH(dst, base, off, count) = self.decode(); let ParamBBDH(dst, base, off, count) = self.decode();
ldst_bound_check(dst, count)?;
self.memory.store( self.memory.store(
self.read_reg(base).cast::<u64>() + off, self.read_reg(base).cast::<u64>() + off,
self.registers.as_ptr().add(usize::from(dst)).cast(), self.registers.as_ptr().add(usize::from(dst)).cast(),
@ -250,6 +254,10 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
BRC => { BRC => {
// Block register copy // Block register copy
let ParamBBB(src, dst, count) = self.decode(); let ParamBBB(src, dst, count) = self.decode();
if src.checked_add(count).is_none() || dst.checked_add(count).is_none() {
return Err(VmRunError::RegOutOfBounds);
}
core::ptr::copy( core::ptr::copy(
self.registers.get_unchecked(usize::from(src)), self.registers.get_unchecked(usize::from(src)),
self.registers.get_unchecked_mut(usize::from(dst)), self.registers.get_unchecked_mut(usize::from(dst)),
@ -394,6 +402,16 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
} }
} }
/// Load/Store target/source register range bound checking
#[inline]
fn ldst_bound_check(reg: u8, size: u16) -> Result<(), VmRunError> {
if usize::from(reg) * 8 + usize::from(size) > 2048 {
Err(VmRunError::RegOutOfBounds)
} else {
Ok(())
}
}
/// Virtual machine halt error /// Virtual machine halt error
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)] #[repr(u8)]
@ -407,6 +425,9 @@ pub enum VmRunError {
/// Unhandled store access exception /// Unhandled store access exception
StoreAccessEx(u64), StoreAccessEx(u64),
/// Register out-of-bounds access
RegOutOfBounds,
/// Reached unreachable code /// Reached unreachable code
Unreachable, Unreachable,
} }