mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 16:20:49 +00:00
Merge remote-tracking branch 'origin/master' into fix/fpcc-workaround
This commit is contained in:
commit
3ff3554345
@ -2,6 +2,8 @@
|
||||
|
||||
## **[Unreleased]**
|
||||
|
||||
- [#1272](https://github.com/wasmerio/wasmer/pull/1272) Fix off-by-one error bug when accessing memory with a `WasmPtr` that contains the last valid byte of memory. Also changes the behavior of `WasmPtr<T, Array>` with a length of 0 and `WasmPtr<T>` where `std::mem::size_of::<T>()` is 0 to always return `None`
|
||||
|
||||
## 0.15.0 - 2020-03-04
|
||||
|
||||
- [#1263](https://github.com/wasmerio/wasmer/pull/1263) Changed the behavior of some WASI syscalls to now handle preopened directories more properly. Changed default `--debug` logging to only show Wasmer-related messages.
|
||||
|
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -659,7 +659,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "inkwell"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/TheDan64/inkwell?rev=0a864ebf68b33d4d514b67796264b03898aa0944#0a864ebf68b33d4d514b67796264b03898aa0944"
|
||||
source = "git+https://github.com/TheDan64/inkwell?rev=af4cf4efbb27cdea8a54175ffc18ffd91964618c#af4cf4efbb27cdea8a54175ffc18ffd91964618c"
|
||||
dependencies = [
|
||||
"either",
|
||||
"inkwell_internals",
|
||||
@ -673,7 +673,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "inkwell_internals"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/TheDan64/inkwell?rev=0a864ebf68b33d4d514b67796264b03898aa0944#0a864ebf68b33d4d514b67796264b03898aa0944"
|
||||
source = "git+https://github.com/TheDan64/inkwell?rev=af4cf4efbb27cdea8a54175ffc18ffd91964618c#af4cf4efbb27cdea8a54175ffc18ffd91964618c"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
|
@ -19,13 +19,13 @@ byteorder = "1"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies.inkwell]
|
||||
git = "https://github.com/TheDan64/inkwell"
|
||||
rev = "0a864ebf68b33d4d514b67796264b03898aa0944"
|
||||
rev = "af4cf4efbb27cdea8a54175ffc18ffd91964618c"
|
||||
default-features = false
|
||||
features = ["llvm8-0", "target-x86"]
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")'.dependencies.inkwell]
|
||||
git = "https://github.com/TheDan64/inkwell"
|
||||
rev = "0a864ebf68b33d4d514b67796264b03898aa0944"
|
||||
rev = "af4cf4efbb27cdea8a54175ffc18ffd91964618c"
|
||||
default-features = false
|
||||
features = ["llvm8-0", "target-aarch64"]
|
||||
|
||||
|
@ -354,15 +354,15 @@ fn trap_if_not_representable_as_int<'ctx>(
|
||||
let failure_block = context.append_basic_block(*function, "conversion_failure_block");
|
||||
let continue_block = context.append_basic_block(*function, "conversion_success_block");
|
||||
|
||||
builder.build_conditional_branch(out_of_bounds, &failure_block, &continue_block);
|
||||
builder.position_at_end(&failure_block);
|
||||
builder.build_conditional_branch(out_of_bounds, failure_block, continue_block);
|
||||
builder.position_at_end(failure_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_illegal_arithmetic],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&continue_block);
|
||||
builder.position_at_end(continue_block);
|
||||
}
|
||||
|
||||
fn trap_if_zero_or_overflow<'ctx>(
|
||||
@ -418,15 +418,15 @@ fn trap_if_zero_or_overflow<'ctx>(
|
||||
|
||||
let shouldnt_trap_block = context.append_basic_block(*function, "shouldnt_trap_block");
|
||||
let should_trap_block = context.append_basic_block(*function, "should_trap_block");
|
||||
builder.build_conditional_branch(should_trap, &should_trap_block, &shouldnt_trap_block);
|
||||
builder.position_at_end(&should_trap_block);
|
||||
builder.build_conditional_branch(should_trap, should_trap_block, shouldnt_trap_block);
|
||||
builder.position_at_end(should_trap_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_illegal_arithmetic],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&shouldnt_trap_block);
|
||||
builder.position_at_end(shouldnt_trap_block);
|
||||
}
|
||||
|
||||
fn trap_if_zero<'ctx>(
|
||||
@ -460,15 +460,15 @@ fn trap_if_zero<'ctx>(
|
||||
|
||||
let shouldnt_trap_block = context.append_basic_block(*function, "shouldnt_trap_block");
|
||||
let should_trap_block = context.append_basic_block(*function, "should_trap_block");
|
||||
builder.build_conditional_branch(should_trap, &should_trap_block, &shouldnt_trap_block);
|
||||
builder.position_at_end(&should_trap_block);
|
||||
builder.build_conditional_branch(should_trap, should_trap_block, shouldnt_trap_block);
|
||||
builder.position_at_end(should_trap_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_illegal_arithmetic],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&shouldnt_trap_block);
|
||||
builder.position_at_end(shouldnt_trap_block);
|
||||
}
|
||||
|
||||
fn v128_into_int_vec<'ctx>(
|
||||
@ -774,17 +774,17 @@ fn resolve_memory_ptr<'ctx>(
|
||||
let not_in_bounds_block = context.append_basic_block(*function, "not_in_bounds_block");
|
||||
builder.build_conditional_branch(
|
||||
ptr_in_bounds,
|
||||
&in_bounds_continue_block,
|
||||
¬_in_bounds_block,
|
||||
in_bounds_continue_block,
|
||||
not_in_bounds_block,
|
||||
);
|
||||
builder.position_at_end(¬_in_bounds_block);
|
||||
builder.position_at_end(not_in_bounds_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_memory_oob],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&in_bounds_continue_block);
|
||||
builder.position_at_end(in_bounds_continue_block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -918,9 +918,9 @@ fn trap_if_misaligned<'ctx>(
|
||||
|
||||
let continue_block = context.append_basic_block(*function, "aligned_access_continue_block");
|
||||
let not_aligned_block = context.append_basic_block(*function, "misaligned_trap_block");
|
||||
builder.build_conditional_branch(aligned, &continue_block, ¬_aligned_block);
|
||||
builder.build_conditional_branch(aligned, continue_block, not_aligned_block);
|
||||
|
||||
builder.position_at_end(¬_aligned_block);
|
||||
builder.position_at_end(not_aligned_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_misaligned_atomic],
|
||||
@ -928,7 +928,7 @@ fn trap_if_misaligned<'ctx>(
|
||||
);
|
||||
builder.build_unreachable();
|
||||
|
||||
builder.position_at_end(&continue_block);
|
||||
builder.position_at_end(continue_block);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -1053,11 +1053,11 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
.builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.build_unconditional_branch(&start_of_code_block);
|
||||
.build_unconditional_branch(start_of_code_block);
|
||||
self.builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.position_at_end(&start_of_code_block);
|
||||
.position_at_end(start_of_code_block);
|
||||
|
||||
let cache_builder = self.context.as_ref().unwrap().create_builder();
|
||||
cache_builder.position_before(&entry_end_inst);
|
||||
@ -1210,7 +1210,7 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
})?;
|
||||
|
||||
let end_block = context.append_basic_block(function, "end");
|
||||
builder.position_at_end(&end_block);
|
||||
builder.position_at_end(end_block);
|
||||
|
||||
let phis = if let Ok(wasmer_ty) = blocktype_to_type(ty) {
|
||||
let llvm_ty = type_to_llvm(intrinsics, wasmer_ty);
|
||||
@ -1223,15 +1223,15 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
};
|
||||
|
||||
state.push_block(end_block, phis);
|
||||
builder.position_at_end(¤t_block);
|
||||
builder.position_at_end(current_block);
|
||||
}
|
||||
Operator::Loop { ty } => {
|
||||
let loop_body = context.append_basic_block(function, "loop_body");
|
||||
let loop_next = context.append_basic_block(function, "loop_outer");
|
||||
|
||||
builder.build_unconditional_branch(&loop_body);
|
||||
builder.build_unconditional_branch(loop_body);
|
||||
|
||||
builder.position_at_end(&loop_next);
|
||||
builder.position_at_end(loop_next);
|
||||
let phis = if let Ok(wasmer_ty) = blocktype_to_type(ty) {
|
||||
let llvm_ty = type_to_llvm(intrinsics, wasmer_ty);
|
||||
[llvm_ty]
|
||||
@ -1242,7 +1242,7 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
SmallVec::new()
|
||||
};
|
||||
|
||||
builder.position_at_end(&loop_body);
|
||||
builder.position_at_end(loop_body);
|
||||
|
||||
if self.track_state {
|
||||
if let Some(offset) = opcode_offset {
|
||||
@ -1299,10 +1299,10 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
// pop a value off the value stack and load it into
|
||||
// the corresponding phi.
|
||||
for (phi, value) in frame.phis().iter().zip(values) {
|
||||
phi.add_incoming(&[(&value, ¤t_block)]);
|
||||
phi.add_incoming(&[(&value, current_block)]);
|
||||
}
|
||||
|
||||
builder.build_unconditional_branch(frame.br_dest());
|
||||
builder.build_unconditional_branch(*frame.br_dest());
|
||||
|
||||
state.popn(value_len)?;
|
||||
state.reachable = false;
|
||||
@ -1327,7 +1327,7 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
});
|
||||
|
||||
for (phi, value) in frame.phis().iter().zip(param_stack) {
|
||||
phi.add_incoming(&[(&value, ¤t_block)]);
|
||||
phi.add_incoming(&[(&value, current_block)]);
|
||||
}
|
||||
|
||||
let else_block = context.append_basic_block(function, "else");
|
||||
@ -1338,8 +1338,8 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
intrinsics.i32_zero,
|
||||
&state.var_name(),
|
||||
);
|
||||
builder.build_conditional_branch(cond_value, frame.br_dest(), &else_block);
|
||||
builder.position_at_end(&else_block);
|
||||
builder.build_conditional_branch(cond_value, *frame.br_dest(), else_block);
|
||||
builder.position_at_end(else_block);
|
||||
}
|
||||
Operator::BrTable { ref table } => {
|
||||
let current_block = builder.get_insert_block().ok_or(CodegenError {
|
||||
@ -1360,7 +1360,7 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
};
|
||||
|
||||
for (phi, value) in default_frame.phis().iter().zip(args.iter()) {
|
||||
phi.add_incoming(&[(value, ¤t_block)]);
|
||||
phi.add_incoming(&[(value, current_block)]);
|
||||
}
|
||||
|
||||
let cases: Vec<_> = label_depths
|
||||
@ -1377,14 +1377,14 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
context.i32_type().const_int(case_index as u64, false);
|
||||
|
||||
for (phi, value) in frame.phis().iter().zip(args.iter()) {
|
||||
phi.add_incoming(&[(value, ¤t_block)]);
|
||||
phi.add_incoming(&[(value, current_block)]);
|
||||
}
|
||||
|
||||
Ok((case_index_literal, frame.br_dest()))
|
||||
Ok((case_index_literal, *frame.br_dest()))
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
builder.build_switch(index.into_int_value(), default_frame.br_dest(), &cases[..]);
|
||||
builder.build_switch(index.into_int_value(), *default_frame.br_dest(), &cases[..]);
|
||||
|
||||
let args_len = args.len();
|
||||
state.popn(args_len)?;
|
||||
@ -1399,7 +1399,7 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
let end_block = context.append_basic_block(function, "if_end");
|
||||
|
||||
let end_phis = {
|
||||
builder.position_at_end(&end_block);
|
||||
builder.position_at_end(end_block);
|
||||
|
||||
let phis = if let Ok(wasmer_ty) = blocktype_to_type(ty) {
|
||||
let llvm_ty = type_to_llvm(intrinsics, wasmer_ty);
|
||||
@ -1411,7 +1411,7 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
SmallVec::new()
|
||||
};
|
||||
|
||||
builder.position_at_end(¤t_block);
|
||||
builder.position_at_end(current_block);
|
||||
phis
|
||||
};
|
||||
|
||||
@ -1424,8 +1424,8 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
&state.var_name(),
|
||||
);
|
||||
|
||||
builder.build_conditional_branch(cond_value, &if_then_block, &if_else_block);
|
||||
builder.position_at_end(&if_then_block);
|
||||
builder.build_conditional_branch(cond_value, if_then_block, if_else_block);
|
||||
builder.position_at_end(if_then_block);
|
||||
state.push_if(if_then_block, if_else_block, end_block, end_phis);
|
||||
}
|
||||
Operator::Else => {
|
||||
@ -1439,10 +1439,10 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
let (value, info) = state.pop1_extra()?;
|
||||
let value =
|
||||
apply_pending_canonicalization(builder, intrinsics, value, info);
|
||||
phi.add_incoming(&[(&value, ¤t_block)])
|
||||
phi.add_incoming(&[(&value, current_block)])
|
||||
}
|
||||
let frame = state.frame_at_depth(0)?;
|
||||
builder.build_unconditional_branch(frame.code_after());
|
||||
builder.build_unconditional_branch(*frame.code_after());
|
||||
}
|
||||
|
||||
let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
|
||||
@ -1458,7 +1458,7 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
|
||||
*if_else_state = IfElseState::Else;
|
||||
|
||||
builder.position_at_end(if_else_block);
|
||||
builder.position_at_end(*if_else_block);
|
||||
state.reachable = true;
|
||||
}
|
||||
|
||||
@ -1473,10 +1473,10 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
let (value, info) = state.pop1_extra()?;
|
||||
let value =
|
||||
apply_pending_canonicalization(builder, intrinsics, value, info);
|
||||
phi.add_incoming(&[(&value, ¤t_block)]);
|
||||
phi.add_incoming(&[(&value, current_block)]);
|
||||
}
|
||||
|
||||
builder.build_unconditional_branch(frame.code_after());
|
||||
builder.build_unconditional_branch(*frame.code_after());
|
||||
}
|
||||
|
||||
if let ControlFrame::IfElse {
|
||||
@ -1487,12 +1487,12 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
} = &frame
|
||||
{
|
||||
if let IfElseState::If = if_else_state {
|
||||
builder.position_at_end(if_else);
|
||||
builder.build_unconditional_branch(next);
|
||||
builder.position_at_end(*if_else);
|
||||
builder.build_unconditional_branch(*next);
|
||||
}
|
||||
}
|
||||
|
||||
builder.position_at_end(frame.code_after());
|
||||
builder.position_at_end(*frame.code_after());
|
||||
state.reset_stack(&frame);
|
||||
|
||||
state.reachable = true;
|
||||
@ -1530,11 +1530,11 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
for phi in frame.phis().to_vec().iter() {
|
||||
let (arg, info) = state.pop1_extra()?;
|
||||
let arg = apply_pending_canonicalization(builder, intrinsics, arg, info);
|
||||
phi.add_incoming(&[(&arg, ¤t_block)]);
|
||||
phi.add_incoming(&[(&arg, current_block)]);
|
||||
}
|
||||
|
||||
let frame = state.outermost_frame()?;
|
||||
builder.build_unconditional_branch(frame.br_dest());
|
||||
builder.build_unconditional_branch(*frame.br_dest());
|
||||
|
||||
state.reachable = false;
|
||||
}
|
||||
@ -2073,17 +2073,17 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
context.append_basic_block(function, "not_in_bounds_block");
|
||||
builder.build_conditional_branch(
|
||||
index_in_bounds,
|
||||
&in_bounds_continue_block,
|
||||
¬_in_bounds_block,
|
||||
in_bounds_continue_block,
|
||||
not_in_bounds_block,
|
||||
);
|
||||
builder.position_at_end(¬_in_bounds_block);
|
||||
builder.position_at_end(not_in_bounds_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_call_indirect_oob],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&in_bounds_continue_block);
|
||||
builder.position_at_end(in_bounds_continue_block);
|
||||
|
||||
// Next, check if the signature id is correct.
|
||||
|
||||
@ -2114,18 +2114,18 @@ impl<'ctx> FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator<'ct
|
||||
context.append_basic_block(function, "sigindices_notequal_block");
|
||||
builder.build_conditional_branch(
|
||||
sigindices_equal,
|
||||
&continue_block,
|
||||
&sigindices_notequal_block,
|
||||
continue_block,
|
||||
sigindices_notequal_block,
|
||||
);
|
||||
|
||||
builder.position_at_end(&sigindices_notequal_block);
|
||||
builder.position_at_end(sigindices_notequal_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_call_indirect_sig],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&continue_block);
|
||||
builder.position_at_end(continue_block);
|
||||
|
||||
let wasmer_fn_sig = &info.signatures[sig_index];
|
||||
let fn_ty = signatures[sig_index];
|
||||
@ -8763,10 +8763,10 @@ impl<'ctx> ModuleCodeGenerator<LLVMFunctionCodeGenerator<'ctx>, LLVMBackend, Cod
|
||||
let mut state: State<'ctx> = State::new();
|
||||
let entry_block = context.append_basic_block(*function, "entry");
|
||||
let alloca_builder = context.create_builder();
|
||||
alloca_builder.position_at_end(&entry_block);
|
||||
alloca_builder.position_at_end(entry_block);
|
||||
|
||||
let return_block = context.append_basic_block(*function, "return");
|
||||
builder.position_at_end(&return_block);
|
||||
builder.position_at_end(return_block);
|
||||
|
||||
let phis: SmallVec<[PhiValue; 1]> = func_sig
|
||||
.returns()
|
||||
@ -8776,7 +8776,7 @@ impl<'ctx> ModuleCodeGenerator<LLVMFunctionCodeGenerator<'ctx>, LLVMBackend, Cod
|
||||
.collect();
|
||||
|
||||
state.push_block(return_block, phis);
|
||||
builder.position_at_end(&entry_block);
|
||||
builder.position_at_end(entry_block);
|
||||
|
||||
let mut locals = Vec::new();
|
||||
locals.extend(
|
||||
|
@ -10,20 +10,20 @@ use std::ops::{BitAnd, BitOr, BitOrAssign};
|
||||
#[derive(Debug)]
|
||||
pub enum ControlFrame<'ctx> {
|
||||
Block {
|
||||
next: BasicBlock,
|
||||
next: BasicBlock<'ctx>,
|
||||
phis: SmallVec<[PhiValue<'ctx>; 1]>,
|
||||
stack_size_snapshot: usize,
|
||||
},
|
||||
Loop {
|
||||
body: BasicBlock,
|
||||
next: BasicBlock,
|
||||
body: BasicBlock<'ctx>,
|
||||
next: BasicBlock<'ctx>,
|
||||
phis: SmallVec<[PhiValue<'ctx>; 1]>,
|
||||
stack_size_snapshot: usize,
|
||||
},
|
||||
IfElse {
|
||||
if_then: BasicBlock,
|
||||
if_else: BasicBlock,
|
||||
next: BasicBlock,
|
||||
if_then: BasicBlock<'ctx>,
|
||||
if_else: BasicBlock<'ctx>,
|
||||
next: BasicBlock<'ctx>,
|
||||
phis: SmallVec<[PhiValue<'ctx>; 1]>,
|
||||
stack_size_snapshot: usize,
|
||||
if_else_state: IfElseState,
|
||||
@ -37,7 +37,7 @@ pub enum IfElseState {
|
||||
}
|
||||
|
||||
impl<'ctx> ControlFrame<'ctx> {
|
||||
pub fn code_after(&self) -> &BasicBlock {
|
||||
pub fn code_after(&self) -> &BasicBlock<'ctx> {
|
||||
match self {
|
||||
ControlFrame::Block { ref next, .. }
|
||||
| ControlFrame::Loop { ref next, .. }
|
||||
@ -45,7 +45,7 @@ impl<'ctx> ControlFrame<'ctx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn br_dest(&self) -> &BasicBlock {
|
||||
pub fn br_dest(&self) -> &BasicBlock<'ctx> {
|
||||
match self {
|
||||
ControlFrame::Block { ref next, .. } | ControlFrame::IfElse { ref next, .. } => next,
|
||||
ControlFrame::Loop { ref body, .. } => body,
|
||||
@ -367,7 +367,7 @@ impl<'ctx> State<'ctx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn push_block(&mut self, next: BasicBlock, phis: SmallVec<[PhiValue<'ctx>; 1]>) {
|
||||
pub fn push_block(&mut self, next: BasicBlock<'ctx>, phis: SmallVec<[PhiValue<'ctx>; 1]>) {
|
||||
self.control_stack.push(ControlFrame::Block {
|
||||
next,
|
||||
phis,
|
||||
@ -377,8 +377,8 @@ impl<'ctx> State<'ctx> {
|
||||
|
||||
pub fn push_loop(
|
||||
&mut self,
|
||||
body: BasicBlock,
|
||||
next: BasicBlock,
|
||||
body: BasicBlock<'ctx>,
|
||||
next: BasicBlock<'ctx>,
|
||||
phis: SmallVec<[PhiValue<'ctx>; 1]>,
|
||||
) {
|
||||
self.control_stack.push(ControlFrame::Loop {
|
||||
@ -391,9 +391,9 @@ impl<'ctx> State<'ctx> {
|
||||
|
||||
pub fn push_if(
|
||||
&mut self,
|
||||
if_then: BasicBlock,
|
||||
if_else: BasicBlock,
|
||||
next: BasicBlock,
|
||||
if_then: BasicBlock<'ctx>,
|
||||
if_else: BasicBlock<'ctx>,
|
||||
next: BasicBlock<'ctx>,
|
||||
phis: SmallVec<[PhiValue<'ctx>; 1]>,
|
||||
) {
|
||||
self.control_stack.push(ControlFrame::IfElse {
|
||||
|
@ -55,7 +55,7 @@ fn generate_trampoline<'ctx>(
|
||||
intrinsics: &Intrinsics<'ctx>,
|
||||
) -> Result<(), String> {
|
||||
let entry_block = context.append_basic_block(trampoline_func, "entry");
|
||||
builder.position_at_end(&entry_block);
|
||||
builder.position_at_end(entry_block);
|
||||
|
||||
let (vmctx_ptr, func_ptr, args_ptr, returns_ptr) = match trampoline_func.get_params().as_slice()
|
||||
{
|
||||
|
@ -78,7 +78,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
||||
/// This invariant will be enforced in the future.
|
||||
#[inline]
|
||||
pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
|
||||
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
||||
if (self.offset as usize) + mem::size_of::<T>() > memory.size().bytes().0
|
||||
|| mem::size_of::<T>() == 0
|
||||
{
|
||||
return None;
|
||||
}
|
||||
unsafe {
|
||||
@ -99,7 +101,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
||||
/// exclusive access to Wasm linear memory before calling this method.
|
||||
#[inline]
|
||||
pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell<T>> {
|
||||
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
||||
if (self.offset as usize) + mem::size_of::<T>() > memory.size().bytes().0
|
||||
|| mem::size_of::<T>() == 0
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let cell_ptr = align_pointer(
|
||||
@ -127,7 +131,10 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
||||
let slice_full_len = index as usize + length as usize;
|
||||
|
||||
if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
|
||||
if (self.offset as usize) + (item_size * slice_full_len) > memory.size().bytes().0
|
||||
|| length == 0
|
||||
|| mem::size_of::<T>() == 0
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -161,7 +168,10 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
||||
let slice_full_len = index as usize + length as usize;
|
||||
|
||||
if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
|
||||
if (self.offset as usize) + (item_size * slice_full_len) > memory.size().bytes().0
|
||||
|| length == 0
|
||||
|| mem::size_of::<T>() == 0
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -180,7 +190,7 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
/// underlying data can be mutated if the Wasm is allowed to execute or
|
||||
/// an aliasing `WasmPtr` is used to mutate memory.
|
||||
pub fn get_utf8_string(self, memory: &Memory, str_len: u32) -> Option<&str> {
|
||||
if self.offset as usize + str_len as usize > memory.size().bytes().0 {
|
||||
if self.offset as usize + str_len as usize > memory.size().bytes().0 || str_len == 0 {
|
||||
return None;
|
||||
}
|
||||
let ptr = unsafe { memory.view::<u8>().as_ptr().add(self.offset as usize) as *const u8 };
|
||||
@ -245,3 +255,94 @@ impl<T: Copy, Ty> fmt::Debug for WasmPtr<T, Ty> {
|
||||
write!(f, "WasmPtr({:#x})", self.offset)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::memory;
|
||||
use crate::units::Pages;
|
||||
|
||||
/// Ensure that memory accesses work on the edges of memory and that out of
|
||||
/// bounds errors are caught with both `deref` and `deref_mut`.
|
||||
#[test]
|
||||
fn wasm_ptr_memory_bounds_checks_hold() {
|
||||
// create a memory
|
||||
let memory_descriptor =
|
||||
memory::MemoryDescriptor::new(Pages(1), Some(Pages(1)), false).unwrap();
|
||||
let memory = memory::Memory::new(memory_descriptor).unwrap();
|
||||
|
||||
// test that basic access works and that len = 0 is caught correctly
|
||||
let start_wasm_ptr: WasmPtr<u8> = WasmPtr::new(0);
|
||||
let start_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(0);
|
||||
|
||||
assert!(start_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { start_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
assert!(start_wasm_ptr_array.deref(&memory, 0, 0).is_none());
|
||||
assert!(start_wasm_ptr_array.get_utf8_string(&memory, 0).is_none());
|
||||
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 0).is_none() });
|
||||
assert!(start_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
|
||||
// test that accessing the last valid memory address works correctly and OOB is caught
|
||||
let last_valid_address_for_u8 = (memory.size().bytes().0 - 1) as u32;
|
||||
let end_wasm_ptr: WasmPtr<u8> = WasmPtr::new(last_valid_address_for_u8);
|
||||
assert!(end_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
|
||||
let end_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(last_valid_address_for_u8);
|
||||
|
||||
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
let invalid_idx_len_combos: [(u32, u32); 3] = [(0, 0), (0, 2), (1, 1)];
|
||||
for &(idx, len) in invalid_idx_len_combos.into_iter() {
|
||||
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||
}
|
||||
assert!(end_wasm_ptr_array.get_utf8_string(&memory, 2).is_none());
|
||||
|
||||
// test that accesing the last valid memory address for a u32 is valid
|
||||
// (same as above test but with more edge cases to assert on)
|
||||
let last_valid_address_for_u32 = (memory.size().bytes().0 - 4) as u32;
|
||||
let end_wasm_ptr: WasmPtr<u32> = WasmPtr::new(last_valid_address_for_u32);
|
||||
assert!(end_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
assert!(end_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
|
||||
let end_wasm_ptr_oob_array: [WasmPtr<u32>; 4] = [
|
||||
WasmPtr::new(last_valid_address_for_u32 + 1),
|
||||
WasmPtr::new(last_valid_address_for_u32 + 2),
|
||||
WasmPtr::new(last_valid_address_for_u32 + 3),
|
||||
WasmPtr::new(last_valid_address_for_u32 + 4),
|
||||
];
|
||||
for oob_end_ptr in end_wasm_ptr_oob_array.into_iter() {
|
||||
assert!(oob_end_ptr.deref(&memory).is_none());
|
||||
assert!(unsafe { oob_end_ptr.deref_mut(&memory).is_none() });
|
||||
}
|
||||
let end_wasm_ptr_array: WasmPtr<u32, Array> = WasmPtr::new(last_valid_address_for_u32);
|
||||
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
|
||||
let invalid_idx_len_combos: [(u32, u32); 4] = [(0, 0), (1, 0), (0, 2), (1, 1)];
|
||||
for &(idx, len) in invalid_idx_len_combos.into_iter() {
|
||||
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||
}
|
||||
|
||||
let end_wasm_ptr_array_oob_array: [WasmPtr<u32, Array>; 4] = [
|
||||
WasmPtr::new(last_valid_address_for_u32 + 1),
|
||||
WasmPtr::new(last_valid_address_for_u32 + 2),
|
||||
WasmPtr::new(last_valid_address_for_u32 + 3),
|
||||
WasmPtr::new(last_valid_address_for_u32 + 4),
|
||||
];
|
||||
|
||||
for oob_end_array_ptr in end_wasm_ptr_array_oob_array.into_iter() {
|
||||
assert!(oob_end_array_ptr.deref(&memory, 0, 1).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 0, 1).is_none() });
|
||||
assert!(oob_end_array_ptr.deref(&memory, 0, 0).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 0, 0).is_none() });
|
||||
assert!(oob_end_array_ptr.deref(&memory, 1, 0).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 1, 0).is_none() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user