mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
chore: Harden RVM implementation (#537)
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
d626f75421
commit
740db8a0f5
+242
-66
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
use super::execution_model::SuspendReason;
|
||||
use crate::value::Value;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
@@ -9,112 +10,287 @@ use thiserror::Error;
|
||||
/// VM execution errors
|
||||
#[derive(Error, Debug, Clone, PartialEq)]
|
||||
pub enum VmError {
|
||||
#[error("Execution stopped: exceeded maximum instruction limit of {limit}")]
|
||||
InstructionLimitExceeded { limit: usize },
|
||||
#[error("Execution stopped: exceeded maximum instruction limit of {limit} after {executed} instructions (pc={pc})")]
|
||||
InstructionLimitExceeded {
|
||||
limit: usize,
|
||||
executed: usize,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Literal index {index} out of bounds")]
|
||||
LiteralIndexOutOfBounds { index: usize },
|
||||
#[error("Literal index {index} out of bounds (pc={pc})")]
|
||||
LiteralIndexOutOfBounds { index: u16, pc: usize },
|
||||
|
||||
#[error("Register {register} does not contain an object")]
|
||||
RegisterNotObject { register: u8 },
|
||||
#[error("Register {register} does not contain an object (value={value:?}, pc={pc})")]
|
||||
RegisterNotObject {
|
||||
register: u8,
|
||||
value: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("ObjectCreate: template is not an object")]
|
||||
ObjectCreateInvalidTemplate,
|
||||
#[error("ObjectCreate: template is not an object (pc={pc}, template={template:?})")]
|
||||
ObjectCreateInvalidTemplate { template: Value, pc: usize },
|
||||
|
||||
#[error("Register {register} does not contain an array")]
|
||||
RegisterNotArray { register: u8 },
|
||||
#[error("Register {register} does not contain an array (value={value:?}, pc={pc})")]
|
||||
RegisterNotArray {
|
||||
register: u8,
|
||||
value: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Register {register} does not contain a set")]
|
||||
RegisterNotSet { register: u8 },
|
||||
#[error("Register {register} does not contain a set (value={value:?}, pc={pc})")]
|
||||
RegisterNotSet {
|
||||
register: u8,
|
||||
value: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Rule index {index} out of bounds")]
|
||||
RuleIndexOutOfBounds { index: u16 },
|
||||
#[error("Register index {index} out of bounds (pc={pc}, register_count={register_count})")]
|
||||
RegisterIndexOutOfBounds {
|
||||
index: u8,
|
||||
pc: usize,
|
||||
register_count: usize,
|
||||
},
|
||||
|
||||
#[error("Rule index {index} has no info")]
|
||||
RuleInfoMissing { index: u16 },
|
||||
#[error("Rule index {index} out of bounds (pc={pc}, available={available})")]
|
||||
RuleIndexOutOfBounds {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid object create params index: {index}")]
|
||||
InvalidObjectCreateParams { index: u16 },
|
||||
#[error("Rule index {index} has no info (pc={pc}, available={available})")]
|
||||
RuleInfoMissing {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid template literal index: {index}")]
|
||||
InvalidTemplateLiteralIndex { index: u16 },
|
||||
#[error("Invalid object create params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidObjectCreateParams {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid chained index params index: {index}")]
|
||||
InvalidChainedIndexParams { index: u16 },
|
||||
#[error("Invalid template literal index: {index} (pc={pc}, available={available})")]
|
||||
InvalidTemplateLiteralIndex {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid array create params index: {index}")]
|
||||
InvalidArrayCreateParams { index: u16 },
|
||||
#[error("Invalid chained index params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidChainedIndexParams {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid set create params index: {index}")]
|
||||
InvalidSetCreateParams { index: u16 },
|
||||
#[error("Invalid array create params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidArrayCreateParams {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid virtual data document lookup params index: {index}")]
|
||||
InvalidVirtualDataDocumentLookupParams { index: u16 },
|
||||
#[error("Invalid set create params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidSetCreateParams {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid comprehension start params index: {index}")]
|
||||
InvalidComprehensionBeginParams { index: u16 },
|
||||
#[error("Invalid virtual data document lookup params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidVirtualDataDocumentLookupParams {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid rule index: {rule_index:?}")]
|
||||
InvalidRuleIndex { rule_index: Value },
|
||||
#[error("Invalid comprehension start params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidComprehensionBeginParams {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid rule tree entry: {value:?}")]
|
||||
InvalidRuleTreeEntry { value: Value },
|
||||
#[error("Invalid loop params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidLoopParams {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Builtin function expects exactly {expected} arguments, got {actual}")]
|
||||
BuiltinArgumentMismatch { expected: u16, actual: usize },
|
||||
#[error("Invalid rule index: {rule_index:?} (pc={pc})")]
|
||||
InvalidRuleIndex { rule_index: Value, pc: usize },
|
||||
|
||||
#[error("Builtin function not resolved: {name}")]
|
||||
BuiltinNotResolved { name: String },
|
||||
#[error("Invalid rule tree entry: {value:?} (pc={pc})")]
|
||||
InvalidRuleTreeEntry { value: Value, pc: usize },
|
||||
|
||||
#[error("Cannot add {left:?} and {right:?}")]
|
||||
InvalidAddition { left: Value, right: Value },
|
||||
#[error("Builtin function expects exactly {expected} arguments, got {actual} (pc={pc})")]
|
||||
BuiltinArgumentMismatch {
|
||||
expected: u16,
|
||||
actual: usize,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Cannot subtract {left:?} and {right:?}")]
|
||||
InvalidSubtraction { left: Value, right: Value },
|
||||
#[error("Builtin function not resolved: {name} (pc={pc})")]
|
||||
BuiltinNotResolved { name: String, pc: usize },
|
||||
|
||||
#[error("Cannot multiply {left:?} and {right:?}")]
|
||||
InvalidMultiplication { left: Value, right: Value },
|
||||
#[error("Cannot add {left:?} and {right:?} (pc={pc})")]
|
||||
InvalidAddition {
|
||||
left: Value,
|
||||
right: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Cannot divide {left:?} and {right:?}")]
|
||||
InvalidDivision { left: Value, right: Value },
|
||||
#[error("Cannot subtract {left:?} and {right:?} (pc={pc})")]
|
||||
InvalidSubtraction {
|
||||
left: Value,
|
||||
right: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("modulo on floating-point number")]
|
||||
ModuloOnFloat,
|
||||
#[error("Cannot multiply {left:?} and {right:?} (pc={pc})")]
|
||||
InvalidMultiplication {
|
||||
left: Value,
|
||||
right: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Cannot modulo {left:?} and {right:?}")]
|
||||
InvalidModulo { left: Value, right: Value },
|
||||
#[error("Cannot divide {left:?} and {right:?} (pc={pc})")]
|
||||
InvalidDivision {
|
||||
left: Value,
|
||||
right: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Cannot iterate over {value:?}")]
|
||||
InvalidIteration { value: Value },
|
||||
#[error("modulo on floating-point number (left={left:?}, right={right:?}, pc={pc})")]
|
||||
ModuloOnFloat {
|
||||
left: Value,
|
||||
right: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("HostAwait executed but no response provided for destination register {dest} (id: {identifier:?})")]
|
||||
HostAwaitResponseMissing { dest: u8, identifier: Value },
|
||||
#[error("Cannot modulo {left:?} and {right:?} (pc={pc})")]
|
||||
InvalidModulo {
|
||||
left: Value,
|
||||
right: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Assertion failed")]
|
||||
AssertionFailed,
|
||||
#[error("Cannot iterate over {value:?} (pc={pc})")]
|
||||
InvalidIteration { value: Value, pc: usize },
|
||||
|
||||
#[error("Rule-data conflict: {0}")]
|
||||
RuleDataConflict(String),
|
||||
#[error("HostAwait executed but no response provided for destination register {dest} (id: {identifier:?}, pc={pc})")]
|
||||
HostAwaitResponseMissing {
|
||||
dest: u8,
|
||||
identifier: Value,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Arithmetic error: {0}")]
|
||||
ArithmeticError(String),
|
||||
#[error("Assertion failed (pc={pc})")]
|
||||
AssertionFailed { pc: usize },
|
||||
|
||||
#[error("Entry point index {index} out of bounds (max: {max_index})")]
|
||||
InvalidEntryPointIndex { index: usize, max_index: usize },
|
||||
#[error("Rule-data conflict: {message} (pc={pc})")]
|
||||
RuleDataConflict { message: String, pc: usize },
|
||||
|
||||
#[error("Entry point '{name}' not found. Available entry points: {available:?}")]
|
||||
#[error("Arithmetic error: {message} (pc={pc})")]
|
||||
ArithmeticError { message: String, pc: usize },
|
||||
|
||||
#[error("Entry point index {index} out of bounds (max: {max_index}, pc={pc})")]
|
||||
InvalidEntryPointIndex {
|
||||
index: usize,
|
||||
max_index: usize,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Entry point '{name}' not found (pc={pc}). Available entry points: {available:?}")]
|
||||
EntryPointNotFound {
|
||||
name: String,
|
||||
available: Vec<String>,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Internal VM error: {0}")]
|
||||
Internal(String),
|
||||
#[error("Entry point PC {pc} >= instruction count {instruction_count} for entry point '{entry_point}'")]
|
||||
EntryPointPcOutOfBounds {
|
||||
pc: usize,
|
||||
instruction_count: usize,
|
||||
entry_point: String,
|
||||
},
|
||||
|
||||
#[error("Register count {register_count} below base count {base_count} (pc={pc})")]
|
||||
RegisterCountBelowBase {
|
||||
register_count: usize,
|
||||
base_count: usize,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Program counter {pc} out of bounds for instruction count {instruction_count}")]
|
||||
ProgramCounterOutOfBounds { pc: usize, instruction_count: usize },
|
||||
|
||||
#[error("Rule cache size {cache_size} != rule info count {rule_info_count} (pc={pc})")]
|
||||
RuleCacheSizeMismatch {
|
||||
cache_size: usize,
|
||||
rule_info_count: usize,
|
||||
pc: usize,
|
||||
},
|
||||
|
||||
#[error("Suspend reason {reason:?} is not supported in run-to-completion execution (pc={pc})")]
|
||||
UnsupportedSuspendInRunToCompletion { reason: SuspendReason, pc: usize },
|
||||
|
||||
#[error("Cannot resume VM when execution state is {state} (pc={pc})")]
|
||||
InvalidResumeState { state: String, pc: usize },
|
||||
|
||||
#[error("HostAwait suspension requires a resume value for reason {reason:?} (pc={pc})")]
|
||||
MissingResumeValue { reason: SuspendReason, pc: usize },
|
||||
|
||||
#[error("Unexpected resume value supplied for reason {reason:?} (pc={pc})")]
|
||||
UnexpectedResumeValue { reason: SuspendReason, pc: usize },
|
||||
|
||||
#[error("Missing execution frame: {context} (pc={pc})")]
|
||||
MissingExecutionFrame { context: &'static str, pc: usize },
|
||||
|
||||
#[error("Unhandled instruction variant: {instruction} (pc={pc})")]
|
||||
UnhandledInstruction { instruction: String, pc: usize },
|
||||
|
||||
#[error("Invalid function call params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidFunctionCallParamsIndex {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid builtin call params index: {index} (pc={pc}, available={available})")]
|
||||
InvalidBuiltinCallParamsIndex {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Invalid builtin info index: {index} (pc={pc}, available={available})")]
|
||||
InvalidBuiltinInfoIndex {
|
||||
index: u16,
|
||||
pc: usize,
|
||||
available: usize,
|
||||
},
|
||||
|
||||
#[error("Rule frame has no initial PC (pc={pc})")]
|
||||
RuleFrameMissingInitialPc { pc: usize },
|
||||
|
||||
#[error("Call rule stack underflow during rule finalization (pc={pc})")]
|
||||
CallRuleStackUnderflow { pc: usize },
|
||||
|
||||
#[error("Internal VM error: {message} (pc={pc})")]
|
||||
Internal { message: String, pc: usize },
|
||||
}
|
||||
|
||||
impl From<anyhow::Error> for VmError {
|
||||
fn from(err: anyhow::Error) -> Self {
|
||||
VmError::ArithmeticError(alloc::format!("{}", err))
|
||||
VmError::ArithmeticError {
|
||||
message: alloc::format!("{}", err),
|
||||
pc: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user