diff --git a/crates/evm/fuzz/src/strategies/mutators.rs b/crates/evm/fuzz/src/strategies/mutators.rs index fffb329a0bffb..db944dedb9a95 100644 --- a/crates/evm/fuzz/src/strategies/mutators.rs +++ b/crates/evm/fuzz/src/strategies/mutators.rs @@ -525,7 +525,7 @@ fn validate_uint_mutation(original: U256, mutated: U256, size: usize) -> Option< // Check if mutated value fits the given size. let max = if size < 256 { (U256::from(1) << size) - U256::from(1) } else { U256::MAX }; - (mutated < max).then_some(mutated) + (mutated <= max).then_some(mutated) } /// Returns mutated int value if different from the original value and if it fits in the given size, @@ -550,6 +550,22 @@ mod tests { use super::*; use proptest::test_runner::Config; + #[test] + fn validate_uint_mutation_accepts_inclusive_max() { + // For width `size`, valid unsigned values are 0..=max where max = 2^size - 1. + // Regression: `< max` incorrectly rejected `mutated == max`; must use `<= max`. + for size in [8usize, 16, 32, 64, 128] { + let max = (U256::from(1) << size) - U256::from(1); + assert_eq!( + super::validate_uint_mutation(U256::ZERO, max, size), + Some(max), + "size={size}" + ); + } + let original = U256::from(1); + assert_eq!(super::validate_uint_mutation(original, U256::MAX, 256), Some(U256::MAX)); + } + #[test] fn test_mutate_uint() { let mut runner = TestRunner::new(Config::default());