From 215f2ede2c9af3bbea9544cdc105f2199d30d362 Mon Sep 17 00:00:00 2001 From: Jan Ferdinand Sauer Date: Tue, 17 Oct 2023 11:28:17 +0200 Subject: [PATCH] fix: crash VM when executing `swap 0` --- triton-vm/src/error.rs | 16 ++++++++++++++++ triton-vm/src/vm.rs | 9 ++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/triton-vm/src/error.rs b/triton-vm/src/error.rs index ad30efdf3..ab9a792f0 100644 --- a/triton-vm/src/error.rs +++ b/triton-vm/src/error.rs @@ -17,6 +17,7 @@ pub enum InstructionError { JumpStackIsEmpty, AssertionFailed(usize, u32, BFieldElement), VectorAssertionFailed(usize, u32, OpStackElement, BFieldElement, BFieldElement), + SwapST0, InverseOfZero, DivisionByZero, LogarithmOfZero, @@ -43,6 +44,7 @@ impl Display for InstructionError { write!(f, "{rhs} == op_stack[{failing_index_rhs}]. ")?; write!(f, "ip: {ip}, clk: {clk}") } + SwapST0 => write!(f, "Cannot swap stack element 0 with itself"), InverseOfZero => write!(f, "0 does not have a multiplicative inverse"), DivisionByZero => write!(f, "Division by 0 is impossible"), LogarithmOfZero => write!(f, "The logarithm of 0 does not exist"), @@ -61,7 +63,11 @@ mod tests { use proptest::prelude::*; use proptest_arbitrary_interop::arb; + use crate::instruction::AnInstruction::*; + use crate::instruction::LabelledInstruction; + use crate::op_stack::OpStackElement::ST0; use crate::triton_program; + use crate::Program; use super::*; @@ -111,6 +117,16 @@ mod tests { program.run([].into(), [].into()).unwrap(); } + #[test] + #[should_panic(expected = "swap stack element 0")] + fn swap_st0() { + // The parser rejects this program. Therefore, construct it manually. + let swap_0 = LabelledInstruction::Instruction(Swap(ST0)); + let halt = LabelledInstruction::Instruction(Halt); + let program = Program::new(&[swap_0, halt]); + program.run([].into(), [].into()).unwrap(); + } + proptest! { #[test] fn assert_unequal_vec( diff --git a/triton-vm/src/vm.rs b/triton-vm/src/vm.rs index 1803c8b39..3acebb257 100644 --- a/triton-vm/src/vm.rs +++ b/triton-vm/src/vm.rs @@ -217,7 +217,7 @@ impl<'pgm> VMState<'pgm> { Push(field_element) => self.push(field_element), Divine => self.divine()?, Dup(stack_element) => self.dup(stack_element), - Swap(stack_element) => self.swap(stack_element), + Swap(stack_element) => self.swap(stack_element)?, Nop => self.nop(), Skiz => self.skiz()?, Call(address) => self.call(address), @@ -289,10 +289,13 @@ impl<'pgm> VMState<'pgm> { None } - fn swap(&mut self, stack_register: OpStackElement) -> Option { + fn swap(&mut self, stack_register: OpStackElement) -> Result> { + if stack_register == ST0 { + bail!(SwapST0); + } self.op_stack.swap_top_with(stack_register); self.instruction_pointer += 2; - None + Ok(None) } fn nop(&mut self) -> Option {