Skip to content

Commit a62544f

Browse files
committed
capi: Add rich error reporting to fizzy_resolve_instantiate
1 parent 6240e56 commit a62544f

File tree

4 files changed

+67
-20
lines changed

4 files changed

+67
-20
lines changed

include/fizzy/fizzy.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,8 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
441441
/// @param imported_globals Pointer to the imported globals array. Can be NULL iff
442442
/// @p imported_globals_size equals 0.
443443
/// @param imported_globals_size Size of the imported global array. Can be zero.
444+
/// @param error Pointer to store detailed error information at. Can be NULL
445+
/// if error information is not required.
444446
/// @return non-NULL pointer to instance in case of success,
445447
/// NULL otherwise.
446448
///
@@ -462,7 +464,7 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
462464
FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* module,
463465
const FizzyImportedFunction* imported_functions, size_t imported_functions_size,
464466
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
465-
const FizzyImportedGlobal* imported_globals, size_t imported_globals_size);
467+
const FizzyImportedGlobal* imported_globals, size_t imported_globals_size, FizzyError* error);
466468

467469
/// Free resources associated with the instance.
468470
///

lib/fizzy/capi.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
627627
FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* c_module,
628628
const FizzyImportedFunction* c_imported_functions, size_t imported_functions_size,
629629
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
630-
const FizzyImportedGlobal* c_imported_globals, size_t imported_globals_size)
630+
const FizzyImportedGlobal* c_imported_globals, size_t imported_globals_size, FizzyError* error)
631631
{
632632
try
633633
{
@@ -643,10 +643,12 @@ FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* c_module,
643643
auto instance = fizzy::instantiate(std::move(module), std::move(resolved_imports),
644644
std::move(table), std::move(memory), std::move(resolved_globals));
645645

646+
set_success(error);
646647
return wrap(instance.release());
647648
}
648649
catch (...)
649650
{
651+
set_error_from_current_exception(error);
650652
return nullptr;
651653
}
652654
}

test/unittests/capi_test.cpp

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -837,18 +837,35 @@ TEST(capi, resolve_instantiate_no_imports)
837837
auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
838838
ASSERT_NE(module, nullptr);
839839

840-
auto instance = fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0);
840+
// Success omitting FizzyError argument.
841+
auto instance =
842+
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr);
843+
EXPECT_NE(instance, nullptr);
844+
845+
fizzy_free_instance(instance);
846+
847+
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
848+
ASSERT_NE(module, nullptr);
849+
850+
// Success with FizzyError argument.
851+
FizzyError success;
852+
instance =
853+
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, &success);
841854
EXPECT_NE(instance, nullptr);
855+
EXPECT_EQ(success.code, FIZZY_SUCCESS);
856+
EXPECT_STREQ(success.message, "");
842857

843858
fizzy_free_instance(instance);
844859

845860
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
846861
ASSERT_NE(module, nullptr);
847862

863+
// providing unnecessary import
848864
FizzyImportedFunction host_funcs[] = {
849865
{"mod", "foo", {{FizzyValueTypeVoid, nullptr, 0}, NullFn, nullptr}}};
850866

851-
instance = fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0);
867+
instance =
868+
fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr);
852869
EXPECT_NE(instance, nullptr);
853870

854871
fizzy_free_instance(instance);
@@ -873,7 +890,20 @@ TEST(capi, resolve_instantiate_functions)
873890
FizzyValue mod1g1value{42};
874891
FizzyImportedGlobal mod1g1 = {"mod1", "g1", {&mod1g1value, {FizzyValueTypeI32, false}}};
875892

876-
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, &mod1g1, 1), nullptr);
893+
// no functions provided
894+
// Error omitting FizzyError argument.
895+
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, &mod1g1, 1, nullptr),
896+
nullptr);
897+
898+
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
899+
ASSERT_NE(module, nullptr);
900+
901+
// Error with FizzyError argument.
902+
FizzyError error;
903+
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, &mod1g1, 1, &error),
904+
nullptr);
905+
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION_FAILED);
906+
EXPECT_STREQ(error.message, "imported function mod1.foo1 is required");
877907

878908
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
879909
ASSERT_NE(module, nullptr);
@@ -898,7 +928,8 @@ TEST(capi, resolve_instantiate_functions)
898928
FizzyImportedFunction host_funcs[] = {{"mod1", "foo1", mod1foo1}, {"mod1", "foo2", mod1foo2},
899929
{"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}};
900930

901-
auto instance = fizzy_resolve_instantiate(module, host_funcs, 4, nullptr, nullptr, &mod1g1, 1);
931+
auto instance =
932+
fizzy_resolve_instantiate(module, host_funcs, 4, nullptr, nullptr, &mod1g1, 1, nullptr);
902933
ASSERT_NE(instance, nullptr);
903934

904935
FizzyValue arg;
@@ -914,8 +945,8 @@ TEST(capi, resolve_instantiate_functions)
914945
ASSERT_NE(module, nullptr);
915946
FizzyImportedFunction host_funcs_reordered[] = {{"mod1", "foo2", mod1foo2},
916947
{"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}, {"mod1", "foo1", mod1foo1}};
917-
instance =
918-
fizzy_resolve_instantiate(module, host_funcs_reordered, 4, nullptr, nullptr, &mod1g1, 1);
948+
instance = fizzy_resolve_instantiate(
949+
module, host_funcs_reordered, 4, nullptr, nullptr, &mod1g1, 1, nullptr);
919950
EXPECT_NE(instance, nullptr);
920951
fizzy_free_instance(instance);
921952

@@ -925,15 +956,19 @@ TEST(capi, resolve_instantiate_functions)
925956
FizzyImportedFunction host_funcs_extra[] = {{"mod1", "foo1", mod1foo1},
926957
{"mod1", "foo2", mod1foo2}, {"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2},
927958
{"mod3", "foo1", mod1foo1}};
928-
instance = fizzy_resolve_instantiate(module, host_funcs_extra, 4, nullptr, nullptr, &mod1g1, 1);
959+
instance = fizzy_resolve_instantiate(
960+
module, host_funcs_extra, 4, nullptr, nullptr, &mod1g1, 1, nullptr);
929961
EXPECT_NE(instance, nullptr);
930962
fizzy_free_instance(instance);
931963

932964
// not enough functions
933965
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
934966
ASSERT_NE(module, nullptr);
935967
EXPECT_EQ(
936-
fizzy_resolve_instantiate(module, host_funcs, 3, nullptr, nullptr, &mod1g1, 1), nullptr);
968+
fizzy_resolve_instantiate(module, host_funcs, 3, nullptr, nullptr, &mod1g1, 1, &error),
969+
nullptr);
970+
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION_FAILED);
971+
EXPECT_STREQ(error.message, "imported function mod2.foo2 is required");
937972
}
938973

939974
TEST(capi, resolve_instantiate_function_duplicate)
@@ -954,7 +989,8 @@ TEST(capi, resolve_instantiate_function_duplicate)
954989
FizzyExternalFunction mod1foo1 = {{FizzyValueTypeI32, nullptr, 0}, host_fn, nullptr};
955990
FizzyImportedFunction host_funcs[] = {{"mod1", "foo1", mod1foo1}};
956991

957-
auto instance = fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0);
992+
auto instance =
993+
fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr);
958994
ASSERT_NE(instance, nullptr);
959995

960996
EXPECT_THAT(fizzy_execute(instance, 0, nullptr), CResult(42_u32));
@@ -983,7 +1019,11 @@ TEST(capi, resolve_instantiate_globals)
9831019
auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
9841020
ASSERT_NE(module, nullptr);
9851021

986-
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0), nullptr);
1022+
FizzyError error;
1023+
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, &error),
1024+
nullptr);
1025+
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION_FAILED);
1026+
EXPECT_STREQ(error.message, "imported function mod1.foo1 is required");
9871027

9881028
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
9891029
ASSERT_NE(module, nullptr);
@@ -1007,7 +1047,7 @@ TEST(capi, resolve_instantiate_globals)
10071047
{"mod2", "g1", mod2g1}, {"mod2", "g2", mod2g2}};
10081048

10091049
auto instance =
1010-
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals, 4);
1050+
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals, 4, nullptr);
10111051
ASSERT_NE(instance, nullptr);
10121052

10131053
EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CResult(42_u32));
@@ -1023,7 +1063,7 @@ TEST(capi, resolve_instantiate_globals)
10231063
FizzyImportedGlobal host_globals_reordered[] = {{"mod1", "g2", mod1g2}, {"mod2", "g1", mod2g1},
10241064
{"mod2", "g2", mod2g2}, {"mod1", "g1", mod1g1}};
10251065
instance = fizzy_resolve_instantiate(
1026-
module, &mod1foo1, 1, nullptr, nullptr, host_globals_reordered, 4);
1066+
module, &mod1foo1, 1, nullptr, nullptr, host_globals_reordered, 4, nullptr);
10271067
EXPECT_NE(instance, nullptr);
10281068

10291069
EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CResult(42_u32));
@@ -1038,8 +1078,8 @@ TEST(capi, resolve_instantiate_globals)
10381078
ASSERT_NE(module, nullptr);
10391079
FizzyImportedGlobal host_globals_extra[] = {{"mod1", "g1", mod1g1}, {"mod1", "g2", mod1g2},
10401080
{"mod2", "g1", mod2g1}, {"mod2", "g2", mod2g2}, {"mod3", "g1", mod1g1}};
1041-
instance =
1042-
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 4);
1081+
instance = fizzy_resolve_instantiate(
1082+
module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 4, nullptr);
10431083
EXPECT_NE(instance, nullptr);
10441084

10451085
EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CResult(42_u32));
@@ -1052,9 +1092,11 @@ TEST(capi, resolve_instantiate_globals)
10521092
// not enough globals
10531093
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
10541094
ASSERT_NE(module, nullptr);
1055-
EXPECT_EQ(
1056-
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 3),
1095+
EXPECT_EQ(fizzy_resolve_instantiate(
1096+
module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 3, &error),
10571097
nullptr);
1098+
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION_FAILED);
1099+
EXPECT_STREQ(error.message, "imported global mod2.g2 is required");
10581100
}
10591101

10601102
TEST(capi, resolve_instantiate_global_duplicate)
@@ -1077,7 +1119,7 @@ TEST(capi, resolve_instantiate_global_duplicate)
10771119
FizzyImportedGlobal host_globals[] = {{"mod1", "g1", mod1g1}};
10781120

10791121
auto instance =
1080-
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, host_globals, 1);
1122+
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, host_globals, 1, nullptr);
10811123
ASSERT_NE(instance, nullptr);
10821124

10831125
EXPECT_THAT(fizzy_execute(instance, 0, nullptr), CResult(42_u32));

test/utils/fizzy_c_engine.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ bool FizzyCEngine::instantiate(bytes_view wasm_binary)
6565
FizzyValueType inputs[] = {FizzyValueTypeI32, FizzyValueTypeI32};
6666
FizzyImportedFunction imports[] = {
6767
{"env", "adler32", {{FizzyValueTypeI32, inputs, 2}, env_adler32, nullptr}}};
68-
m_instance.reset(fizzy_resolve_instantiate(module, imports, 1, nullptr, nullptr, nullptr, 0));
68+
m_instance.reset(
69+
fizzy_resolve_instantiate(module, imports, 1, nullptr, nullptr, nullptr, 0, nullptr));
6970

7071
return (m_instance != nullptr);
7172
}

0 commit comments

Comments
 (0)