Skip to content

Commit

Permalink
fix: detect circular external nodes (#1464)
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbinth authored Aug 21, 2024
1 parent 8bf7503 commit e683be9
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#### Fixes

- Fixed an issue with registering non-local procedures in `MemMastForestStore` (#1462).
- Added a check for circular external node lookups in the processor (#1464).

## 0.10.4 (2024-08-15) - `miden-processor` crate only

Expand Down
4 changes: 4 additions & 0 deletions processor/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum ExecutionError {
AdviceMapKeyNotFound(Word),
AdviceStackReadFailed(RowIndex),
CallerNotInSyscall,
CircularExternalNode(Digest),
CycleLimitExceeded(u32),
DivideByZero(RowIndex),
DynamicNodeNotFound(Digest),
Expand Down Expand Up @@ -91,6 +92,9 @@ impl Display for ExecutionError {
CallerNotInSyscall => {
write!(f, "Instruction `caller` used outside of kernel context")
},
CircularExternalNode(mast_root) => {
write!(f, "External node with root {mast_root} resolved to an external node")
},
CycleLimitExceeded(max_cycles) => {
write!(f, "Exceeded the allowed number of cycles (max cycles = {max_cycles})")
},
Expand Down
24 changes: 14 additions & 10 deletions processor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,21 +277,25 @@ where
MastNode::Call(node) => self.execute_call_node(node, program),
MastNode::Dyn => self.execute_dyn_node(program),
MastNode::External(external_node) => {
let mast_forest =
self.host.borrow().get_mast_forest(&external_node.digest()).ok_or_else(
|| ExecutionError::MastForestNotFound {
root_digest: external_node.digest(),
},
)?;
let node_digest = external_node.digest();
let mast_forest = self
.host
.borrow()
.get_mast_forest(&node_digest)
.ok_or(ExecutionError::MastForestNotFound { root_digest: node_digest })?;

// We limit the parts of the program that can be called externally to procedure
// roots, even though MAST doesn't have that restriction.
let root_id = mast_forest.find_procedure_root(external_node.digest()).ok_or(
ExecutionError::MalformedMastForestInHost {
root_digest: external_node.digest(),
},
let root_id = mast_forest.find_procedure_root(node_digest).ok_or(
ExecutionError::MalformedMastForestInHost { root_digest: node_digest },
)?;

// if the node that we got by looking up an external reference is also an External
// node, we are about to enter into an infinite loop - so, return an error
if mast_forest[root_id].is_external() {
return Err(ExecutionError::CircularExternalNode(node_digest));
}

self.execute_mast_node(root_id, &mast_forest)
},
}
Expand Down

0 comments on commit e683be9

Please sign in to comment.