From ec378597f191879c2a150a443f48f318851934fe Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 14:49:14 +0100 Subject: [PATCH 01/19] chore(runtime-c-api) Update headers. --- lib/runtime-c-api/wasmer.h | 2 +- lib/runtime-c-api/wasmer.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 1c3bf4c7ea4..e5d1aee72f2 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -47,7 +47,7 @@ enum Version { Unknown = 0, /** * Latest version. See `wasmer_wasi::WasiVersion::Latest` to - * leran more. + * learn more. */ Latest = 1, /** diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 0f4f44441a0..9ab20ad524a 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -44,7 +44,7 @@ enum class Version : uint8_t { /// Version cannot be detected or is unknown. Unknown = 0, /// Latest version. See `wasmer_wasi::WasiVersion::Latest` to - /// leran more. + /// learn more. Latest = 1, /// `wasi_unstable`. Snapshot0 = 2, From e913e8928f68499d9ac2a398c834d707d3deb897 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 15:12:56 +0100 Subject: [PATCH 02/19] chore(runtime-c-api) Fix CS. --- lib/runtime-c-api/src/export.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/runtime-c-api/src/export.rs b/lib/runtime-c-api/src/export.rs index 40d370111b5..5f33748ce3b 100644 --- a/lib/runtime-c-api/src/export.rs +++ b/lib/runtime-c-api/src/export.rs @@ -456,6 +456,7 @@ pub unsafe extern "C" fn wasmer_export_func_call( let instance = &*named_export.instance; let result = instance.call(&named_export.name, ¶ms[..]); + match result { Ok(results_vec) => { if !results_vec.is_empty() { From 35459c2931d9554256196e7d2101345dad2f9faf Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 15:13:30 +0100 Subject: [PATCH 03/19] feat(runtime-c-api) Implement `wasmer_import_trap`. The new `wasmer_import_trap` allows a host function to fail properly with the Wasmer trapping API. --- lib/runtime-c-api/src/import/mod.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/src/import/mod.rs b/lib/runtime-c-api/src/import/mod.rs index 1c3c1521c8f..de9692d8ec5 100644 --- a/lib/runtime-c-api/src/import/mod.rs +++ b/lib/runtime-c-api/src/import/mod.rs @@ -4,13 +4,20 @@ use crate::{ error::{update_last_error, CApiError}, export::{wasmer_import_export_kind, wasmer_import_export_value}, + instance::wasmer_instance_context_t, module::wasmer_module_t, value::wasmer_value_tag, wasmer_byte_array, wasmer_result_t, }; use libc::c_uint; -use std::{convert::TryFrom, ffi::c_void, ptr, slice, sync::Arc}; -use wasmer_runtime::{Global, Memory, Module, Table}; +use std::{ + convert::TryFrom, + ffi::{c_void, CStr}, + os::raw::c_char, + ptr, slice, + sync::Arc, +}; +use wasmer_runtime::{Ctx, Global, Memory, Module, Table}; use wasmer_runtime_core::{ export::{Context, Export, FuncPointer}, import::{ImportObject, ImportObjectIterator}, @@ -661,6 +668,24 @@ pub unsafe extern "C" fn wasmer_import_func_new( Box::into_raw(export) as *mut wasmer_import_func_t } +/// Hello +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_import_trap( + ctx: *const wasmer_instance_context_t, + error_message: *const c_char, +) -> c_uint { + let ctx = &*(ctx as *const Ctx); + let error_message = CStr::from_ptr(error_message).to_str().unwrap(); + + (&*ctx.module) + .runnable_module + .do_early_trap(Box::new(error_message)); // never returns + + #[allow(unreachable_code)] + 0 +} + /// Sets the params buffer to the parameter types of the given wasmer_import_func_t /// /// Returns `wasmer_result_t::WASMER_OK` upon success. From 684620435f9de0b004e934ccc8f7f68629bcd154 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 15:14:18 +0100 Subject: [PATCH 04/19] chore(runtime-c-api) Update headers. --- lib/runtime-c-api/wasmer.h | 5 +++++ lib/runtime-c-api/wasmer.hh | 3 +++ 2 files changed, 8 insertions(+) diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index e5d1aee72f2..9d555abbf8c 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -661,6 +661,11 @@ wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer */ wasmer_import_object_t *wasmer_import_object_new(void); +/** + * Hello + */ +unsigned int wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); + /** * Calls an instances exported function by `name` with the provided parameters. * Results are set using the provided `results` pointer. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 9ab20ad524a..aedaf0a5c40 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -528,6 +528,9 @@ wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer /// See also `wasmer_import_object_append` wasmer_import_object_t *wasmer_import_object_new(); +/// Hello +unsigned int wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); + /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. /// From c7a4825bee2075757ed81d50f921d05e3f66fd81 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 15:14:34 +0100 Subject: [PATCH 05/19] doc(runtime-core) Update documentation. --- lib/runtime-core/src/backend.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 19995f3a7a8..cd4b8bafa28 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -219,10 +219,11 @@ pub trait RunnableModule: Send + Sync { } /// A wasm trampoline contains the necessary data to dynamically call an exported wasm function. - /// Given a particular signature index, we are returned a trampoline that is matched with that + /// Given a particular signature index, we are returning a trampoline that is matched with that /// signature and an invoke function that can call the trampoline. fn get_trampoline(&self, info: &ModuleInfo, sig_index: SigIndex) -> Option; + /// Trap an error. unsafe fn do_early_trap(&self, data: Box) -> !; /// Returns the machine code associated with this module. From 4bf3d6dd41a21e69426b01562e97d02ce432a1fc Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 15:14:52 +0100 Subject: [PATCH 06/19] test(runtime-c-api) Test `wasmer_import_trap`. --- lib/runtime-c-api/tests/test-import-function.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index a6bea2a54c4..fbe75bd8f2b 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -9,6 +9,7 @@ static int memory_len = 0; static int ptr_len = 0; static char actual_str[14] = {}; static int actual_context_data_value = 0; +static const char *trap_error_message = "hello"; typedef struct { int value; @@ -31,12 +32,14 @@ void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) actual_str[idx] = mem_bytes[ptr + idx]; } actual_str[13] = '\0'; - printf("In print_str, memory len: %d, ptr_len: %d\n, str %s", mem_len, len, actual_str); + printf("In print_str, memory len: %d, ptr_len: %d, str %s\n", mem_len, len, actual_str); print_str_called = true; memory_len = mem_len; ptr_len = len; actual_context_data_value = ((context_data *) wasmer_instance_context_data_get(ctx))->value; + + wasmer_import_trap(ctx, trap_error_message); } int main() From 8790f6dbc9ff21fb0459a3a2094d5a5c925d5167 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 13 Jan 2020 07:20:06 +0100 Subject: [PATCH 07/19] feat(runtime-c-api) Check pointers aren't null in `wasmer_import_trap`. --- lib/runtime-c-api/src/import/mod.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/src/import/mod.rs b/lib/runtime-c-api/src/import/mod.rs index de9692d8ec5..76e332283fe 100644 --- a/lib/runtime-c-api/src/import/mod.rs +++ b/lib/runtime-c-api/src/import/mod.rs @@ -674,7 +674,23 @@ pub unsafe extern "C" fn wasmer_import_func_new( pub unsafe extern "C" fn wasmer_import_trap( ctx: *const wasmer_instance_context_t, error_message: *const c_char, -) -> c_uint { +) -> wasmer_result_t { + if ctx.is_null() { + update_last_error(CApiError { + msg: "ctx ptr is null in wasmer_import_trap".to_string(), + }); + + return wasmer_result_t::WASMER_ERROR; + } + + if error_message.is_null() { + update_last_error(CApiError { + msg: "error_message is null in wasmer_import_trap".to_string(), + }); + + return wasmer_result_t::WASMER_ERROR; + } + let ctx = &*(ctx as *const Ctx); let error_message = CStr::from_ptr(error_message).to_str().unwrap(); @@ -683,7 +699,7 @@ pub unsafe extern "C" fn wasmer_import_trap( .do_early_trap(Box::new(error_message)); // never returns #[allow(unreachable_code)] - 0 + wasmer_result_t::WASMER_OK } /// Sets the params buffer to the parameter types of the given wasmer_import_func_t From b45ead289f4f0249b40b9ed6b0b91c6334f06792 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 13 Jan 2020 07:22:03 +0100 Subject: [PATCH 08/19] test(runtime-c-api) Test `wasmer_import_trap`. --- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 5 ++ .../tests/test-import-function.c | 3 - lib/runtime-c-api/tests/test-import-trap.c | 80 +++++++++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 lib/runtime-c-api/tests/test-import-trap.c diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index b62699da34d..722e91641c0 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -15,6 +15,7 @@ test-exported-memory test-exports test-globals test-import-function +test-import-trap test-import-object test-imports test-instantiate diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index f9aecd4d694..58e94077bd1 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(test-exported-memory test-exported-memory.c) add_executable(test-exports test-exports.c) add_executable(test-globals test-globals.c) add_executable(test-import-function test-import-function.c) +add_executable(test-import-trap test-import-trap.c) add_executable(test-imports test-imports.c) add_executable(test-import-object test-import-object.c) add_executable(test-instantiate test-instantiate.c) @@ -64,6 +65,10 @@ target_link_libraries(test-import-function general ${WASMER_LIB}) target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS}) add_test(test-import-function test-import-function) +target_link_libraries(test-import-trap general ${WASMER_LIB}) +target_compile_options(test-import-trap PRIVATE ${COMPILER_OPTIONS}) +add_test(test-import-trap test-import-trap) + target_link_libraries(test-imports general ${WASMER_LIB}) target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) add_test(test-imports test-imports) diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index fbe75bd8f2b..a53dec75f99 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -9,7 +9,6 @@ static int memory_len = 0; static int ptr_len = 0; static char actual_str[14] = {}; static int actual_context_data_value = 0; -static const char *trap_error_message = "hello"; typedef struct { int value; @@ -38,8 +37,6 @@ void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) ptr_len = len; actual_context_data_value = ((context_data *) wasmer_instance_context_data_get(ctx))->value; - - wasmer_import_trap(ctx, trap_error_message); } int main() diff --git a/lib/runtime-c-api/tests/test-import-trap.c b/lib/runtime-c-api/tests/test-import-trap.c new file mode 100644 index 00000000000..4aaa725f5b2 --- /dev/null +++ b/lib/runtime-c-api/tests/test-import-trap.c @@ -0,0 +1,80 @@ +#include +#include "../wasmer.h" +#include +#include +#include + +static const char *trap_error_message = "Hello"; + +void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) +{ + wasmer_import_trap(ctx, trap_error_message); +} + +int main() +{ + wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; + wasmer_value_tag returns_sig[] = {}; + + printf("Creating new func\n"); + wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0); + + char *module_name = "env"; + wasmer_byte_array module_name_bytes = { + .bytes = (const uint8_t *) module_name, + .bytes_len = strlen(module_name), + }; + + char *import_name = "print_str"; + wasmer_byte_array import_name_bytes = { + .bytes = (const uint8_t *) import_name, + .bytes_len = strlen(import_name), + }; + + wasmer_import_t import = { + .module_name = module_name_bytes, + .import_name = import_name_bytes, + .tag = WASM_FUNCTION, + .value.func = func, + }; + + wasmer_import_t imports[] = {import}; + + // Read the wasm file bytes + FILE *file = fopen("assets/wasm_sample_app.wasm", "r"); + fseek(file, 0, SEEK_END); + long len = ftell(file); + uint8_t *bytes = malloc(len); + fseek(file, 0, SEEK_SET); + fread(bytes, 1, len, file); + fclose(file); + + printf("Instantiating\n"); + wasmer_instance_t *instance = NULL; + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 1); + printf("Compile result: %d\n", compile_result); + + assert(compile_result == WASMER_OK); + + wasmer_value_t params[] = {}; + wasmer_value_t results[] = {}; + wasmer_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0); + printf("Call result: %d\n", call_result); + + assert(call_result == WASMER_ERROR); + + int error_len = wasmer_last_error_length(); + printf("Error len: `%d`\n", 20); + char *error_str = malloc(error_len); + wasmer_last_error_message(error_str, error_len); + printf("Error str: `%s`\n", error_str); + + assert(0 == strcmp(error_str, "Call error: \"Hello\"")); + + printf("Destroying func\n"); + wasmer_import_func_destroy(func); + printf("Destroy instance\n"); + wasmer_instance_destroy(instance); + + return 0; +} From a506411eb58339d205e1962fa2dbb649a16d64c9 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 13 Jan 2020 07:35:37 +0100 Subject: [PATCH 09/19] doc(runtime-c-api) Improve documentation of `wasmer_import_trap`. --- lib/runtime-c-api/src/import/mod.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/runtime-c-api/src/import/mod.rs b/lib/runtime-c-api/src/import/mod.rs index 76e332283fe..4c4903c0789 100644 --- a/lib/runtime-c-api/src/import/mod.rs +++ b/lib/runtime-c-api/src/import/mod.rs @@ -668,7 +668,20 @@ pub unsafe extern "C" fn wasmer_import_func_new( Box::into_raw(export) as *mut wasmer_import_func_t } -/// Hello +/// Stop the execution of a host function, aka imported function. The +/// function must be used _only_ inside a host function. +/// +/// The pointer to `wasmer_instance_context_t` is received by the host +/// function as its first argument. Just passing it to `ctx` is fine. +/// +/// The error message must have a greater lifetime than the host +/// function itself since the error is read outside the host function +/// with `wasmer_last_error_message`. +/// +/// This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or +/// `error_message` are null. +/// +/// This function never returns otherwise. #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_import_trap( From b494bd860d818590583646c57d0539cec1a2b062 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 13 Jan 2020 07:35:57 +0100 Subject: [PATCH 10/19] doc(runtime-c-api) Improve `wasmer_import_func_new`'s documentation. --- lib/runtime-c-api/src/import/mod.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/src/import/mod.rs b/lib/runtime-c-api/src/import/mod.rs index 4c4903c0789..8e788585bdc 100644 --- a/lib/runtime-c-api/src/import/mod.rs +++ b/lib/runtime-c-api/src/import/mod.rs @@ -643,9 +643,23 @@ pub unsafe extern "C" fn wasmer_import_func_params_arity( } } -/// Creates new func +/// Creates new host function, aka imported function. `func` is a +/// function pointer, where the first argument is the famous `vm::Ctx` +/// (in Rust), or `wasmer_instance_context_t` (in C). All arguments +/// must be typed with compatible WebAssembly native types: /// -/// The caller owns the object and should call `wasmer_import_func_destroy` to free it. +/// | WebAssembly type | C/C++ type | +/// | ---------------- | ---------- | +/// | `i32` | `int32_t` | +/// | `i64` | `int64_t` | +/// | `f32` | `float` | +/// | `f64` | `double` | +/// +/// The function pointer must have a lifetime greater than the +/// WebAssembly instance lifetime. +/// +/// The caller owns the object and should call +/// `wasmer_import_func_destroy` to free it. #[no_mangle] #[allow(clippy::cast_ptr_alignment)] pub unsafe extern "C" fn wasmer_import_func_new( From 6e7d5baccc1ea0be0a2da93c635d202a448796bb Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 13 Jan 2020 07:39:04 +0100 Subject: [PATCH 11/19] chore(runtime-c-api) Update C/C++ headers. --- lib/runtime-c-api/wasmer.h | 35 +++++++++++++++++++++++++++++++---- lib/runtime-c-api/wasmer.hh | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 9d555abbf8c..154e58af732 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -537,9 +537,23 @@ unsigned int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports) void wasmer_import_func_destroy(wasmer_import_func_t *func); /** - * Creates new func + * Creates new host function, aka imported function. `func` is a + * function pointer, where the first argument is the famous `vm::Ctx` + * (in Rust), or `wasmer_instance_context_t` (in C). All arguments + * must be typed with compatible WebAssembly native types: * - * The caller owns the object and should call `wasmer_import_func_destroy` to free it. + * | WebAssembly type | C/C++ type | + * | ---------------- | ---------- | + * | `i32` | `int32_t` | + * | `i64` | `int64_t` | + * | `f32` | `float` | + * | `f64` | `double` | + * + * The function pointer must have a lifetime greater than the + * WebAssembly instance lifetime. + * + * The caller owns the object and should call + * `wasmer_import_func_destroy` to free it. */ wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), const wasmer_value_tag *params, @@ -662,9 +676,22 @@ wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer wasmer_import_object_t *wasmer_import_object_new(void); /** - * Hello + * Stop the execution of a host function, aka imported function. The + * function must be used _only_ inside a host function. + * + * The pointer to `wasmer_instance_context_t` is received by the host + * function as its first argument. Just passing it to `ctx` is fine. + * + * The error message must have a greater lifetime than the host + * function itself since the error is read outside the host function + * with `wasmer_last_error_message`. + * + * This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or + * `error_message` are null. + * + * This function never returns otherwise. */ -unsigned int wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); +wasmer_result_t wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); /** * Calls an instances exported function by `name` with the provided parameters. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index aedaf0a5c40..aad45957004 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -431,9 +431,23 @@ unsigned int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports) /// Frees memory for the given Func void wasmer_import_func_destroy(wasmer_import_func_t *func); -/// Creates new func -/// -/// The caller owns the object and should call `wasmer_import_func_destroy` to free it. +/// Creates new host function, aka imported function. `func` is a +/// function pointer, where the first argument is the famous `vm::Ctx` +/// (in Rust), or `wasmer_instance_context_t` (in C). All arguments +/// must be typed with compatible WebAssembly native types: +/// +/// | WebAssembly type | C/C++ type | +/// | ---------------- | ---------- | +/// | `i32` | `int32_t` | +/// | `i64` | `int64_t` | +/// | `f32` | `float` | +/// | `f64` | `double` | +/// +/// The function pointer must have a lifetime greater than the +/// WebAssembly instance lifetime. +/// +/// The caller owns the object and should call +/// `wasmer_import_func_destroy` to free it. wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), const wasmer_value_tag *params, unsigned int params_len, @@ -528,8 +542,21 @@ wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer /// See also `wasmer_import_object_append` wasmer_import_object_t *wasmer_import_object_new(); -/// Hello -unsigned int wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); +/// Stop the execution of a host function, aka imported function. The +/// function must be used _only_ inside a host function. +/// +/// The pointer to `wasmer_instance_context_t` is received by the host +/// function as its first argument. Just passing it to `ctx` is fine. +/// +/// The error message must have a greater lifetime than the host +/// function itself since the error is read outside the host function +/// with `wasmer_last_error_message`. +/// +/// This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or +/// `error_message` are null. +/// +/// This function never returns otherwise. +wasmer_result_t wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. From b5e96b8aa1ef1b99cadc94b6a73403afb2f28a05 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 13 Jan 2020 07:40:33 +0100 Subject: [PATCH 12/19] doc(changelog) Add #1133. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe82692b441..82f8bcc03e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## **[Unreleased]** +- [#1133](https://github.com/wasmerio/wasmer/pull/1133) New `wasmer_import_trap` function in the C API, to properly error from within a host function - [#1128](https://github.com/wasmerio/wasmer/pull/1128) Fix a crash when a host function is missing and the `allow_missing_functions` flag is enabled - [#1097](https://github.com/wasmerio/wasmer/pull/1097) Move inline breakpoint outside of runtime backend - [#1095](https://github.com/wasmerio/wasmer/pull/1095) Update to cranelift 0.52. From 176152e7d56769eec0834e309213804c07a843fb Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 13 Jan 2020 07:46:48 +0100 Subject: [PATCH 13/19] test(runtime-c-api) Remove a hardcoded value. --- lib/runtime-c-api/tests/test-import-trap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/tests/test-import-trap.c b/lib/runtime-c-api/tests/test-import-trap.c index 4aaa725f5b2..ab11bcca9bd 100644 --- a/lib/runtime-c-api/tests/test-import-trap.c +++ b/lib/runtime-c-api/tests/test-import-trap.c @@ -64,7 +64,7 @@ int main() assert(call_result == WASMER_ERROR); int error_len = wasmer_last_error_length(); - printf("Error len: `%d`\n", 20); + printf("Error len: `%d`\n", error_len); char *error_str = malloc(error_len); wasmer_last_error_message(error_str, error_len); printf("Error str: `%s`\n", error_str); From c0b439e66a841d378f8da1173b5a3ebd6f6e6ab5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 15 Jan 2020 08:37:20 +0100 Subject: [PATCH 14/19] feat(runtime-c-api) Rename `wasmer_import_trap` to `wasmer_trap`. --- lib/runtime-c-api/src/import/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-c-api/src/import/mod.rs b/lib/runtime-c-api/src/import/mod.rs index 8e788585bdc..dace736e529 100644 --- a/lib/runtime-c-api/src/import/mod.rs +++ b/lib/runtime-c-api/src/import/mod.rs @@ -698,7 +698,7 @@ pub unsafe extern "C" fn wasmer_import_func_new( /// This function never returns otherwise. #[no_mangle] #[allow(clippy::cast_ptr_alignment)] -pub unsafe extern "C" fn wasmer_import_trap( +pub unsafe extern "C" fn wasmer_trap( ctx: *const wasmer_instance_context_t, error_message: *const c_char, ) -> wasmer_result_t { From 4cdf868a0b9c4e46728ca6f6b9a6a3eaceaca2dd Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 15 Jan 2020 08:40:36 +0100 Subject: [PATCH 15/19] doc(runtime-c-api) Explain why code is unreachable in `wasmer_trap`. --- lib/runtime-c-api/src/import/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/runtime-c-api/src/import/mod.rs b/lib/runtime-c-api/src/import/mod.rs index dace736e529..a2044c06041 100644 --- a/lib/runtime-c-api/src/import/mod.rs +++ b/lib/runtime-c-api/src/import/mod.rs @@ -725,6 +725,12 @@ pub unsafe extern "C" fn wasmer_trap( .runnable_module .do_early_trap(Box::new(error_message)); // never returns + // cbindgen does not generate a binding for a function that + // returns `!`. Since we also need to error in some cases, the + // output type of `wasmer_trap` is `wasmer_result_t`. But the OK + // case is not reachable because `do_early_trap` never + // returns. That's a compromise to satisfy the Rust type system, + // cbindgen, and get an acceptable clean code. #[allow(unreachable_code)] wasmer_result_t::WASMER_OK } From bcbde69694d729839402e82bb6440be891a4f3f8 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 15 Jan 2020 08:41:37 +0100 Subject: [PATCH 16/19] doc(runtime-core) Fix a typo. --- lib/runtime-core/src/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index cd4b8bafa28..4596ffb6079 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -219,7 +219,7 @@ pub trait RunnableModule: Send + Sync { } /// A wasm trampoline contains the necessary data to dynamically call an exported wasm function. - /// Given a particular signature index, we are returning a trampoline that is matched with that + /// Given a particular signature index, we return a trampoline that is matched with that /// signature and an invoke function that can call the trampoline. fn get_trampoline(&self, info: &ModuleInfo, sig_index: SigIndex) -> Option; From cd16a7d1a76866172b8a3553eb4ea043de885171 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 15 Jan 2020 08:42:17 +0100 Subject: [PATCH 17/19] chore(runtime-c-api) Update C/C++ headers. --- lib/runtime-c-api/wasmer.h | 36 ++++++++++++++++++------------------ lib/runtime-c-api/wasmer.hh | 32 ++++++++++++++++---------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 154e58af732..c085f8d841a 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -675,24 +675,6 @@ wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer */ wasmer_import_object_t *wasmer_import_object_new(void); -/** - * Stop the execution of a host function, aka imported function. The - * function must be used _only_ inside a host function. - * - * The pointer to `wasmer_instance_context_t` is received by the host - * function as its first argument. Just passing it to `ctx` is fine. - * - * The error message must have a greater lifetime than the host - * function itself since the error is read outside the host function - * with `wasmer_last_error_message`. - * - * This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or - * `error_message` are null. - * - * This function never returns otherwise. - */ -wasmer_result_t wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); - /** * Calls an instances exported function by `name` with the provided parameters. * Results are set using the provided `results` pointer. @@ -998,6 +980,24 @@ const wasmer_trampoline_callable_t *wasmer_trampoline_buffer_get_trampoline(cons void *wasmer_trampoline_get_context(void); #endif +/** + * Stop the execution of a host function, aka imported function. The + * function must be used _only_ inside a host function. + * + * The pointer to `wasmer_instance_context_t` is received by the host + * function as its first argument. Just passing it to `ctx` is fine. + * + * The error message must have a greater lifetime than the host + * function itself since the error is read outside the host function + * with `wasmer_last_error_message`. + * + * This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or + * `error_message` are null. + * + * This function never returns otherwise. + */ +wasmer_result_t wasmer_trap(const wasmer_instance_context_t *ctx, const char *error_message); + /** * Returns true for valid wasm bytes and false for invalid bytes */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index aad45957004..12bc0a9b8a9 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -542,22 +542,6 @@ wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer /// See also `wasmer_import_object_append` wasmer_import_object_t *wasmer_import_object_new(); -/// Stop the execution of a host function, aka imported function. The -/// function must be used _only_ inside a host function. -/// -/// The pointer to `wasmer_instance_context_t` is received by the host -/// function as its first argument. Just passing it to `ctx` is fine. -/// -/// The error message must have a greater lifetime than the host -/// function itself since the error is read outside the host function -/// with `wasmer_last_error_message`. -/// -/// This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or -/// `error_message` are null. -/// -/// This function never returns otherwise. -wasmer_result_t wasmer_import_trap(const wasmer_instance_context_t *ctx, const char *error_message); - /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. /// @@ -793,6 +777,22 @@ const wasmer_trampoline_callable_t *wasmer_trampoline_buffer_get_trampoline(cons void *wasmer_trampoline_get_context(); #endif +/// Stop the execution of a host function, aka imported function. The +/// function must be used _only_ inside a host function. +/// +/// The pointer to `wasmer_instance_context_t` is received by the host +/// function as its first argument. Just passing it to `ctx` is fine. +/// +/// The error message must have a greater lifetime than the host +/// function itself since the error is read outside the host function +/// with `wasmer_last_error_message`. +/// +/// This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or +/// `error_message` are null. +/// +/// This function never returns otherwise. +wasmer_result_t wasmer_trap(const wasmer_instance_context_t *ctx, const char *error_message); + /// Returns true for valid wasm bytes and false for invalid bytes bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len); From f4ae606006ac7a7f74a39c435ecc2873588079f5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 15 Jan 2020 08:46:12 +0100 Subject: [PATCH 18/19] doc(changelog) Update #1133. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed7308ffd5d..7a25fe171cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## **[Unreleased]** -- [#1133](https://github.com/wasmerio/wasmer/pull/1133) New `wasmer_import_trap` function in the C API, to properly error from within a host function +- [#1133](https://github.com/wasmerio/wasmer/pull/1133) New `wasmer_trap` function in the C API, to properly error from within a host function - [#1147](https://github.com/wasmerio/wasmer/pull/1147) Remove `log` and `trace` macros from `wasmer-runtime-core`, remove `debug` and `trace` features from `wasmer-*` crates, use the `log` crate for logging and use `fern` in the Wasmer CLI binary to output log messages. Colorized output will be enabled automatically if printing to a terminal, to force colorization on or off, set the `WASMER_COLOR` environment variable to `true` or `false`. - [#1128](https://github.com/wasmerio/wasmer/pull/1128) Fix a crash when a host function is missing and the `allow_missing_functions` flag is enabled - [#1099](https://github.com/wasmerio/wasmer/pull/1099) Remove `backend::Backend` from `wasmer_runtime_core` From fb06ee33e321534fcacd6fa7b48819ba867a5ec5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 15 Jan 2020 08:47:52 +0100 Subject: [PATCH 19/19] test(runtime-c-api) Rename `wasmer_import_trap` to `wasmer_trap`. --- lib/runtime-c-api/tests/test-import-trap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/runtime-c-api/tests/test-import-trap.c b/lib/runtime-c-api/tests/test-import-trap.c index ab11bcca9bd..0e28208eccc 100644 --- a/lib/runtime-c-api/tests/test-import-trap.c +++ b/lib/runtime-c-api/tests/test-import-trap.c @@ -6,9 +6,9 @@ static const char *trap_error_message = "Hello"; -void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len) +void print_str(wasmer_instance_context_t *ctx, int32_t _ptr, int32_t _len) { - wasmer_import_trap(ctx, trap_error_message); + wasmer_trap(ctx, trap_error_message); } int main()