Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SECURITY] Attempt to subtract with overflow in SWAP opcode #1146

Open
pventuzelo opened this issue Nov 12, 2024 · 0 comments
Open

[SECURITY] Attempt to subtract with overflow in SWAP opcode #1146

pventuzelo opened this issue Nov 12, 2024 · 0 comments

Comments

@pventuzelo
Copy link

Our team (@FuzzingLabs) discovered a bug was identified in the op_swap function, we can trigger an overflow due to the lack of checks.

Root cause

pub fn op_swap(
        &mut self,
        current_call_frame: &mut CallFrame,
        op: Opcode,
    ) -> Result<OpcodeSuccess, VMError> {
        self.increase_consumed_gas(current_call_frame, gas_cost::SWAPN)?;

        let depth = (op as u8) - (Opcode::SWAP1 as u8) + 1;

        if current_call_frame.stack.len() < depth as usize {
            return Err(VMError::StackUnderflow);
        }
        let stack_top_index = current_call_frame.stack.len();
        let to_swap_index = stack_top_index
            .checked_sub(depth as usize)
            .ok_or(VMError::StackUnderflow)?;
        current_call_frame
            .stack
            .swap(stack_top_index - 1, to_swap_index - 1);

        Ok(OpcodeSuccess::Continue)
    }

stack_top_index - 1 we trigger an underflow because there is no check if stack_top_index ≠ 0.

Step to reproduce

Payload

[48, 144]

ADDRESS
SWAP1

Add to [test](https://github.com/lambdaclass/lambda_ethereum_rust/blob/main/crates/vm/levm/tests/tests.rs) :

#[test]
fn test_overflow_swap() {
    let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[48, 144]));
    let mut current_call_frame = vm.call_frames.pop().unwrap();
    vm.execute(&mut current_call_frame);
}

Backtrace

---- tests::test_overflow_swap stdout ----
thread 'tests::test_overflow_swap' panicked at crates/vm/levm/src/opcode_handlers/exchange.rs:32:40:
attempt to subtract 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_sub_overflow
             at /rustc/59e2c01c2217a01546222e4d9ff4e6695ee8a1db/library/core/src/panicking.rs:181:21
   3: ethereum_rust_levm::opcode_handlers::exchange::<impl ethereum_rust_levm::vm::VM>::op_swap
             at ./src/opcode_handlers/exchange.rs:32:40
   4: ethereum_rust_levm::vm::VM::execute
             at ./src/vm.rs:207:21
   5: lib::tests::test_overflow_swap
             at ./tests/tests.rs:82:5
   6: lib::tests::test_overflow_swap::{{closure}}
             at ./tests/tests.rs:79:24
   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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

1 participant