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

fix(c-api) wasi_version_t wasn't bound correctly to C #2058

Merged
merged 11 commits into from
Jan 28, 2021
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [#2056](https://github.com/wasmerio/wasmer/pull/2056) Change back to depend on the `enumset` crate instead of `wasmer_enumset`

### Fixed
- [#2058](https://github.com/wasmerio/wasmer/pull/2058) Expose WASI versions to C correctly.
- [#2044](https://github.com/wasmerio/wasmer/pull/2044) Do not build C headers on docs.rs.

## 1.0.1 - 2021-01-12
Expand Down
142 changes: 129 additions & 13 deletions lib/c-api/src/wasm_c_api/wasi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,22 +286,40 @@ fn read_inner(wasi_file: &mut Box<dyn WasiFile>, inner_buffer: &mut [u8]) -> isi
}
}

/// The version of WASI. This is determined by the imports namespace
/// string.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum wasi_version_t {
Latest = 0,
Snapshot0 = 1,
Snapshot1 = 2,
InvalidVersion = u32::max_value(),
/// An invalid version.
INVALID_VERSION = -1,

/// Latest version.
///
/// It's a “floating” version, i.e. it's an alias to the latest
/// version (for the moment, `Snapshot1`). Using this version is a
/// way to ensure that modules will run only if they come with the
/// latest WASI version (in case of security issues for instance),
/// by just updating the runtime.
///
/// Note that this version is never returned by an API. It is
/// provided only by the user.
LATEST = 0,

/// `wasi_unstable`.
SNAPSHOT0 = 1,

/// `wasi_snapshot_preview1`.
SNAPSHOT1 = 2,
}

impl From<WasiVersion> for wasi_version_t {
fn from(other: WasiVersion) -> Self {
match other {
WasiVersion::Snapshot0 => wasi_version_t::Snapshot0,
WasiVersion::Snapshot1 => wasi_version_t::Snapshot1,
WasiVersion::Latest => wasi_version_t::Latest,
WasiVersion::Snapshot0 => wasi_version_t::SNAPSHOT0,
WasiVersion::Snapshot1 => wasi_version_t::SNAPSHOT1,
WasiVersion::Latest => wasi_version_t::LATEST,
}
}
}
Expand All @@ -311,10 +329,10 @@ impl TryFrom<wasi_version_t> for WasiVersion {

fn try_from(other: wasi_version_t) -> Result<Self, Self::Error> {
Ok(match other {
wasi_version_t::Snapshot0 => WasiVersion::Snapshot0,
wasi_version_t::Snapshot1 => WasiVersion::Snapshot1,
wasi_version_t::Latest => WasiVersion::Latest,
wasi_version_t::InvalidVersion => return Err("Invalid WASI version cannot be used"),
wasi_version_t::INVALID_VERSION => return Err("Invalid WASI version cannot be used"),
wasi_version_t::SNAPSHOT0 => WasiVersion::Snapshot0,
wasi_version_t::SNAPSHOT1 => WasiVersion::Snapshot1,
wasi_version_t::LATEST => WasiVersion::Latest,
})
}
}
Expand All @@ -323,7 +341,7 @@ impl TryFrom<wasi_version_t> for WasiVersion {
pub unsafe extern "C" fn wasi_get_wasi_version(module: &wasm_module_t) -> wasi_version_t {
get_wasi_version(&module.inner, false)
.map(Into::into)
.unwrap_or(wasi_version_t::InvalidVersion)
.unwrap_or(wasi_version_t::INVALID_VERSION)
}

/// Takes ownership of `wasi_env_t`.
Expand Down Expand Up @@ -396,3 +414,101 @@ pub unsafe extern "C" fn wasi_get_start_function(
/// cbindgen:ignore
#[no_mangle]
pub unsafe extern "C" fn wasm_extern_delete(_item: Option<Box<wasm_extern_t>>) {}

#[cfg(test)]
mod tests {
use inline_c::assert_c;

#[test]
fn test_wasi_get_wasi_version_snapshot0() {
(assert_c! {
#include "tests/wasmer_wasm.h"

int main() {
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);

wasm_byte_vec_t wat;
wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_unstable\" \"args_get\" (func (param i32 i32) (result i32))))");
wasm_byte_vec_t wasm;
wat2wasm(&wat, &wasm);

wasm_module_t* module = wasm_module_new(store, &wasm);
assert(module);

assert(wasi_get_wasi_version(module) == SNAPSHOT0);

wasm_module_delete(module);
wasm_byte_vec_delete(&wasm);
wasm_byte_vec_delete(&wat);
wasm_store_delete(store);
wasm_engine_delete(engine);

return 0;
}
})
.success();
}

#[test]
fn test_wasi_get_wasi_version_snapshot1() {
(assert_c! {
#include "tests/wasmer_wasm.h"

int main() {
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);

wasm_byte_vec_t wat;
wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_snapshot_preview1\" \"args_get\" (func (param i32 i32) (result i32))))");
wasm_byte_vec_t wasm;
wat2wasm(&wat, &wasm);

wasm_module_t* module = wasm_module_new(store, &wasm);
assert(module);

assert(wasi_get_wasi_version(module) == SNAPSHOT1);

wasm_module_delete(module);
wasm_byte_vec_delete(&wasm);
wasm_byte_vec_delete(&wat);
wasm_store_delete(store);
wasm_engine_delete(engine);

return 0;
}
})
.success();
}

#[test]
fn test_wasi_get_wasi_version_invalid() {
(assert_c! {
#include "tests/wasmer_wasm.h"

int main() {
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);

wasm_byte_vec_t wat;
wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_snpsht_prvw1\" \"args_get\" (func (param i32 i32) (result i32))))");
wasm_byte_vec_t wasm;
wat2wasm(&wat, &wasm);

wasm_module_t* module = wasm_module_new(store, &wasm);
assert(module);

assert(wasi_get_wasi_version(module) == INVALID_VERSION);

wasm_module_delete(module);
wasm_byte_vec_delete(&wasm);
wasm_byte_vec_delete(&wat);
wasm_store_delete(store);
wasm_engine_delete(engine);

return 0;
}
})
.success();
}
}
10 changes: 0 additions & 10 deletions lib/c-api/src/wasm_c_api/wat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ mod tests {
#include "tests/wasmer_wasm.h"

int main() {
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);

wasm_byte_vec_t wat;
wasmer_byte_vec_new_from_string(&wat, "(module)");
wasm_byte_vec_t wasm;
Expand All @@ -65,8 +62,6 @@ mod tests {

wasm_byte_vec_delete(&wasm);
wasm_byte_vec_delete(&wat);
wasm_store_delete(store);
wasm_engine_delete(engine);

return 0;
}
Expand All @@ -80,9 +75,6 @@ mod tests {
#include "tests/wasmer_wasm.h"

int main() {
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);

wasm_byte_vec_t wat;
wasmer_byte_vec_new_from_string(&wat, "(module");
wasm_byte_vec_t wasm;
Expand All @@ -92,8 +84,6 @@ mod tests {
assert(wasmer_last_error_length() > 0);

wasm_byte_vec_delete(&wat);
wasm_store_delete(store);
wasm_engine_delete(engine);

return 0;
}
Expand Down
46 changes: 42 additions & 4 deletions lib/c-api/wasmer_wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,48 @@
#include <stdlib.h>
#include "wasm.h"

#if defined(WASMER_WASI_ENABLED)
/**
* The version of WASI. This is determined by the imports namespace
* string.
*/
typedef enum {
#if defined(WASMER_WASI_ENABLED)
/**
* An invalid version.
*/
INVALID_VERSION = -1,
#endif
#if defined(WASMER_WASI_ENABLED)
/**
* Latest version.
*
* It's a “floating” version, i.e. it's an alias to the latest
* version (for the moment, `Snapshot1`). Using this version is a
* way to ensure that modules will run only if they come with the
* latest WASI version (in case of security issues for instance),
* by just updating the runtime.
*
* Note that this version is never returned by an API. It is
* provided only by the user.
*/
LATEST = 0,
#endif
#if defined(WASMER_WASI_ENABLED)
/**
* `wasi_unstable`.
*/
SNAPSHOT0 = 1,
#endif
#if defined(WASMER_WASI_ENABLED)
/**
* `wasi_snapshot_preview1`.
*/
SNAPSHOT1 = 2,
#endif
} wasi_version_t;
#endif

#if defined(WASMER_COMPILER_ENABLED)
/**
* Kind of compilers that can be used by the engines.
Expand Down Expand Up @@ -120,10 +162,6 @@ typedef struct wasi_config_t wasi_config_t;
typedef struct wasi_env_t wasi_env_t;
#endif

#if defined(WASMER_WASI_ENABLED)
typedef struct wasi_version_t wasi_version_t;
#endif

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
Expand Down
1 change: 1 addition & 0 deletions lib/wasi/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn is_wasi_module(module: &Module) -> bool {
pub enum WasiVersion {
/// `wasi_unstable`.
Snapshot0,

/// `wasi_snapshot_preview1`.
Snapshot1,

Expand Down