@@ -86,7 +86,7 @@ class Flow {
8686 }
8787
8888 Literals values;
89- Name breakTo; // if non-null, a break is going on
89+ Name breakTo; // if non-null, a break is going on
9090 Tag* suspendTag = nullptr ; // if non-null, breakTo must be SUSPEND_FLOW, and
9191 // this is the tag being suspended
9292
@@ -2658,6 +2658,8 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
26582658
26592659 virtual void trap (const char * why) { WASM_UNREACHABLE (" unimp" ); }
26602660
2661+ virtual void trap (std::string_view why) { WASM_UNREACHABLE (" unimp" ); }
2662+
26612663 virtual void hostLimit (const char * why) { WASM_UNREACHABLE (" unimp" ); }
26622664
26632665 virtual void throwException (const WasmException& exn) {
@@ -2937,6 +2939,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
29372939 Index oldSize,
29382940 Index newSize) = 0;
29392941 virtual void trap (const char * why) = 0;
2942+ virtual void trap (std::string_view why) { trap (std::string (why).c_str ()); }
29402943 virtual void hostLimit (const char * why) = 0;
29412944 virtual void throwException (const WasmException& exn) = 0;
29422945 // Get the Tag instance for a tag implemented in the host, that is, not
@@ -3178,6 +3181,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
31783181 // initialize the rest of the external interface
31793182 externalInterface->init (wasm, *self ());
31803183
3184+ validateImports ();
3185+
31813186 initializeTableContents ();
31823187 initializeMemoryContents ();
31833188
@@ -3269,6 +3274,61 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
32693274 Name name;
32703275 };
32713276
3277+ // Trap if types don't match between all imports and their corresponding
3278+ // exports. Imported memories must also be a subtype of their export.
3279+ void validateImports () {
3280+ ModuleUtils::iterImportable (
3281+ wasm,
3282+ [this ](ExternalKind kind,
3283+ std::variant<Function*, Memory*, Tag*, Global*, Table*> import ) {
3284+ Importable* importable = std::visit (
3285+ [](const auto & import ) -> Importable* { return import ; }, import );
3286+
3287+ SubType* importedInstance =
3288+ linkedInstances.at (importable->module ).get ();
3289+ Export* export_ =
3290+ importedInstance->wasm .getExportOrNull (importable->base );
3291+
3292+ // In case functions are imported from the special "spectest" module,
3293+ // don't check them here, since they won't show up in exports.
3294+ if (!export_ && kind != ExternalKind::Function) {
3295+ std::cerr << " importedinstance " << importedInstance
3296+ << " . Importable: " << importable->module << " "
3297+ << importable->base << " \n " ;
3298+ trap ((std::stringstream ()
3299+ << " Export " << importable->base << " doesn't exist." )
3300+ .str ());
3301+ }
3302+ if (export_ && export_->kind != kind) {
3303+ trap (" Exported kind doesn't match" );
3304+ }
3305+
3306+ if (auto ** memory = std::get_if<Memory*>(&import )) {
3307+ SubType* importedInstance =
3308+ linkedInstances.at ((*memory)->module ).get ();
3309+ Export* export_ =
3310+ importedInstance->wasm .getExportOrNull ((*memory)->base );
3311+ Memory* exportedMemory =
3312+ importedInstance->wasm .getMemory (*export_->getInternalName ());
3313+ if (!(*memory)->isSubType (*exportedMemory)) {
3314+ trap (" Imported memory isn't compatible" );
3315+ }
3316+ }
3317+
3318+ if (auto ** table = std::get_if<Table*>(&import )) {
3319+ SubType* importedInstance =
3320+ linkedInstances.at ((*table)->module ).get ();
3321+ Export* export_ =
3322+ importedInstance->wasm .getExportOrNull ((*table)->base );
3323+ Table* exportedTable =
3324+ importedInstance->wasm .getTable (*export_->getInternalName ());
3325+ if (!(*table)->isSubType (*exportedTable)) {
3326+ trap (" Imported table isn't compatible" );
3327+ }
3328+ }
3329+ });
3330+ }
3331+
32723332 TableInstanceInfo getTableInstanceInfo (Name name) {
32733333 auto * table = wasm.getTable (name);
32743334 if (table->imported ()) {
@@ -4682,12 +4742,13 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
46824742 }
46834743 Flow visitStackSwitch (StackSwitch* curr) { return Flow (NONCONSTANT_FLOW); }
46844744
4685- void trap (const char * why) override {
4686- // Traps break all current continuations - they will never be resumable.
4745+ void trap (std::string_view why) override {
46874746 self ()->clearContinuationStore ();
46884747 externalInterface->trap (why);
46894748 }
46904749
4750+ void trap (const char * why) override { trap (std::string_view (why)); }
4751+
46914752 void hostLimit (const char * why) override {
46924753 self ()->clearContinuationStore ();
46934754 externalInterface->hostLimit (why);
0 commit comments