diff --git a/CHANGELOG.md b/CHANGELOG.md index 86d6fb4064..8c30a95b2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* fix: Handle error in hint `UINT256_MUL_DIV_MOD` when divides by zero [#1367](https://github.com/lambdaclass/cairo-vm/pull/1367) + * Add HintError::SyscallError and VmErrors::HINT_ERROR_STR constant [#1357](https://github.com/lambdaclass/cairo-rs/pull/1357) * feat: make *arbitrary* feature also enable a `proptest::arbitrary::Arbitrary` implementation for `Felt252` [#1355](https://github.com/lambdaclass/cairo-vm/pull/1355) diff --git a/cairo_programs/bad_programs/div_by_zero.cairo b/cairo_programs/bad_programs/div_by_zero.cairo new file mode 100644 index 0000000000..6f844cd981 --- /dev/null +++ b/cairo_programs/bad_programs/div_by_zero.cairo @@ -0,0 +1,31 @@ +struct MyStruct0 { + low: felt, + high: felt, +} +func main() { + let a = MyStruct0(low=0, high=0); + let b = MyStruct0(low=0, high=0); + let div = MyStruct0(low=0, high=0); + hint_func(a, b, div); + return(); +} +func hint_func(a: MyStruct0, b: MyStruct0, div: MyStruct0) -> (MyStruct0, MyStruct0, MyStruct0) { + alloc_locals; + local quotient_low: MyStruct0; + local quotient_high: MyStruct0; + local remainder: MyStruct0; + %{ + a = (ids.a.high << 128) + ids.a.low + b = (ids.b.high << 128) + ids.b.low + div = (ids.div.high << 128) + ids.div.low + quotient, remainder = divmod(a * b, div) + + ids.quotient_low.low = quotient & ((1 << 128) - 1) + ids.quotient_low.high = (quotient >> 128) & ((1 << 128) - 1) + ids.quotient_high.low = (quotient >> 256) & ((1 << 128) - 1) + ids.quotient_high.high = quotient >> 384 + ids.remainder.low = remainder & ((1 << 128) - 1) + ids.remainder.high = remainder >> 128 + %} + return(quotient_low, quotient_high, remainder); +} diff --git a/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 52238bcc24..3f304ba6a4 100644 --- a/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -13,7 +13,7 @@ use crate::{ ops::{Shl, Shr}, prelude::*, }, - types::relocatable::Relocatable, + types::{errors::math_errors::MathError, relocatable::Relocatable}, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; use felt::Felt252; @@ -434,6 +434,9 @@ pub fn uint256_mul_div_mod( let a = a_high.to_biguint().shl(128_usize) + a_low.to_biguint(); let b = b_high.to_biguint().shl(128_usize) + b_low.to_biguint(); let div = div_high.to_biguint().shl(128_usize) + div_low.to_biguint(); + if div.is_zero() { + return Err(MathError::DividedByZero.into()); + } let (quotient, remainder) = (a * b).div_mod_floor(&div); // ids.quotient_low.low diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index baa95b9f90..cfff8f981d 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -640,6 +640,13 @@ fn error_msg_attr_struct() { let error_msg = "Error message: Cats cannot have more than nine lives: {cat} (Cannot evaluate ap-based or complex references: ['cat'])"; run_program_with_error(program_data.as_slice(), error_msg); } +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn error_msg_attr_div_by_zero() { + let program_data = include_bytes!("../../../cairo_programs/bad_programs/div_by_zero.json"); + let error_msg = "Got an exception while executing a hint: Attempted to divide by zero"; + run_program_with_error(program_data.as_slice(), error_msg); +} #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]