You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Our team at FuzzingLabs discovered a bug in the op_keccak256 function, this bug can lead to a panic when calculating minimum_word_size.
Root cause
pub fn op_keccak256(
&mut self,
current_call_frame: &mut CallFrame,
) -> Result<OpcodeSuccess, VMError> {
let offset = current_call_frame
.stack
.pop()?
.try_into()
.unwrap_or(usize::MAX);
let size = current_call_frame
.stack
.pop()?
.try_into()
.unwrap_or(usize::MAX);
let minimum_word_size = (size + WORD_SIZE - 1) / WORD_SIZE;
let memory_expansion_cost = current_call_frame.memory.expansion_cost(
offset
.checked_add(size)
.ok_or(VMError::MemoryLoadOutOfBounds)?,
)?;
let gas_cost = gas_cost::KECCAK25_STATIC
+ gas_cost::KECCAK25_DYNAMIC_BASE * minimum_word_size
+ memory_expansion_cost;
self.increase_consumed_gas(current_call_frame, gas_cost)?;
let value_bytes = current_call_frame.memory.load_range(offset, size)?;
let mut hasher = Keccak256::new();
hasher.update(value_bytes);
let result = hasher.finalize();
current_call_frame
.stack
.push(U256::from_big_endian(&result))?;
Ok(OpcodeSuccess::Continue)
}
let minimum_word_size = (size + WORD_SIZE - 1) / WORD_SIZE; We can control size and give a value equal to usize::MAX. Since WORD_SIZE = 32, when we attempt to add usize::MAX + 32, we encounter an overflow because minimum_word_size is also a usize.
#[test]
fn test_overflow_keccak256() {
let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[51, 63, 61, 32]));
let mut current_call_frame = vm.call_frames.pop().unwrap();
vm.execute(&mut current_call_frame);
}
Backtrace
---- tests::test_overflow_keccak256 stdout ----
thread 'tests::test_overflow_keccak256' panicked at crates/vm/levm/./src/opcode_handlers/keccak.rs:29:34:
attempt to add with overflow
stack backtrace:
0: rust_begin_unwind
at /rustc/59e2c01c2217a01546222e4d9ff4e6695ee8a1db/library/std/src/panicking.rs:658:5
1: core::panicking::panic_fmt
at /rustc/59e2c01c2217a01546222e4d9ff4e6695ee8a1db/library/core/src/panicking.rs:74:14
2: core::panicking::panic_const::panic_const_add_overflow
at /rustc/59e2c01c2217a01546222e4d9ff4e6695ee8a1db/library/core/src/panicking.rs:181:21
3: ethereum_rust_levm::opcode_handlers::keccak::<impl ethereum_rust_levm::vm::VM>::op_keccak256
at ./src/opcode_handlers/keccak.rs:29:34
4: ethereum_rust_levm::vm::VM::execute
at ./src/vm.rs:170:38
5: lib::tests::test_overflow_keccak256
at ./tests/tests.rs:50:5
6: lib::tests::test_overflow_keccak256::{{closure}}
at ./tests/tests.rs:47:29
7: core::ops::function::FnOnce::call_once
at /rustc/59e2c01c2217a01546222e4d9ff4e6695ee8a1db/library/core/src/ops/function.rs:250:5
8: core::ops::function::FnOnce::call_once
at /rustc/59e2c01c2217a01546222e4d9ff4e6695ee8a1db/library/core/src/ops/function.rs:250:5
The text was updated successfully, but these errors were encountered:
Our team at FuzzingLabs discovered a bug in the op_keccak256 function, this bug can lead to a panic when calculating
minimum_word_size
.Root cause
let minimum_word_size = (size + WORD_SIZE - 1) / WORD_SIZE;
We can controlsize
and give a value equal tousize::MAX
. SinceWORD_SIZE = 32
, when we attempt to addusize::MAX + 32
, we encounter an overflow becauseminimum_word_size
is also ausize
.Step to reproduce
Payload
Add to test :
Backtrace
The text was updated successfully, but these errors were encountered: