diff --git a/acvm-repo/brillig_vm/src/arithmetic.rs b/acvm-repo/brillig_vm/src/arithmetic.rs index f5407521455..c9417faaff3 100644 --- a/acvm-repo/brillig_vm/src/arithmetic.rs +++ b/acvm-repo/brillig_vm/src/arithmetic.rs @@ -43,7 +43,13 @@ pub(crate) fn evaluate_binary_field_op( BinaryFieldOp::Add => MemoryValue::new_field(a + b), BinaryFieldOp::Sub => MemoryValue::new_field(a - b), BinaryFieldOp::Mul => MemoryValue::new_field(a * b), - BinaryFieldOp::Div => MemoryValue::new_field(a / b), + BinaryFieldOp::Div => { + if b.is_zero() { + return Err(BrilligArithmeticError::DivisionByZero); + } else { + MemoryValue::new_field(a / b) + } + } BinaryFieldOp::IntegerDiv => { if b.is_zero() { return Err(BrilligArithmeticError::DivisionByZero); diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 578cc15010c..27759012335 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -2406,4 +2406,45 @@ mod tests { assert_eq!(output_value.to_field(), FieldElement::from(1u128)); } + + #[test] + fn field_zero_division_regression() { + let calldata: Vec = vec![]; + + let opcodes = &[ + Opcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Field, + value: FieldElement::from(1u64), + }, + Opcode::Const { + destination: MemoryAddress::direct(1), + bit_size: BitSize::Field, + value: FieldElement::from(0u64), + }, + Opcode::BinaryFieldOp { + destination: MemoryAddress::direct(2), + op: BinaryFieldOp::Div, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + }, + ]; + let solver = StubbedBlackBoxSolver::default(); + let mut vm = VM::new(calldata, opcodes, &solver, false); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!( + status, + VMStatus::Failure { + reason: FailureReason::RuntimeError { + message: "Attempted to divide by zero".into() + }, + call_stack: vec![2] + } + ); + } }