Fixed few overflows
This commit is contained in:
parent
bdda987da9
commit
83436507df
|
@ -230,27 +230,26 @@ 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: u8 = match dst {
|
||||||
|
|
||||||
let n: usize = match dst {
|
|
||||||
0 => 1,
|
0 => 1,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.memory.load(
|
self.memory.load(
|
||||||
self.read_reg(base).cast::<u64>() + off + n as u64,
|
self.ldst_addr_uber(dst, base, off, count, n)?,
|
||||||
self.registers.as_mut_ptr().add(usize::from(dst) + n).cast(),
|
self.registers
|
||||||
usize::from(count).saturating_sub(n),
|
.as_mut_ptr()
|
||||||
|
.add(usize::from(dst) + usize::from(n))
|
||||||
|
.cast(),
|
||||||
|
usize::from(count).saturating_sub(n.into()),
|
||||||
&mut self.pfhandler,
|
&mut self.pfhandler,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
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.ldst_addr_uber(dst, base, off, count, 0)?,
|
||||||
self.registers.as_ptr().add(usize::from(dst)).cast(),
|
self.registers.as_ptr().add(usize::from(dst)).cast(),
|
||||||
count.into(),
|
count.into(),
|
||||||
&mut self.pfhandler,
|
&mut self.pfhandler,
|
||||||
|
@ -312,7 +311,8 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
// specified register and jump to reg + offset.
|
// specified register and jump to reg + offset.
|
||||||
let ParamBBD(save, reg, offset) = self.decode();
|
let ParamBBD(save, reg, offset) = self.decode();
|
||||||
self.write_reg(save, self.pc as u64);
|
self.write_reg(save, self.pc as u64);
|
||||||
self.pc = (self.read_reg(reg).cast::<u64>() + offset) as usize;
|
self.pc =
|
||||||
|
(self.read_reg(reg).cast::<u64>().saturating_add(offset)) as usize;
|
||||||
}
|
}
|
||||||
// Conditional jumps, jump only to immediates
|
// Conditional jumps, jump only to immediates
|
||||||
JEQ => self.cond_jmp::<u64>(Ordering::Equal),
|
JEQ => self.cond_jmp::<u64>(Ordering::Equal),
|
||||||
|
@ -443,15 +443,28 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
*self.registers.get_unchecked_mut(n as usize) = value.into();
|
*self.registers.get_unchecked_mut(n as usize) = value.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Load/Store target/source register range bound checking
|
/// Load / Store Address check-computation überfunction
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ldst_bound_check(reg: u8, size: u16) -> Result<(), VmRunError> {
|
unsafe fn ldst_addr_uber(
|
||||||
if usize::from(reg) * 8 + usize::from(size) > 2048 {
|
&self,
|
||||||
Err(VmRunError::RegOutOfBounds)
|
dst: u8,
|
||||||
} else {
|
base: u8,
|
||||||
Ok(())
|
offset: u64,
|
||||||
|
size: u16,
|
||||||
|
adder: u8,
|
||||||
|
) -> Result<u64, VmRunError> {
|
||||||
|
let reg = dst.checked_add(adder).ok_or(VmRunError::RegOutOfBounds)?;
|
||||||
|
|
||||||
|
if usize::from(reg) * 8 + usize::from(size) > 2048 {
|
||||||
|
Err(VmRunError::RegOutOfBounds)
|
||||||
|
} else {
|
||||||
|
self.read_reg(base)
|
||||||
|
.cast::<u64>()
|
||||||
|
.checked_add(offset)
|
||||||
|
.and_then(|x| x.checked_add(adder.into()))
|
||||||
|
.ok_or(VmRunError::AddrOutOfBounds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,6 +484,9 @@ pub enum VmRunError {
|
||||||
/// Register out-of-bounds access
|
/// Register out-of-bounds access
|
||||||
RegOutOfBounds,
|
RegOutOfBounds,
|
||||||
|
|
||||||
|
/// Address out-of-bounds
|
||||||
|
AddrOutOfBounds,
|
||||||
|
|
||||||
/// Reached unreachable code
|
/// Reached unreachable code
|
||||||
Unreachable,
|
Unreachable,
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl BlockCopier {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy one block
|
/// Copy one block
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// - Same as for [`Memory::load`] and [`Memory::store`]
|
/// - Same as for [`Memory::load`] and [`Memory::store`]
|
||||||
pub unsafe fn poll(
|
pub unsafe fn poll(
|
||||||
|
@ -59,8 +59,16 @@ impl BlockCopier {
|
||||||
return Poll::Ready(Err(e));
|
return Poll::Ready(Err(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.src += BUF_SIZE as u64;
|
match self.src.checked_add(BUF_SIZE as u64) {
|
||||||
self.dst += BUF_SIZE as u64;
|
Some(n) => self.src = n,
|
||||||
|
None => return Poll::Ready(Err(BlkCopyError::OutOfBounds)),
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.dst.checked_add(BUF_SIZE as u64) {
|
||||||
|
Some(n) => self.dst = n,
|
||||||
|
None => return Poll::Ready(Err(BlkCopyError::OutOfBounds)),
|
||||||
|
};
|
||||||
|
|
||||||
self.n_buffers -= 1;
|
self.n_buffers -= 1;
|
||||||
|
|
||||||
return if self.n_buffers + self.rem == 0 {
|
return if self.n_buffers + self.rem == 0 {
|
||||||
|
@ -109,7 +117,7 @@ unsafe fn act(
|
||||||
|src, dst, count| core::ptr::copy(src, dst, count),
|
|src, dst, count| core::ptr::copy(src, dst, count),
|
||||||
traph,
|
traph,
|
||||||
)
|
)
|
||||||
.map_err(|addr| BlkCopyError {
|
.map_err(|addr| BlkCopyError::Access {
|
||||||
access_reason: MemoryAccessReason::Load,
|
access_reason: MemoryAccessReason::Load,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
|
@ -125,7 +133,7 @@ unsafe fn act(
|
||||||
|dst, src, count| core::ptr::copy(src, dst, count),
|
|dst, src, count| core::ptr::copy(src, dst, count),
|
||||||
traph,
|
traph,
|
||||||
)
|
)
|
||||||
.map_err(|addr| BlkCopyError {
|
.map_err(|addr| BlkCopyError::Access {
|
||||||
access_reason: MemoryAccessReason::Store,
|
access_reason: MemoryAccessReason::Store,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
|
@ -135,18 +143,30 @@ unsafe fn act(
|
||||||
|
|
||||||
/// Error occured when copying a block of memory
|
/// Error occured when copying a block of memory
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct BlkCopyError {
|
pub enum BlkCopyError {
|
||||||
/// Kind of access
|
/// Memory access error
|
||||||
access_reason: MemoryAccessReason,
|
Access {
|
||||||
/// VM Address
|
/// Kind of access
|
||||||
addr: u64,
|
access_reason: MemoryAccessReason,
|
||||||
|
/// VM Address
|
||||||
|
addr: u64,
|
||||||
|
},
|
||||||
|
/// Address out of bounds
|
||||||
|
OutOfBounds,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BlkCopyError> for VmRunError {
|
impl From<BlkCopyError> for VmRunError {
|
||||||
fn from(value: BlkCopyError) -> Self {
|
fn from(value: BlkCopyError) -> Self {
|
||||||
match value.access_reason {
|
match value {
|
||||||
MemoryAccessReason::Load => Self::LoadAccessEx(value.addr),
|
BlkCopyError::Access {
|
||||||
MemoryAccessReason::Store => Self::StoreAccessEx(value.addr),
|
access_reason: MemoryAccessReason::Load,
|
||||||
|
addr,
|
||||||
|
} => Self::LoadAccessEx(addr),
|
||||||
|
BlkCopyError::Access {
|
||||||
|
access_reason: MemoryAccessReason::Store,
|
||||||
|
addr,
|
||||||
|
} => Self::StoreAccessEx(addr),
|
||||||
|
BlkCopyError::OutOfBounds => Self::AddrOutOfBounds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue