Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions compiler-lib/src/bc_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self, Self::Error> {
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),
}

Expand Down
7 changes: 6 additions & 1 deletion compiler-lib/src/dump/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 << " <invalid bytecode: " << e.to_string() << ">\n";
}
};
let mut op_idx = 0;
loop {
let idx_str = format!(" {op_idx:05}: ");
Expand Down
4 changes: 4 additions & 0 deletions vm-lib/src/error/vm_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,17 @@ 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,
}

impl From<DecodeError> 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),
Expand Down
2 changes: 1 addition & 1 deletion vm-lib/src/runtime_value/runtime_code_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl PartialEq for CodeObject {

fn byte_array_to_opcode_array(bytes: &[u8]) -> DecodeResult<Vec<Opcode>> {
let mut opcodes = Vec::new();
let mut decoder = BytecodeReader::from(bytes);
let mut decoder = BytecodeReader::try_from(bytes)?;

loop {
let next = decoder.read_opcode();
Expand Down