Skip to content

Commit

Permalink
Add exports field to Config (#1418)
Browse files Browse the repository at this point in the history
* Add `exports` field to `Config`

Add an optional `exports` field to `Config` which describes exactly
which exports the generated module should have.

* use existing exported globals for dropped values

* use Validator API when reading `exports`

* use `Validator` API in tests

* update example with initial global value
  • Loading branch information
adambratschikaye authored Feb 20, 2024
1 parent 32ffa5a commit 4eaf9fb
Show file tree
Hide file tree
Showing 6 changed files with 560 additions and 89 deletions.
95 changes: 91 additions & 4 deletions crates/wasm-smith/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ macro_rules! define_config {
/// Defaults to `None` which means that any arbitrary import can be
/// generated.
///
/// To only allow specific imports, override this method to return a
/// WebAssembly module which describes the imports allowed.
/// To only allow specific imports, set this field to a WebAssembly
/// module which describes the imports allowed.
///
/// Note that [`Self::min_imports`] is ignored when
/// `available_imports` are enabled.
///
/// The returned value must be a valid binary encoding of a
/// The provided value must be a valid binary encoding of a
/// WebAssembly module. `wasm-smith` will panic if the module cannot
/// be parsed.
///
Expand All @@ -49,6 +49,51 @@ macro_rules! define_config {
/// ```
pub available_imports: Option<Vec<u8>>,

/// If provided, the generated module will have exports with exactly
/// the same names and types as those in the provided WebAssembly
/// module. The implementation (e.g. function bodies, global
/// initializers) of each export in the generated module will be
/// random and unrelated to the implementation in the provided
/// module. Only globals and functions are supported.
///
///
/// Defaults to `None` which means arbitrary exports will be
/// generated.
///
/// To specify which exports the generated modules should have, set
/// this field to a WebAssembly module which describes the desired
/// exports. To generate modules with varying exports that meet some
/// constraints, consider randomly generating the value for this
/// field.
///
/// The provided value must be a valid binary encoding of a
/// WebAssembly module. `wasm-smith` will panic if the module cannot
/// be parsed.
///
/// # Module Limits
///
/// All types, functions, globals, and exports that are needed to
/// provide the required exports will be generated, even if it
/// causes the resulting module to exceed the limits defined in
/// [`Self::max_type_size`], [`Self::max_types`],
/// [`Self::max_funcs`], [`Self::max_globals`], or
/// [`Self::max_exports`].
///
/// # Example
///
/// As for [`Self::available_imports`], the `wat` crate can be used
/// to provide an human-readable description of the desired exports:
///
/// ```rust
/// Some(wat::parse_str(r#"
/// (module
/// (func (export "foo") (param i32) (result i64) unreachable)
/// (global (export "bar") f32 f32.const 0)
/// )
/// "#));
/// ```
pub exports: Option<Vec<u8>>,

$(
$(#[$field_attr])*
pub $field: $field_ty,
Expand All @@ -59,6 +104,7 @@ macro_rules! define_config {
fn default() -> Config {
Config {
available_imports: None,
exports: None,

$(
$field: $default,
Expand All @@ -82,12 +128,44 @@ macro_rules! define_config {
/// Note that [`Self::min_imports`] is ignored when
/// `available_imports` are enabled.
///
/// The returned value must be a valid binary encoding of a
/// The provided value must be a valid binary encoding of a
/// WebAssembly module. `wasm-smith` will panic if the module cannot
/// be parsed.
#[cfg_attr(feature = "clap", clap(long))]
available_imports: Option<std::path::PathBuf>,

/// If provided, the generated module will have exports with exactly
/// the same names and types as those in the provided WebAssembly
/// module. The implementation (e.g. function bodies, global
/// initializers) of each export in the generated module will be
/// random and unrelated to the implementation in the provided
/// module. Only globals and functions are supported.
///
/// Defaults to `None` which means arbitrary exports will be
/// generated.
///
/// To specify which exports the generated modules should have, set
/// this field to a WebAssembly module which describes the desired
/// exports. To generate modules with varying exports that meet some
/// constraints, consider randomly generating the value for this
/// field.
///
/// The provided value must be a valid binary encoding of a
/// WebAssembly module. `wasm-smith` will panic if the module cannot
/// be parsed.
///
/// # Module Limits
///
/// All types, functions, globals, and exports that are needed to
/// provide the required exports will be generated, even if it
/// causes the resulting module to exceed the limits defined in
/// [`Self::max_type_size`], [`Self::max_types`],
/// [`Self::max_funcs`], [`Self::max_globals`], or
/// [`Self::max_exports`].
///
#[cfg_attr(feature = "clap", clap(long))]
exports: Option<std::path::PathBuf>,

$(
$(#[$field_attr])*
#[cfg_attr(feature = "clap", clap(long))]
Expand All @@ -100,6 +178,7 @@ macro_rules! define_config {
pub fn or(self, other: Self) -> Self {
Self {
available_imports: self.available_imports.or(other.available_imports),
exports: self.exports.or(other.exports),

$(
$field: self.$field.or(other.$field),
Expand All @@ -121,6 +200,13 @@ macro_rules! define_config {
} else {
None
},
exports: if let Some(file) = config
.exports
.as_ref() {
Some(wat::parse_file(file)?)
} else {
None
},

$(
$field: config.$field.unwrap_or(default.$field),
Expand Down Expand Up @@ -623,6 +709,7 @@ impl<'a> Arbitrary<'a> for Config {
max_type_size: 1000,
canonicalize_nans: false,
available_imports: None,
exports: None,
threads_enabled: false,
export_everything: false,
disallow_traps: false,
Expand Down
Loading

0 comments on commit 4eaf9fb

Please sign in to comment.