add table_grow_failed

This commit is contained in:
Pat Hickey
2021-10-21 15:07:40 -07:00
parent c0a1af94cf
commit a1301f8dae
4 changed files with 40 additions and 9 deletions

View File

@@ -90,24 +90,28 @@ pub unsafe trait Store {
&mut self,
) -> (&mut VMExternRefActivationsTable, &dyn ModuleInfoLookup);
/// Callback invoked to allow the store's resource limiter to reject a memory grow operation.
/// Callback invoked to allow the store's resource limiter to reject a
/// memory grow operation.
fn memory_growing(
&mut self,
current: usize,
desired: usize,
maximum: Option<usize>,
) -> Result<bool, Error>;
/// Callback invoked to notify the store's resource limiter that a memory grow operation has
/// failed.
/// Callback invoked to notify the store's resource limiter that a memory
/// grow operation has failed.
fn memory_grow_failed(&mut self, error: &Error);
/// Callback invoked to allow the store's resource limiter to reject a table grow operation.
/// Callback invoked to allow the store's resource limiter to reject a
/// table grow operation.
fn table_growing(
&mut self,
current: u32,
desired: u32,
maximum: Option<u32>,
) -> Result<bool, Error>;
/// Callback invoked to notify the store's resource limiter that a table
/// grow operation has failed.
fn table_grow_failed(&mut self, error: &Error);
/// Callback invoked whenever fuel runs out by a wasm instance. If an error
/// is returned that's raised as a trap. Otherwise wasm execution will
/// continue as normal.

View File

@@ -4,8 +4,7 @@
use crate::vmcontext::{VMCallerCheckedAnyfunc, VMTableDefinition};
use crate::{Store, Trap, VMExternRef};
use anyhow::Error;
use anyhow::{bail, Result};
use anyhow::{bail, format_err, Error, Result};
use std::convert::{TryFrom, TryInto};
use std::ops::Range;
use std::ptr;
@@ -302,6 +301,7 @@ impl Table {
if let Some(max) = self.maximum() {
if new_size > max {
store.table_grow_failed(&format_err!("Table maximum size exceeded"));
return Ok(None);
}
}

View File

@@ -50,6 +50,13 @@ pub trait ResourceLimiter {
/// effect as the table will not grow.
fn table_growing(&mut self, current: u32, desired: u32, maximum: Option<u32>) -> bool;
/// Notifies the resource limiter that growing a linear memory, permitted by
/// the `table_growing` method, has failed.
///
/// Reasons for failure include: the growth exceeds the `maximum` passed to
/// `table_growing`. This could expand in the future.
fn table_grow_failed(&mut self, _error: &anyhow::Error) {}
/// The maximum number of instances that can be created for a `Store`.
///
/// Module instantiation will fail if this limit is exceeded.
@@ -79,9 +86,13 @@ pub trait ResourceLimiter {
}
#[cfg(feature = "async")]
/// Used by hosts to limit resource consumption of instances.
/// Identical to [`ResourceLimiter`], except that the `memory_growing` and `table_growing`
/// Used by hosts to limit resource consumption of instances. Identical to
/// [`ResourceLimiter`], except that the `memory_growing` and `table_growing`
/// functions are async. Must be used with an async [`Store`].
///
/// This trait is used with [`Store::limiter_async`]: see those docs for
/// restrictions on using other Wasmtime interfaces with an async resource
/// limiter.
#[async_trait::async_trait]
pub trait ResourceLimiterAsync {
/// Async version of [`ResourceLimiter::memory_growing`]
@@ -98,6 +109,9 @@ pub trait ResourceLimiterAsync {
/// Asynchronous version of [`ResourceLimiter::table_growing`]
async fn table_growing(&mut self, current: u32, desired: u32, maximum: Option<u32>) -> bool;
/// Identical to [`ResourceLimiter::table_grow_failed`]
fn table_grow_failed(&mut self, _error: &anyhow::Error) {}
/// Identical to [`ResourceLimiter::instances`]`
fn instances(&self) -> usize {
DEFAULT_INSTANCE_LIMIT

View File

@@ -1618,6 +1618,19 @@ unsafe impl<T> wasmtime_runtime::Store for StoreInner<T> {
}
}
fn table_grow_failed(&mut self, error: &anyhow::Error) {
match self.limiter {
Some(ResourceLimiterInner::Sync(ref mut limiter)) => {
limiter(&mut self.data).table_grow_failed(error)
}
#[cfg(feature = "async")]
Some(ResourceLimiterInner::Async(ref mut limiter)) => {
limiter(&mut self.data).table_grow_failed(error)
}
None => {}
}
}
fn out_of_gas(&mut self) -> Result<(), anyhow::Error> {
return match &mut self.out_of_gas_behavior {
OutOfGas::Trap => Err(anyhow::Error::new(OutOfGasError)),