diff --git a/lib/fizzy/parser.cpp b/lib/fizzy/parser.cpp index 9917a2082..a5d6ae90c 100644 --- a/lib/fizzy/parser.cpp +++ b/lib/fizzy/parser.cpp @@ -493,6 +493,12 @@ Module parse(bytes_view input) } } + for (const auto type_idx : module.funcsec) + { + if (type_idx >= module.typesec.size()) + throw validation_error{"invalid function type index"}; + } + if (module.tablesec.size() > 1) throw validation_error{"too many table sections (at most one is allowed)"}; @@ -533,9 +539,7 @@ Module parse(bytes_view input) module.codesec.reserve(code_binaries.size()); for (size_t i = 0; i < code_binaries.size(); ++i) { - const auto type_idx = module.funcsec[i]; - if (type_idx >= module.typesec.size()) - throw validation_error{"invalid function type index"}; + assert(module.funcsec[i] < module.typesec.size()); module.codesec.emplace_back(parse_code(code_binaries[i], module)); } diff --git a/test/unittests/parser_expr_test.cpp b/test/unittests/parser_expr_test.cpp index 299249a78..4c158f286 100644 --- a/test/unittests/parser_expr_test.cpp +++ b/test/unittests/parser_expr_test.cpp @@ -349,4 +349,16 @@ TEST(parser_expr, call_1arg_1result) const auto module = parse(wasm); ASSERT_EQ(module.codesec.size(), 2); -} \ No newline at end of file +} + +TEST(parser_expr, call_nonexisting_typeidx) +{ + // This creates a wasm module where code[0] has a call instruction calling function[1] which + // has invalid type_idx 1. + // wat2wasm cannot be used as there is no way to have invalid type_idx in WAT form. + const auto wasm = bytes{wasm_prefix} + make_section(1, make_vec({"600000"_bytes})) + + make_section(3, make_vec({"00"_bytes, "01"_bytes})) + + make_section(10, make_vec({"040010010b"_bytes, "02000b"_bytes})); + + EXPECT_THROW_MESSAGE(parse(wasm), validation_error, "invalid function type index"); +} diff --git a/test/unittests/parser_test.cpp b/test/unittests/parser_test.cpp index 2712f3264..fc15bbff4 100644 --- a/test/unittests/parser_test.cpp +++ b/test/unittests/parser_test.cpp @@ -436,8 +436,10 @@ TEST(parser, function_section_end_out_of_bounds) TEST(parser, function_section_without_code) { + const auto type_section = make_vec({make_functype({}, {})}); const auto function_section = "0100"_bytes; - const auto bin = bytes{wasm_prefix} + make_section(3, function_section); + const auto bin = + bytes{wasm_prefix} + make_section(1, type_section) + make_section(3, function_section); EXPECT_THROW_MESSAGE(parse(bin), parser_error, "malformed binary: number of function and code entries must match"); }