mirror of
https://github.com/typst/typst
synced 2025-05-21 12:35:29 +08:00
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.
|
/// Owns all data associated with the WebAssembly module.
|
||||||
type Store = wasmi::Store<StoreData>;
|
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.
|
/// The persistent store data used for communication between store and host.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct StoreData {
|
struct StoreData {
|
||||||
args: Vec<Bytes>,
|
args: Vec<Bytes>,
|
||||||
output: Vec<u8>,
|
output: Vec<u8>,
|
||||||
|
memory_error: Option<MemoryError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[scope]
|
#[scope]
|
||||||
@ -245,6 +253,14 @@ impl Plugin {
|
|||||||
let mut code = wasmi::Value::I32(-1);
|
let mut code = wasmi::Value::I32(-1);
|
||||||
func.call(store.as_context_mut(), &lengths, std::slice::from_mut(&mut code))
|
func.call(store.as_context_mut(), &lengths, std::slice::from_mut(&mut code))
|
||||||
.map_err(|err| eco_format!("plugin panicked: {err}"))?;
|
.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.
|
// Extract the returned data.
|
||||||
let output = std::mem::take(&mut store.data_mut().output);
|
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 arguments = std::mem::take(&mut caller.data_mut().args);
|
||||||
let mut offset = ptr as usize;
|
let mut offset = ptr as usize;
|
||||||
for arg in arguments {
|
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();
|
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 memory = caller.get_export("memory").unwrap().into_memory().unwrap();
|
||||||
let mut buffer = std::mem::take(&mut caller.data_mut().output);
|
let mut buffer = std::mem::take(&mut caller.data_mut().output);
|
||||||
buffer.resize(len as usize, 0);
|
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;
|
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