@@ -3908,7 +3908,7 @@ static void validateTags(Module& module, ValidationInfo& info) {
39083908 }
39093909}
39103910
3911- static void validateModule (Module& module , ValidationInfo& info) {
3911+ static void validateStart (Module& module , ValidationInfo& info) {
39123912 // start
39133913 if (module .start .is ()) {
39143914 auto func = module .getFunctionOrNull (module .start );
@@ -3924,6 +3924,59 @@ static void validateModule(Module& module, ValidationInfo& info) {
39243924 }
39253925}
39263926
3927+ namespace {
3928+ template <typename T, typename U>
3929+ void validateModuleMap (Module& module ,
3930+ ValidationInfo& info,
3931+ T& list,
3932+ U getter,
3933+ const std::string& kind) {
3934+ // Given a list of module elements (like exports or globals), see that we can
3935+ // get the items using the getter (getExportorNull, etc.). The getter uses the
3936+ // lookup map internally, so this validates that they contain all items in
3937+ // the list.
3938+ for (auto & item : list) {
3939+ auto * ptr = (module .*getter)(item->name );
3940+ if (!ptr) {
3941+ info.fail (kind + " must be found (use updateMaps)" , item->name , nullptr );
3942+ } else {
3943+ info.shouldBeEqual (item->name ,
3944+ ptr->name ,
3945+ item->name ,
3946+ " getter must return the correct item" );
3947+ }
3948+ }
3949+
3950+ // TODO: Also check there is nothing extraneous in the map, but that would
3951+ // require inspecting private fields of Module.
3952+ }
3953+ } // anonymous namespace
3954+
3955+ static void validateModuleMaps (Module& module , ValidationInfo& info) {
3956+ // Module maps should be up to date.
3957+ validateModuleMap (
3958+ module , info, module .exports , &Module::getExportOrNull, " Export" );
3959+ validateModuleMap (
3960+ module , info, module .functions , &Module::getFunctionOrNull, " Function" );
3961+ validateModuleMap (
3962+ module , info, module .globals , &Module::getGlobalOrNull, " Global" );
3963+ validateModuleMap (module , info, module .tags , &Module::getTagOrNull, " Tag" );
3964+ validateModuleMap (module ,
3965+ info,
3966+ module .elementSegments ,
3967+ &Module::getElementSegmentOrNull,
3968+ " ElementSegment" );
3969+ validateModuleMap (
3970+ module , info, module .memories , &Module::getMemoryOrNull, " Memory" );
3971+ validateModuleMap (module ,
3972+ info,
3973+ module .dataSegments ,
3974+ &Module::getDataSegmentOrNull,
3975+ " DataSegment" );
3976+ validateModuleMap (
3977+ module , info, module .tables , &Module::getTableOrNull, " Table" );
3978+ }
3979+
39273980static void validateFeatures (Module& module , ValidationInfo& info) {
39283981 if (module .features .hasGC ()) {
39293982 info.shouldBeTrue (module .features .hasReferenceTypes (),
@@ -4004,7 +4057,8 @@ bool WasmValidator::validate(Module& module, Flags flags) {
40044057 validateDataSegments (module , info);
40054058 validateTables (module , info);
40064059 validateTags (module , info);
4007- validateModule (module , info);
4060+ validateStart (module , info);
4061+ validateModuleMaps (module , info);
40084062 validateFeatures (module , info);
40094063 if (info.closedWorld ) {
40104064 validateClosedWorldInterface (module , info);
0 commit comments