From 3ee2e20c1bdf218771ab7ca370b459dddcae29d6 Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Mon, 29 Mar 2021 12:43:03 +0200 Subject: [PATCH] capi: Add rich error reporting to fizzy_instantiate --- bindings/rust/src/lib.rs | 1 + include/fizzy/fizzy.h | 2 +- lib/fizzy/capi.cpp | 4 +- test/unittests/capi_test.cpp | 88 +++++++++++++++++++++--------------- 4 files changed, 56 insertions(+), 39 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 4e94196eab..e17fddf555 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -110,6 +110,7 @@ impl Module { std::ptr::null(), std::ptr::null(), 0, + std::ptr::null_mut(), ) }; // Forget Module (and avoid calling drop) because it has been consumed by instantiate (even if it failed). diff --git a/include/fizzy/fizzy.h b/include/fizzy/fizzy.h index 8a65eeadcb..084213f7a3 100644 --- a/include/fizzy/fizzy.h +++ b/include/fizzy/fizzy.h @@ -403,7 +403,7 @@ bool fizzy_module_has_start_function(const FizzyModule* module); FizzyInstance* fizzy_instantiate(const FizzyModule* module, const FizzyExternalFunction* imported_functions, size_t imported_functions_size, const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory, - const FizzyExternalGlobal* imported_globals, size_t imported_globals_size); + const FizzyExternalGlobal* imported_globals, size_t imported_globals_size, FizzyError* error); /// Instantiate a module resolving imported functions. /// diff --git a/lib/fizzy/capi.cpp b/lib/fizzy/capi.cpp index a257e95fa7..464796e93d 100644 --- a/lib/fizzy/capi.cpp +++ b/lib/fizzy/capi.cpp @@ -586,7 +586,7 @@ bool fizzy_module_has_start_function(const FizzyModule* module) FizzyInstance* fizzy_instantiate(const FizzyModule* module, const FizzyExternalFunction* imported_functions, size_t imported_functions_size, const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory, - const FizzyExternalGlobal* imported_globals, size_t imported_globals_size) + const FizzyExternalGlobal* imported_globals, size_t imported_globals_size, FizzyError* error) { try { @@ -598,10 +598,12 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module, auto instance = fizzy::instantiate(std::unique_ptr(unwrap(module)), std::move(functions), std::move(table), std::move(memory), std::move(globals)); + set_success(error); return wrap(instance.release()); } catch (...) { + set_error(error); return nullptr; } } diff --git a/test/unittests/capi_test.cpp b/test/unittests/capi_test.cpp index f49cb88164..5b2e1efafd 100644 --- a/test/unittests/capi_test.cpp +++ b/test/unittests/capi_test.cpp @@ -402,7 +402,7 @@ TEST(capi, export_name_after_instantiate) const auto export0 = fizzy_get_export_description(module, 0); EXPECT_STREQ(export0.name, "fn"); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); EXPECT_NE(instance, nullptr); EXPECT_STREQ(export0.name, "fn"); @@ -456,7 +456,7 @@ TEST(capi, find_exported_function) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); FizzyExternalFunction function; @@ -494,7 +494,7 @@ TEST(capi, find_exported_table) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); FizzyExternalTable table; @@ -524,7 +524,7 @@ TEST(capi, find_exported_table_no_max) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); FizzyExternalTable table; @@ -553,7 +553,7 @@ TEST(capi, find_exported_memory) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); FizzyExternalMemory memory; @@ -583,7 +583,7 @@ TEST(capi, find_exported_memory_no_max) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); FizzyExternalMemory memory; @@ -612,7 +612,7 @@ TEST(capi, find_exported_global) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); FizzyExternalGlobal global; @@ -658,12 +658,21 @@ TEST(capi, has_start_function) TEST(capi, instantiate) { uint8_t wasm_prefix[]{0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00}; - auto module = fizzy_parse(wasm_prefix, sizeof(wasm_prefix), nullptr); + const auto* module = fizzy_parse(wasm_prefix, sizeof(wasm_prefix), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); EXPECT_NE(instance, nullptr); + const auto* module_clone = fizzy_clone_module(module); + ASSERT_NE(module_clone, nullptr); + fizzy_free_instance(instance); + + FizzyError success; + instance = fizzy_instantiate(module_clone, nullptr, 0, nullptr, nullptr, nullptr, 0, &success); + EXPECT_NE(instance, nullptr); + EXPECT_EQ(success.code, FIZZY_SUCCESS); + EXPECT_STREQ(success.message, ""); fizzy_free_instance(instance); } @@ -676,14 +685,15 @@ TEST(capi, instantiate_imported_function) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0), nullptr); + EXPECT_EQ( + fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr), nullptr); module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); FizzyExternalFunction host_funcs[] = {{{FizzyValueTypeI32, nullptr, 0}, NullFn, nullptr}}; - auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); @@ -718,7 +728,7 @@ TEST(capi, instantiate_imported_globals) {&g2, {FizzyValueTypeI64, false}}, {&g3, {FizzyValueTypeF32, false}}, {&g4, {FizzyValueTypeF64, true}}}; - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals, 4); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals, 4, nullptr); EXPECT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 0, nullptr), CResult(42_u32)); @@ -731,12 +741,14 @@ TEST(capi, instantiate_imported_globals) // No globals provided. module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0), nullptr); + EXPECT_EQ( + fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr), nullptr); // Not enough globals provided. module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals, 3), nullptr); + EXPECT_EQ( + fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals, 3, nullptr), nullptr); // Incorrect order or globals. module = fizzy_parse(wasm.data(), wasm.size(), nullptr); @@ -746,7 +758,8 @@ TEST(capi, instantiate_imported_globals) {&g2, {FizzyValueTypeI64, false}}, {&g4, {FizzyValueTypeF64, true}}, {&g3, {FizzyValueTypeF32, false}}}; - EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals_incorrect_order, 4), + EXPECT_EQ(fizzy_instantiate( + module, nullptr, 0, nullptr, nullptr, globals_incorrect_order, 4, nullptr), nullptr); // Global type mismatch. @@ -758,7 +771,8 @@ TEST(capi, instantiate_imported_globals) {&g4, {FizzyValueTypeF64, true}}}; EXPECT_EQ( - fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals_type_mismatch, 4), nullptr); + fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals_type_mismatch, 4, nullptr), + nullptr); } TEST(capi, instantiate_twice) @@ -767,13 +781,13 @@ TEST(capi, instantiate_twice) const auto* module1 = fizzy_parse(wasm_prefix, sizeof(wasm_prefix), nullptr); ASSERT_NE(module1, nullptr); - auto* instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto* instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); EXPECT_NE(instance1, nullptr); const auto* module2 = fizzy_clone_module(module1); ASSERT_NE(module2, nullptr); - auto* instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto* instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); EXPECT_NE(instance2, nullptr); EXPECT_NE(instance1, instance2); @@ -1053,7 +1067,7 @@ TEST(capi, get_instance_module) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); auto instance_module = fizzy_get_instance_module(instance); @@ -1073,7 +1087,7 @@ TEST(capi, memory_access_no_memory) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); EXPECT_EQ(fizzy_get_instance_memory_data(instance), nullptr); @@ -1091,7 +1105,7 @@ TEST(capi, memory_access_empty_memory) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); EXPECT_NE(fizzy_get_instance_memory_data(instance), nullptr); @@ -1116,7 +1130,7 @@ TEST(capi, memory_access) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); uint8_t* memory = fizzy_get_instance_memory_data(instance); @@ -1150,7 +1164,7 @@ TEST(capi, imported_memory_access) auto* module_memory = fizzy_parse(wasm_memory.data(), wasm_memory.size(), nullptr); ASSERT_NE(module_memory, nullptr); auto* instance_memory = - fizzy_instantiate(module_memory, nullptr, 0, nullptr, nullptr, nullptr, 0); + fizzy_instantiate(module_memory, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance_memory, nullptr); FizzyExternalMemory memory; @@ -1168,7 +1182,7 @@ TEST(capi, imported_memory_access) auto* module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto* instance = fizzy_instantiate(module, nullptr, 0, nullptr, &memory, nullptr, 0); + auto* instance = fizzy_instantiate(module, nullptr, 0, nullptr, &memory, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); EXPECT_EQ(fizzy_execute(instance, 0, nullptr).value.i32, 0x221100); @@ -1205,7 +1219,7 @@ TEST(capi, execute) auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 0, nullptr), CResult()); @@ -1244,7 +1258,7 @@ TEST(capi, execute_with_host_function) }, nullptr}}; - auto instance = fizzy_instantiate(module, host_funcs, 2, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, host_funcs, 2, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 0, nullptr), CResult(42_u32)); @@ -1274,7 +1288,7 @@ TEST(capi, imported_function_traps) }, nullptr}}; - auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CTraps()); @@ -1303,7 +1317,7 @@ TEST(capi, imported_function_void) }, &called}}; - auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CResult()); @@ -1327,7 +1341,7 @@ TEST(capi, imported_function_from_another_module) "0061736d0100000001070160027f7f017f030201000707010373756200000a09010700200020016b0b"); auto module1 = fizzy_parse(bin1.data(), bin1.size(), nullptr); ASSERT_NE(module1, nullptr); - auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance1, nullptr); FizzyExternalFunction func; @@ -1350,7 +1364,7 @@ TEST(capi, imported_function_from_another_module) auto module2 = fizzy_parse(bin2.data(), bin2.size(), nullptr); ASSERT_NE(module2, nullptr); - auto instance2 = fizzy_instantiate(module2, &func, 1, nullptr, nullptr, nullptr, 0); + auto instance2 = fizzy_instantiate(module2, &func, 1, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance2, nullptr); FizzyValue args[] = {{44}, {2}}; @@ -1373,7 +1387,7 @@ TEST(capi, imported_table_from_another_module) "0400412a0b"); auto module1 = fizzy_parse(bin1.data(), bin1.size(), nullptr); ASSERT_NE(module1, nullptr); - auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance1, nullptr); /* wat2wasm @@ -1391,7 +1405,7 @@ TEST(capi, imported_table_from_another_module) FizzyExternalTable table; ASSERT_TRUE(fizzy_find_exported_table(instance1, "t", &table)); - auto instance2 = fizzy_instantiate(module2, nullptr, 0, &table, nullptr, nullptr, 0); + auto instance2 = fizzy_instantiate(module2, nullptr, 0, &table, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance2, nullptr); EXPECT_THAT(fizzy_execute(instance2, 0, nullptr), CResult(42_u32)); @@ -1409,7 +1423,7 @@ TEST(capi, imported_memory_from_another_module) const auto bin1 = from_hex("0061736d010000000503010001070501016d02000b080100410a0b02aaff"); auto module1 = fizzy_parse(bin1.data(), bin1.size(), nullptr); ASSERT_NE(module1, nullptr); - auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance1, nullptr); /* wat2wasm @@ -1427,7 +1441,7 @@ TEST(capi, imported_memory_from_another_module) FizzyExternalMemory memory; ASSERT_TRUE(fizzy_find_exported_memory(instance1, "m", &memory)); - auto instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, &memory, nullptr, 0); + auto instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, &memory, nullptr, 0, nullptr); ASSERT_NE(instance2, nullptr); EXPECT_THAT(fizzy_execute(instance2, 0, nullptr), CResult(0x00ffaa00_u32)); @@ -1444,7 +1458,7 @@ TEST(capi, imported_global_from_another_module) const auto bin1 = from_hex("0061736d010000000606017f00412a0b07050101670300"); auto module1 = fizzy_parse(bin1.data(), bin1.size(), nullptr); ASSERT_NE(module1, nullptr); - auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0); + auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr); ASSERT_NE(instance1, nullptr); /* wat2wasm @@ -1463,7 +1477,7 @@ TEST(capi, imported_global_from_another_module) FizzyExternalGlobal global; ASSERT_TRUE(fizzy_find_exported_global(instance1, "g", &global)); - auto instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, nullptr, &global, 1); + auto instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, nullptr, &global, 1, nullptr); ASSERT_NE(instance2, nullptr); EXPECT_THAT(fizzy_execute(instance2, 0, nullptr), CResult(42_u32)); @@ -1730,7 +1744,7 @@ TEST(capi, import_name_after_instantiate) FizzyExternalFunction host_funcs[] = {{{FizzyValueTypeI32, nullptr, 0}, NullFn, nullptr}}; - auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0); + auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr); EXPECT_NE(instance, nullptr); EXPECT_STREQ(import0.module, "m");