Check trap code in test suite assertions

This commit is contained in:
Artur Jamro
2019-09-25 10:34:37 -07:00
committed by Dan Gohman
parent b0fe01397b
commit 286d2515f9
7 changed files with 66 additions and 20 deletions

View File

@@ -203,6 +203,11 @@ fn handle_module(
}), }),
}; };
let mut flag_builder = settings::builder(); let mut flag_builder = settings::builder();
// There are two possible traps for division, and this way
// we get the proper one if code traps.
flag_builder.enable("avoid_div_traps").unwrap();
if enable_simd { if enable_simd {
flag_builder.enable("enable_simd").unwrap(); flag_builder.enable("enable_simd").unwrap();
} }

View File

@@ -258,6 +258,10 @@ fn rmain() -> Result<(), Error> {
let mut flag_builder = settings::builder(); let mut flag_builder = settings::builder();
let mut features: Features = Default::default(); let mut features: Features = Default::default();
// There are two possible traps for division, and this way
// we get the proper one if code traps.
flag_builder.enable("avoid_div_traps")?;
// Enable/disable producing of debug info. // Enable/disable producing of debug info.
let debug_info = args.flag_g; let debug_info = args.flag_g;

View File

@@ -128,6 +128,10 @@ fn main() {
let mut flag_builder = settings::builder(); let mut flag_builder = settings::builder();
let mut features: Features = Default::default(); let mut features: Features = Default::default();
// There are two possible traps for division, and this way
// we get the proper one if code traps.
flag_builder.enable("avoid_div_traps").unwrap();
// Enable verifier passes in debug mode. // Enable verifier passes in debug mode.
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
flag_builder.enable("enable_verifier").unwrap(); flag_builder.enable("enable_verifier").unwrap();

View File

@@ -13,6 +13,7 @@ include!(concat!(env!("OUT_DIR"), "/wast_testsuite_tests.rs"));
fn native_isa() -> Box<dyn isa::TargetIsa> { fn native_isa() -> Box<dyn isa::TargetIsa> {
let mut flag_builder = settings::builder(); let mut flag_builder = settings::builder();
flag_builder.enable("enable_verifier").unwrap(); flag_builder.enable("enable_verifier").unwrap();
flag_builder.enable("avoid_div_traps").unwrap();
let isa_builder = cranelift_native::builder().unwrap_or_else(|_| { let isa_builder = cranelift_native::builder().unwrap_or_else(|_| {
panic!("host machine is not a supported target"); panic!("host machine is not a supported target");

View File

@@ -569,6 +569,18 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
let table_entry_addr = pos.ins().table_addr(pointer_type, table, callee, 0); let table_entry_addr = pos.ins().table_addr(pointer_type, table, callee, 0);
// Dereference table_entry_addr to get the function address.
let mem_flags = ir::MemFlags::trusted();
let func_addr = pos.ins().load(
pointer_type,
mem_flags,
table_entry_addr,
i32::from(self.offsets.vmcaller_checked_anyfunc_func_ptr()),
);
// Check whether `func_addr` is null.
pos.ins().trapz(func_addr, ir::TrapCode::IndirectCallToNull);
// If necessary, check the signature. // If necessary, check the signature.
match self.module.table_plans[table_index].style { match self.module.table_plans[table_index].style {
TableStyle::CallerChecksSignature => { TableStyle::CallerChecksSignature => {
@@ -599,15 +611,6 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
} }
} }
// Dereference table_entry_addr to get the function address.
let mem_flags = ir::MemFlags::trusted();
let func_addr = pos.ins().load(
pointer_type,
mem_flags,
table_entry_addr,
i32::from(self.offsets.vmcaller_checked_anyfunc_func_ptr()),
);
let mut real_call_args = Vec::with_capacity(call_args.len() + 1); let mut real_call_args = Vec::with_capacity(call_args.len() + 1);
// First append the callee vmctx address. // First append the callee vmctx address.

View File

@@ -86,13 +86,30 @@ fn trap_message() -> String {
.expect("trap_message must be called after trap occurred"); .expect("trap_message must be called after trap occurred");
format!( format!(
"wasm trap: code {:?}, source location: {}", "wasm trap: {}, source location: {}",
// todo print the error message from wast tests trap_code_to_expected_string(trap_desc.trap_code),
trap_desc.trap_code,
trap_desc.source_loc, trap_desc.source_loc,
) )
} }
fn trap_code_to_expected_string(trap_code: ir::TrapCode) -> String {
use ir::TrapCode::*;
match trap_code {
StackOverflow => "call stack exhausted".to_string(),
HeapOutOfBounds => "out of bounds memory access".to_string(),
TableOutOfBounds => "undefined element".to_string(),
OutOfBounds => "out of bounds".to_string(), // Note: not covered by the test suite
IndirectCallToNull => "uninitialized element".to_string(),
BadSignature => "indirect call type mismatch".to_string(),
IntegerOverflow => "integer overflow".to_string(),
IntegerDivisionByZero => "integer divide by zero".to_string(),
BadConversionToInteger => "invalid conversion to integer".to_string(),
UnreachableCodeReached => "unreachable".to_string(),
Interrupt => "interrupt".to_string(), // Note: not covered by the test suite
User(x) => format!("user trap {}", x), // Note: not covered by the test suite
}
}
/// Call the wasm function pointed to by `callee`. `values_vec` points to /// Call the wasm function pointed to by `callee`. `values_vec` points to
/// a buffer which holds the incoming arguments, and to which the outgoing /// a buffer which holds the incoming arguments, and to which the outgoing
/// return values will be written. /// return values will be written.

View File

@@ -289,10 +289,16 @@ impl WastContext {
ActionOutcome::Trapped { ActionOutcome::Trapped {
message: trap_message, message: trap_message,
} => { } => {
println!( if !trap_message.contains(&message) {
"{}:{}: TODO: Check the assert_trap message: expected {}, got {}", return Err(WastFileError {
filename, line, message, trap_message filename: filename.to_string(),
); line,
error: WastError::Assert(format!(
"expected {}, got {}",
message, trap_message
)),
});
}
} }
} }
} }
@@ -315,10 +321,16 @@ impl WastContext {
ActionOutcome::Trapped { ActionOutcome::Trapped {
message: trap_message, message: trap_message,
} => { } => {
println!( if !trap_message.contains(&message) {
"{}:{}: TODO: Check the assert_exhaustion message: expected {}, got {}", return Err(WastFileError {
filename, line, message, trap_message filename: filename.to_string(),
); line,
error: WastError::Assert(format!(
"expected exhaustion with {}, got {}",
message, trap_message
)),
});
}
} }
} }
} }