Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Wasm: Test for reaching stack overflow #9042

Merged
merged 1 commit into from
Jul 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ethcore/res/wasm-tests
2 changes: 1 addition & 1 deletion ethcore/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ libc = "0.2"
pwasm-utils = "0.2.2"
vm = { path = "../vm" }
ethcore-logger = { path = "../../logger" }
wasmi = "0.2.1"
wasmi = "0.3.0"
90 changes: 65 additions & 25 deletions ethcore/wasm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ fn empty() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};

assert_eq!(gas_left, U256::from(98462));
assert_eq!(gas_left, U256::from(96_926));
}

// This test checks if the contract deserializes payload header properly.
Expand Down Expand Up @@ -138,7 +138,7 @@ fn logger() {
U256::from(1_000_000_000),
"Logger sets 0x04 key to the trasferred value"
);
assert_eq!(gas_left, U256::from(17_578));
assert_eq!(gas_left, U256::from(16_181));
}

// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
Expand Down Expand Up @@ -173,7 +173,7 @@ fn identity() {
sender,
"Idenity test contract does not return the sender passed"
);
assert_eq!(gas_left, U256::from(98_408));
assert_eq!(gas_left, U256::from(96_883));
}

// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
Expand Down Expand Up @@ -207,7 +207,7 @@ fn dispersion() {
result,
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
);
assert_eq!(gas_left, U256::from(94_013));
assert_eq!(gas_left, U256::from(92_371));
}

#[test]
Expand Down Expand Up @@ -235,7 +235,7 @@ fn suicide_not() {
result,
vec![0u8]
);
assert_eq!(gas_left, U256::from(94_984));
assert_eq!(gas_left, U256::from(93_378));
}

#[test]
Expand Down Expand Up @@ -267,7 +267,7 @@ fn suicide() {
};

assert!(ext.suicides.contains(&refund));
assert_eq!(gas_left, U256::from(94_925));
assert_eq!(gas_left, U256::from(93_348));
}

#[test]
Expand Down Expand Up @@ -297,15 +297,15 @@ fn create() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Create,
gas: U256::from(60_914),
gas: U256::from(59_269),
sender_address: None,
receive_address: None,
value: Some(1_000_000_000.into()),
data: vec![0u8, 2, 4, 8, 16, 32, 64, 128],
code_address: None,
}
));
assert_eq!(gas_left, U256::from(60_900));
assert_eq!(gas_left, U256::from(59_212));
}

#[test]
Expand Down Expand Up @@ -349,7 +349,7 @@ fn call_msg() {
}
));

assert_eq!(gas_left, U256::from(93_511));
assert_eq!(gas_left, U256::from(91_672));
}

#[test]
Expand Down Expand Up @@ -394,7 +394,7 @@ fn call_code() {
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614);
assert_eq!(gas_left, U256::from(92_381));
assert_eq!(gas_left, U256::from(90_038));
}

#[test]
Expand Down Expand Up @@ -442,7 +442,7 @@ fn call_static() {
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590);

assert_eq!(gas_left, U256::from(92_381));
assert_eq!(gas_left, U256::from(90_043));
}

// Realloc test
Expand All @@ -465,7 +465,7 @@ fn realloc() {
}
};
assert_eq!(result, vec![0u8; 2]);
assert_eq!(gas_left, U256::from(94_372));
assert_eq!(gas_left, U256::from(92_842));
}

#[test]
Expand All @@ -486,8 +486,8 @@ fn alloc() {
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, vec![5u8; 1024*450]);
assert_eq!(gas_left, U256::from(6_506_844));
assert_eq!(result, vec![5u8; 1024*400]);
assert_eq!(gas_left, U256::from(6_893_883));
}

// Tests that contract's ability to read from a storage
Expand Down Expand Up @@ -515,7 +515,7 @@ fn storage_read() {
};

assert_eq!(Address::from(&result[12..32]), address);
assert_eq!(gas_left, U256::from(98_298));
assert_eq!(gas_left, U256::from(96_833));
}

// Tests keccak calculation
Expand All @@ -541,7 +541,7 @@ fn keccak() {
};

assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(84_240));
assert_eq!(gas_left, U256::from(84_134));
}

// math_* tests check the ability of wasm contract to perform big integer operations
Expand Down Expand Up @@ -570,7 +570,7 @@ fn math_add() {
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(93_814));
assert_eq!(gas_left, U256::from(92_086));
}

// multiplication
Expand All @@ -592,7 +592,7 @@ fn math_mul() {
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(93_300));
assert_eq!(gas_left, U256::from(91_414));
}

// subtraction
Expand All @@ -614,7 +614,7 @@ fn math_sub() {
U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(93_826));
assert_eq!(gas_left, U256::from(92_086));
}

// subtraction with overflow
Expand Down Expand Up @@ -656,7 +656,7 @@ fn math_div() {
U256::from_dec_str("1125000").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(90_603));
assert_eq!(gas_left, U256::from(87_376));
}

#[test]
Expand Down Expand Up @@ -684,7 +684,7 @@ fn storage_metering() {
};

// 0 -> not 0
assert_eq!(gas_left, U256::from(74_338));
assert_eq!(gas_left, U256::from(72_399));

// #2

Expand All @@ -703,7 +703,7 @@ fn storage_metering() {
};

// not 0 -> not 0
assert_eq!(gas_left, U256::from(89_338));
assert_eq!(gas_left, U256::from(87_399));
}

// This test checks the ability of wasm contract to invoke
Expand Down Expand Up @@ -791,7 +791,7 @@ fn externs() {
"Gas limit requested and returned does not match"
);

assert_eq!(gas_left, U256::from(92_110));
assert_eq!(gas_left, U256::from(90_435));
}

#[test]
Expand All @@ -817,7 +817,7 @@ fn embedded_keccak() {
};

assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(84_240));
assert_eq!(gas_left, U256::from(84_134));
}

/// This test checks the correctness of log extern
Expand Down Expand Up @@ -852,5 +852,45 @@ fn events() {
assert_eq!(&log_entry.data, b"gnihtemos");

assert_eq!(&result, b"gnihtemos");
assert_eq!(gas_left, U256::from(81_292));
assert_eq!(gas_left, U256::from(81_351));
}

#[test]
fn recursive() {
::ethcore_logger::init_log();
let code = load_sample!("recursive.wasm");

let mut params = ActionParams::default();
params.gas = U256::from(100_000_000);
params.code = Some(Arc::new(code));
params.data = Some({
// `recursive` expects only one 32-bit word in LE that
// represents an iteration count.
//
// We pick a relative big number to definitely hit stack overflow.
use byteorder::WriteBytesExt;
let mut data = vec![];
data.write_u32::<LittleEndian>(100000).unwrap();
data
});

let mut ext = FakeExt::new().with_wasm();

let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext);

// We expect that stack overflow will occur and it should be generated by
// deterministic stack metering. Exceeding deterministic stack height limit
// always ends with a trap generated by `unreachable` instruction.
match result {
Err(trap) => {
let err_description = trap.to_string();
assert!(
err_description.contains("Unreachable"),
"err_description: {} should contain 'Unreachable'",
err_description
);
},
_ => panic!("this test should trap"),
}
}