Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate initializers before writing to memory #659

Merged
merged 3 commits into from
Aug 11, 2019
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
54 changes: 38 additions & 16 deletions lib/runtime-core/src/backing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ impl LocalBacking {
memories: &mut SliceMap<LocalMemoryIndex, Memory>,
) -> LinkResult<BoxedMap<LocalMemoryIndex, *mut vm::LocalMemory>> {
// For each init that has some data...

// Validate data size fits
for init in module.info.data_initializers.iter() {
let init_base = match init.base {
Initializer::Const(Value::I32(offset)) => offset as u32,
Expand All @@ -143,17 +145,47 @@ impl LocalBacking {
}
} as usize;

// Validate data size fits
match init.memory_index.local_or_import(&module.info) {
LocalOrImport::Local(local_memory_index) => {
let memory_desc = module.info.memories[local_memory_index];
let data_top = init_base + init.data.len();

if memory_desc.minimum.bytes().0 < data_top || data_top < init_base {
return Err(vec![LinkError::Generic {
message: "data segment does not fit".to_string(),
}]);
}
}
LocalOrImport::Import(imported_memory_index) => {
// Write the initialization data to the memory that
// we think the imported memory is.
let local_memory = unsafe { &*imports.vm_memories[imported_memory_index] };
let data_top = init_base + init.data.len();
if local_memory.bound < data_top || data_top < init_base {
return Err(vec![LinkError::Generic {
message: "data segment does not fit".to_string(),
}]);
}
}
}
}

// Initialize data
for init in module.info.data_initializers.iter() {
let init_base = match init.base {
Initializer::Const(Value::I32(offset)) => offset as u32,
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
Initializer::GetGlobal(import_global_index) => {
if let Value::I32(x) = imports.globals[import_global_index].get() {
x as u32
} else {
panic!("unsupported global type for initializer")
}
}
} as usize;

match init.memory_index.local_or_import(&module.info) {
LocalOrImport::Local(local_memory_index) => {
let mem = &memories[local_memory_index];
for (mem_byte, data_byte) in mem.view()[init_base..init_base + init.data.len()]
.iter()
Expand All @@ -165,23 +197,13 @@ impl LocalBacking {
LocalOrImport::Import(imported_memory_index) => {
// Write the initialization data to the memory that
// we think the imported memory is.
unsafe {
let memory_slice = unsafe {
let local_memory = &*imports.vm_memories[imported_memory_index];
slice::from_raw_parts_mut(local_memory.base, local_memory.bound)
};

let data_top = init_base + init.data.len();
if local_memory.bound < data_top || data_top < init_base {
return Err(vec![LinkError::Generic {
message: "data segment does not fit".to_string(),
}]);
}

let memory_slice =
slice::from_raw_parts_mut(local_memory.base, local_memory.bound);

let mem_init_view =
&mut memory_slice[init_base..init_base + init.data.len()];
mem_init_view.copy_from_slice(&init.data);
}
let mem_init_view = &mut memory_slice[init_base..init_base + init.data.len()];
mem_init_view.copy_from_slice(&init.data);
}
}
}
Expand Down
34 changes: 17 additions & 17 deletions lib/spectests/tests/excludes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,19 @@ clif:skip:names.wast:* # Names file has parsing error?
clif:skip:simd.wast:* # SIMD not implemented
clif:skip:simd_binaryen.wast:* # SIMD not implemented

# linking.wast:387,388 appear to be related to WABT issue: https://github.com/pepyakin/wabt-rs/issues/51

clif:fail:globals.wast:243 # AssertInvalid - Should be invalid
clif:fail:linking.wast:137 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837062 - illegal instruction"
clif:fail:linking.wast:139 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837062 - illegal instruction"
clif:fail:linking.wast:142 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837062 - illegal instruction"
clif:fail:linking.wast:144 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837062 - illegal instruction"
clif:fail:linking.wast:147 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837037 - illegal instruction"
clif:fail:linking.wast:149 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837037 - illegal instruction"
clif:fail:linking.wast:185 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837062 - illegal instruction"
clif:fail:linking.wast:187 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x108837062 - illegal instruction"
clif:fail:linking.wast:236 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x10883d000 - segmentation violation"
clif:fail:linking.wast:248 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x10883d000 - segmentation violation"
clif:fail:linking.wast:342 # AssertReturn - result I32(97) ("0x61") does not match expected I32(0) ("0x0")
clif:fail:linking.wast:137 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635062 - illegal instruction"
clif:fail:linking.wast:139 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635062 - illegal instruction"
clif:fail:linking.wast:142 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635062 - illegal instruction"
clif:fail:linking.wast:144 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635062 - illegal instruction"
clif:fail:linking.wast:147 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635037 - illegal instruction"
clif:fail:linking.wast:149 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635037 - illegal instruction"
clif:fail:linking.wast:185 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635062 - illegal instruction"
clif:fail:linking.wast:187 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x109635062 - illegal instruction"
clif:fail:linking.wast:236 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x10963b000 - segmentation violation"
clif:fail:linking.wast:248 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x10963b000 - segmentation violation"
clif:fail:linking.wast:354 # AssertReturn - result I32(97) ("0x61") does not match expected I32(0) ("0x0")
clif:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68")
clif:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: WebAssembly trap occurred during runtime: `call_indirect` out-of-bounds
Expand Down Expand Up @@ -838,10 +839,10 @@ llvm:fail:binary-leb128.wast:86 # Module - caught panic Any
llvm:fail:binary-leb128.wast:98 # Module - caught panic Any
llvm:fail:binary.wast:446 # Module - caught panic Any
llvm:fail:globals.wast:243 # AssertInvalid - caught panic Any
llvm:fail:i32.wast:243 # AssertReturn - result I32(115568975) ("0x6e3714f") does not match expected I32(32) ("0x20")
llvm:fail:i32.wast:252 # AssertReturn - result I32(115568992) ("0x6e37160") does not match expected I32(32) ("0x20")
llvm:fail:i64.wast:243 # AssertReturn - result I64(4410536431) ("0x106e371ef") does not match expected I64(64) ("0x40")
llvm:fail:i64.wast:252 # AssertReturn - result I64(4410536416) ("0x106e371e0") does not match expected I64(64) ("0x40")
llvm:fail:i32.wast:243 # AssertReturn - result I32(305467727) ("0x1235114f") does not match expected I32(32) ("0x20")
llvm:fail:i32.wast:252 # AssertReturn - result I32(305467744) ("0x12351160") does not match expected I32(32) ("0x20")
llvm:fail:i64.wast:243 # AssertReturn - result I64(4600435183) ("0x1123511ef") does not match expected I64(64) ("0x40")
llvm:fail:i64.wast:252 # AssertReturn - result I64(4600435168) ("0x1123511e0") does not match expected I64(64) ("0x40")
llvm:fail:imports.wast:98 # Module - caught panic Any
llvm:fail:imports.wast:99 # Module - caught panic Any
llvm:fail:imports.wast:100 # Module - caught panic Any
Expand Down Expand Up @@ -892,11 +893,10 @@ llvm:fail:linking.wast:319 # AssertReturn - No instance available: Some("$Pm")
llvm:fail:linking.wast:320 # AssertReturn - No instance available: Some("$Pm")
llvm:fail:linking.wast:321 # AssertReturn - No instance available: Some("$Pm")
llvm:fail:linking.wast:324 # AssertUnlinkable - caught panic Any
llvm:fail:linking.wast:342 # AssertReturn - result I32(97) ("0x61") does not match expected I32(0) ("0x0")
llvm:fail:linking.wast:354 # AssertReturn - result I32(97) ("0x61") does not match expected I32(0) ("0x0")
llvm:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68")
llvm:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: WebAssembly trap occurred during runtime: incorrect `call_indirect` signature
llvm:fail:load.wast:201 # AssertReturn - result I32(118083615) ("0x709d01f") does not match expected I32(32) ("0x20")
llvm:fail:load.wast:201 # AssertReturn - result I32(305745951) ("0x1239501f") does not match expected I32(32) ("0x20")
llvm:fail:start.wast:92 # Module - caught panic Any
llvm:fail:type.wast:3 # Module - caught panic Any

Expand Down