Avoid plugin panics (#2232)
This commit is contained in:
parent
2fd0291a81
commit
962071619d
BIN
assets/files/plugin-oob.wasm
Executable file
BIN
assets/files/plugin-oob.wasm
Executable file
Binary file not shown.
@ -120,11 +120,19 @@ struct Repr {
|
||||
/// Owns all data associated with the WebAssembly module.
|
||||
type Store = wasmi::Store<StoreData>;
|
||||
|
||||
/// If there was an error reading/writing memory, keep the offset + length to
|
||||
/// display an error message.
|
||||
struct MemoryError {
|
||||
offset: u32,
|
||||
length: u32,
|
||||
write: bool,
|
||||
}
|
||||
/// The persistent store data used for communication between store and host.
|
||||
#[derive(Default)]
|
||||
struct StoreData {
|
||||
args: Vec<Bytes>,
|
||||
output: Vec<u8>,
|
||||
memory_error: Option<MemoryError>,
|
||||
}
|
||||
|
||||
#[scope]
|
||||
@ -245,6 +253,14 @@ impl Plugin {
|
||||
let mut code = wasmi::Value::I32(-1);
|
||||
func.call(store.as_context_mut(), &lengths, std::slice::from_mut(&mut code))
|
||||
.map_err(|err| eco_format!("plugin panicked: {err}"))?;
|
||||
if let Some(MemoryError { offset, length, write }) =
|
||||
store.data_mut().memory_error.take()
|
||||
{
|
||||
return Err(eco_format!(
|
||||
"plugin tried to {kind} out of bounds: pointer {offset:#x} is out of bounds for {kind} of length {length}",
|
||||
kind = if write { "write" } else { "read" }
|
||||
));
|
||||
}
|
||||
|
||||
// Extract the returned data.
|
||||
let output = std::mem::take(&mut store.data_mut().output);
|
||||
@ -294,7 +310,14 @@ fn wasm_minimal_protocol_write_args_to_buffer(mut caller: Caller<StoreData>, ptr
|
||||
let arguments = std::mem::take(&mut caller.data_mut().args);
|
||||
let mut offset = ptr as usize;
|
||||
for arg in arguments {
|
||||
memory.write(&mut caller, offset, arg.as_slice()).unwrap();
|
||||
if memory.write(&mut caller, offset, arg.as_slice()).is_err() {
|
||||
caller.data_mut().memory_error = Some(MemoryError {
|
||||
offset: offset as u32,
|
||||
length: arg.len() as u32,
|
||||
write: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
offset += arg.len();
|
||||
}
|
||||
}
|
||||
@ -308,6 +331,10 @@ fn wasm_minimal_protocol_send_result_to_host(
|
||||
let memory = caller.get_export("memory").unwrap().into_memory().unwrap();
|
||||
let mut buffer = std::mem::take(&mut caller.data_mut().output);
|
||||
buffer.resize(len as usize, 0);
|
||||
memory.read(&caller, ptr as _, &mut buffer).unwrap();
|
||||
if memory.read(&caller, ptr as _, &mut buffer).is_err() {
|
||||
caller.data_mut().memory_error =
|
||||
Some(MemoryError { offset: ptr, length: len, write: false });
|
||||
return;
|
||||
}
|
||||
caller.data_mut().output = buffer;
|
||||
}
|
||||
|
14
tests/typ/compiler/plugin-oob.typ
Normal file
14
tests/typ/compiler/plugin-oob.typ
Normal file
@ -0,0 +1,14 @@
|
||||
// Test Out Of Bound read/write in WebAssembly plugins communication.
|
||||
// Ref: false
|
||||
|
||||
---
|
||||
#let p = plugin("/files/plugin-oob.wasm")
|
||||
|
||||
// Error: 2-14 plugin tried to read out of bounds: pointer 0x40000000 is out of bounds for read of length 1
|
||||
#p.read_oob()
|
||||
|
||||
---
|
||||
#let p = plugin("/files/plugin-oob.wasm")
|
||||
|
||||
// Error: 2-27 plugin tried to write out of bounds: pointer 0x40000000 is out of bounds for write of length 3
|
||||
#p.write_oob(bytes("xyz"))
|
Loading…
x
Reference in New Issue
Block a user