Added runtime bound checking

This commit is contained in:
Erin 2023-07-26 00:01:25 +02:00
parent 0f5d78bb27
commit 5055626968
2 changed files with 25 additions and 2 deletions

View file

@ -59,14 +59,16 @@ macro_rules! gen_valider {
let start = program;
loop {
use crate::opcode::*;
extern crate std;
program = match program {
// End of program
[] => return Ok(()),
// 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
+ usize::from(u16::from_le_bytes([*count_1, *count_0]))
+ usize::from(u16::from_le_bytes([*count_0, *count_1]))
> 2048 =>
{
return Err(Error {

View file

@ -215,6 +215,8 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
LD => {
// Load. If loading more than register size, continue on adjecent registers
let ParamBBDH(dst, base, off, count) = self.decode();
ldst_bound_check(dst, count)?;
let n: usize = match dst {
0 => 1,
_ => 0,
@ -230,6 +232,8 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
ST => {
// Store. Same rules apply as to LD
let ParamBBDH(dst, base, off, count) = self.decode();
ldst_bound_check(dst, count)?;
self.memory.store(
self.read_reg(base).cast::<u64>() + off,
self.registers.as_ptr().add(usize::from(dst)).cast(),
@ -250,6 +254,10 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
BRC => {
// Block register copy
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(
self.registers.get_unchecked(usize::from(src)),
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
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
@ -407,6 +425,9 @@ pub enum VmRunError {
/// Unhandled store access exception
StoreAccessEx(u64),
/// Register out-of-bounds access
RegOutOfBounds,
/// Reached unreachable code
Unreachable,
}