Open mhoste51 opened 11 hours ago
Here is the test :
#[test]
fn test_non_compliance_returndatacopy() {
let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[56, 56, 56, 56, 56, 56, 62, 56]))
.unwrap();
let mut current_call_frame = vm.call_frames.pop().unwrap();
let txreport = vm.execute(&mut current_call_frame);
match txreport.result{
Success => panic!("This should return an error"),
Revert(e) => {
assert_eq!(e, VMError::OutOfOffset)
}
}
}
thread 'test_non_compliance_returndatacopy' panicked at crates/vm/levm/tests/edge_case_tests.rs:15:21:
This should return an error
stack backtrace:
0: rust_begin_unwind
at /rustc/8adb4b30f40e6fbd21dc1ba26c3301c7eeb6de3c/library/std/src/panicking.rs:665:5
1: core::panicking::panic_fmt
at /rustc/8adb4b30f40e6fbd21dc1ba26c3301c7eeb6de3c/library/core/src/panicking.rs:76:14
2: edge_case_tests::test_non_compliance_returndatacopy
at ./tests/edge_case_tests.rs:15:21
3: edge_case_tests::test_non_compliance_returndatacopy::{{closure}}
at ./tests/edge_case_tests.rs:9:40
4: core::ops::function::FnOnce::call_once
at /home/mhoste/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
5: core::ops::function::FnOnce::call_once
at /rustc/8adb4b30f40e6fbd21dc1ba26c3301c7eeb6de3c/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
failures:
test_non_compliance_returndatacopy
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 12 filtered out; finished in 0.10s
Our team at FuzzingLabs discovered a non compliance in RETURNDATACOPY implementation. This implementation diverges from the expected behavior defined in the Ethereum Yellow Paper. Specifically, when the
returndata_offset
exceeds the length of thereturndata
, the implementation improperly allocates additional memory filled with zeros instead of returning anOut of Offset
error, as required by the specifications.Root cause
Here is the problematic section in the current implementation:
When
returndata_offset >= sub_return_data_len
(i.e., the offset is out of bounds), the implementation does not fail. Instead, it creates a vector of zeros with a size equal to the requested range:This behavior is non-compliant because:
RETURNDATACOPY
operation should terminate immediately upon detecting an invalid offset (OutOfOffset
).