Check trap code in test suite assertions
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user