mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 05:31:32 +00:00
Add bounds checking for memory accesses on dynamic memories
This commit is contained in:
@ -21,7 +21,7 @@ use wasmparser::{
|
|||||||
BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader,
|
BinaryReaderError, CodeSectionReader, LocalsReader, MemoryImmediate, Operator, OperatorsReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::intrinsics::{CtxType, GlobalCache, Intrinsics};
|
use crate::intrinsics::{CtxType, GlobalCache, Intrinsics, MemoryCache};
|
||||||
use crate::read_info::type_to_type;
|
use crate::read_info::type_to_type;
|
||||||
use crate::state::{ControlFrame, IfElseState, State};
|
use crate::state::{ControlFrame, IfElseState, State};
|
||||||
use crate::trampolines::generate_trampolines;
|
use crate::trampolines::generate_trampolines;
|
||||||
@ -1571,6 +1571,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1583,6 +1585,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1595,6 +1599,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1607,6 +1613,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1621,6 +1629,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1633,6 +1643,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1645,6 +1657,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1657,6 +1671,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1669,6 +1685,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1685,6 +1703,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1701,6 +1721,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1717,6 +1739,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1733,6 +1757,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1750,6 +1776,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1766,6 +1794,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1782,6 +1812,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1798,6 +1830,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1814,6 +1848,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1832,6 +1868,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1846,6 +1884,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1860,6 +1900,8 @@ fn parse_function(
|
|||||||
let effective_address = resolve_memory_ptr(
|
let effective_address = resolve_memory_ptr(
|
||||||
builder,
|
builder,
|
||||||
intrinsics,
|
intrinsics,
|
||||||
|
context,
|
||||||
|
&function,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
@ -1964,6 +2006,8 @@ fn parse_function(
|
|||||||
fn resolve_memory_ptr(
|
fn resolve_memory_ptr(
|
||||||
builder: &Builder,
|
builder: &Builder,
|
||||||
intrinsics: &Intrinsics,
|
intrinsics: &Intrinsics,
|
||||||
|
context: &Context,
|
||||||
|
function: &FunctionValue,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
ctx: &mut CtxType,
|
ctx: &mut CtxType,
|
||||||
memarg: MemoryImmediate,
|
memarg: MemoryImmediate,
|
||||||
@ -1975,8 +2019,62 @@ fn resolve_memory_ptr(
|
|||||||
let var_offset =
|
let var_offset =
|
||||||
builder.build_int_z_extend(var_offset_i32, intrinsics.i64_ty, &state.var_name());
|
builder.build_int_z_extend(var_offset_i32, intrinsics.i64_ty, &state.var_name());
|
||||||
let effective_offset = builder.build_int_add(var_offset, imm_offset, &state.var_name());
|
let effective_offset = builder.build_int_add(var_offset, imm_offset, &state.var_name());
|
||||||
let (mem_base, mem_bound) = ctx.memory(MemoryIndex::new(0));
|
let memory_cache = ctx.memory(MemoryIndex::new(0));
|
||||||
let mem_base_int = builder.build_ptr_to_int(mem_base, intrinsics.i64_ty, &state.var_name());
|
|
||||||
|
let mem_base_int = match memory_cache {
|
||||||
|
MemoryCache::Dynamic {
|
||||||
|
ptr_to_base_ptr,
|
||||||
|
ptr_to_bounds,
|
||||||
|
} => {
|
||||||
|
let base = builder
|
||||||
|
.build_load(ptr_to_base_ptr, "base")
|
||||||
|
.into_pointer_value();
|
||||||
|
let bounds = builder.build_load(ptr_to_bounds, "bounds").into_int_value();
|
||||||
|
|
||||||
|
let base_as_int = builder.build_ptr_to_int(base, intrinsics.i64_ty, "base_as_int");
|
||||||
|
|
||||||
|
let base_in_bounds =
|
||||||
|
builder.build_int_compare(IntPredicate::ULT, base_as_int, bounds, "base_in_bounds");
|
||||||
|
|
||||||
|
let base_in_bounds = builder
|
||||||
|
.build_call(
|
||||||
|
intrinsics.expect_i1,
|
||||||
|
&[
|
||||||
|
base_in_bounds.as_basic_value_enum(),
|
||||||
|
intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(),
|
||||||
|
],
|
||||||
|
"base_in_bounds_expect",
|
||||||
|
)
|
||||||
|
.try_as_basic_value()
|
||||||
|
.left()
|
||||||
|
.unwrap()
|
||||||
|
.into_int_value();
|
||||||
|
|
||||||
|
let in_bounds_continue_block =
|
||||||
|
context.append_basic_block(function, "in_bounds_continue_block");
|
||||||
|
let not_in_bounds_block = context.append_basic_block(function, "not_in_bounds_block");
|
||||||
|
builder.build_conditional_branch(
|
||||||
|
base_in_bounds,
|
||||||
|
&in_bounds_continue_block,
|
||||||
|
¬_in_bounds_block,
|
||||||
|
);
|
||||||
|
builder.position_at_end(¬_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);
|
||||||
|
|
||||||
|
base_as_int
|
||||||
|
}
|
||||||
|
MemoryCache::Static {
|
||||||
|
base_ptr,
|
||||||
|
bounds: _,
|
||||||
|
} => builder.build_ptr_to_int(base_ptr, intrinsics.i64_ty, "base_as_int"),
|
||||||
|
};
|
||||||
|
|
||||||
let effective_address_int =
|
let effective_address_int =
|
||||||
builder.build_int_add(mem_base_int, effective_offset, &state.var_name());
|
builder.build_int_add(mem_base_int, effective_offset, &state.var_name());
|
||||||
Ok(builder.build_int_to_ptr(effective_address_int, ptr_ty, &state.var_name()))
|
Ok(builder.build_int_to_ptr(effective_address_int, ptr_ty, &state.var_name()))
|
||||||
|
@ -398,7 +398,8 @@ impl Intrinsics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MemoryCache {
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum MemoryCache {
|
||||||
/// The memory moves around.
|
/// The memory moves around.
|
||||||
Dynamic {
|
Dynamic {
|
||||||
ptr_to_base_ptr: PointerValue,
|
ptr_to_base_ptr: PointerValue,
|
||||||
@ -452,7 +453,7 @@ impl<'a> CtxType<'a> {
|
|||||||
self.ctx_ptr_value.as_basic_value_enum()
|
self.ctx_ptr_value.as_basic_value_enum()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn memory(&mut self, index: MemoryIndex) -> (PointerValue, IntValue) {
|
pub fn memory(&mut self, index: MemoryIndex) -> MemoryCache {
|
||||||
let (cached_memories, builder, info, ctx_ptr_value, intrinsics, cache_builder) = (
|
let (cached_memories, builder, info, ctx_ptr_value, intrinsics, cache_builder) = (
|
||||||
&mut self.cached_memories,
|
&mut self.cached_memories,
|
||||||
self.builder,
|
self.builder,
|
||||||
@ -462,7 +463,7 @@ impl<'a> CtxType<'a> {
|
|||||||
&self.cache_builder,
|
&self.cache_builder,
|
||||||
);
|
);
|
||||||
|
|
||||||
let memory_cache = cached_memories.entry(index).or_insert_with(|| {
|
*cached_memories.entry(index).or_insert_with(|| {
|
||||||
let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) {
|
let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) {
|
||||||
LocalOrImport::Local(local_mem_index) => (
|
LocalOrImport::Local(local_mem_index) => (
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -516,24 +517,7 @@ impl<'a> CtxType<'a> {
|
|||||||
.into_int_value(),
|
.into_int_value(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
match memory_cache {
|
|
||||||
MemoryCache::Dynamic {
|
|
||||||
ptr_to_base_ptr,
|
|
||||||
ptr_to_bounds,
|
|
||||||
} => {
|
|
||||||
let base = builder
|
|
||||||
.build_load(*ptr_to_base_ptr, "base")
|
|
||||||
.into_pointer_value();
|
|
||||||
let bounds = builder
|
|
||||||
.build_load(*ptr_to_bounds, "bounds")
|
|
||||||
.into_int_value();
|
|
||||||
|
|
||||||
(base, bounds)
|
|
||||||
}
|
|
||||||
MemoryCache::Static { base_ptr, bounds } => (*base_ptr, *bounds),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) {
|
pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) {
|
||||||
|
Reference in New Issue
Block a user