diff --git a/compiler-lib/src/bc_reader.rs b/compiler-lib/src/bc_reader.rs index 6661dd01..c9843657 100644 --- a/compiler-lib/src/bc_reader.rs +++ b/compiler-lib/src/bc_reader.rs @@ -6,19 +6,36 @@ pub struct BytecodeReader { idx: usize, } -impl From<&[u8]> for BytecodeReader { - fn from(value: &[u8]) -> Self { - Self { - data: value.to_vec(), - idx: 0, +impl TryFrom<&[u8]> for BytecodeReader { + type Error = DecodeError; + + fn try_from(value: &[u8]) -> Result { + if value.len() > u16::MAX as usize { + Err(DecodeError::DataTooLarge) + } else { + Ok(Self { + data: value.to_vec(), + idx: 0, + }) } } } +#[derive(Clone, thiserror::Error, PartialEq, Eq, Debug)] pub enum DecodeError { + #[error("bytecode exceeds maximum allowed size")] + DataTooLarge, + + #[error("reached end of stream")] EndOfStream, + + #[error("insufficient data for decoding")] InsufficientData, + + #[error("{0} is not a known opcode")] UnknownOpcode(u8), + + #[error("{1} is not a valid operand for opcode {0}")] UnknownOperand(u8, u8), } diff --git a/compiler-lib/src/dump/mod.rs b/compiler-lib/src/dump/mod.rs index c467e9d8..30576e2b 100644 --- a/compiler-lib/src/dump/mod.rs +++ b/compiler-lib/src/dump/mod.rs @@ -50,7 +50,12 @@ impl ModuleDump for CompiledCodeObject { << self.frame_size << ") bc=\n"; - let mut bcr = BytecodeReader::from(self.body.as_slice()); + let mut bcr = match BytecodeReader::try_from(self.body.as_slice()) { + Ok(bcr) => bcr, + Err(e) => { + return dest << " \n"; + } + }; let mut op_idx = 0; loop { let idx_str = format!(" {op_idx:05}: "); diff --git a/vm-lib/src/error/vm_error.rs b/vm-lib/src/error/vm_error.rs index 2f6ca3b5..c28d76d9 100644 --- a/vm-lib/src/error/vm_error.rs +++ b/vm-lib/src/error/vm_error.rs @@ -78,6 +78,9 @@ pub enum VmErrorReason { #[error("{1} is not a valid operand for opcode {0}")] InvalidVmOperand(u8, u8), + #[error("bytecode exceeds maximum allowed size")] + BytecodeTooLarge, + #[error("VM execution halted")] VmHalted, } @@ -85,6 +88,7 @@ pub enum VmErrorReason { impl From for VmErrorReason { fn from(value: DecodeError) -> Self { match value { + DecodeError::DataTooLarge => VmErrorReason::BytecodeTooLarge, DecodeError::EndOfStream => VmErrorReason::UnterminatedBytecode, DecodeError::InsufficientData => VmErrorReason::IncompleteInstruction, DecodeError::UnknownOpcode(n) => VmErrorReason::UnknownOpcode(n), diff --git a/vm-lib/src/runtime_value/runtime_code_object.rs b/vm-lib/src/runtime_value/runtime_code_object.rs index 02456412..629a5812 100644 --- a/vm-lib/src/runtime_value/runtime_code_object.rs +++ b/vm-lib/src/runtime_value/runtime_code_object.rs @@ -28,7 +28,7 @@ impl PartialEq for CodeObject { fn byte_array_to_opcode_array(bytes: &[u8]) -> DecodeResult> { let mut opcodes = Vec::new(); - let mut decoder = BytecodeReader::from(bytes); + let mut decoder = BytecodeReader::try_from(bytes)?; loop { let next = decoder.read_opcode();