diff --git a/crates/vm/levm/src/opcode_handlers/environment.rs b/crates/vm/levm/src/opcode_handlers/environment.rs index 7e1d90d34..0edce6a62 100644 --- a/crates/vm/levm/src/opcode_handlers/environment.rs +++ b/crates/vm/levm/src/opcode_handlers/environment.rs @@ -324,9 +324,13 @@ impl VM { let bytecode = self.get_account(&address).info.bytecode; - let new_memory_size = dest_offset.checked_add(size).ok_or(VMError::Internal( + let new_memory_size = (((!size).checked_add(1).ok_or(VMError::Internal( InternalError::ArithmeticOperationOverflow, - ))?; + ))?) & 31) + .checked_add(size) + .ok_or(VMError::Internal( + InternalError::ArithmeticOperationOverflow, + ))?; let current_memory_size = current_call_frame.memory.data.len(); if current_memory_size < new_memory_size { current_call_frame.memory.data.resize(new_memory_size, 0); diff --git a/crates/vm/levm/tests/edge_case_tests.rs b/crates/vm/levm/tests/edge_case_tests.rs index 2ae94e7eb..33845f3bd 100644 --- a/crates/vm/levm/tests/edge_case_tests.rs +++ b/crates/vm/levm/tests/edge_case_tests.rs @@ -132,3 +132,14 @@ fn test_non_compliance_extcodecopy() { vm.execute(&mut current_call_frame); assert_eq!(current_call_frame.stack.stack.pop().unwrap(), U256::zero()); } + +#[test] +fn test_non_compliance_extcodecopy_memory_resize() { + let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[ + 0x60, 12, 0x5f, 0x5f, 0x5f, 0x3c, 89, + ])) + .unwrap(); + let mut current_call_frame = vm.call_frames.pop().unwrap(); + vm.execute(&mut current_call_frame); + assert_eq!(current_call_frame.stack.pop().unwrap(), U256::from(32)); +}