Skip to content

Commit 9c0a77c

Browse files
wip
1 parent 44c5834 commit 9c0a77c

File tree

4 files changed

+105
-12
lines changed

4 files changed

+105
-12
lines changed

scripts/test/shared.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,6 @@ def get_tests(test_dir, extensions=[], recursive=False):
444444
'proposals/threads/imports.wast', # Missing memory type validation on instantiation
445445
'linking.wast', # Missing function type validation on instantiation
446446
'proposals/threads/memory.wast', # Missing memory type validation on instantiation
447-
'memory64-imports.wast', # Missing validation on instantiation
448447
'annotations.wast', # String annotations IDs should be allowed
449448
'id.wast', # Empty IDs should be disallowed
450449
# Requires correct handling of tag imports from different instances of the same module,
@@ -473,12 +472,8 @@ def get_tests(test_dir, extensions=[], recursive=False):
473472
'type-rec.wast', # Missing function type validation on instantiation
474473
'type-subtyping.wast', # ShellExternalInterface::callTable does not handle subtyping
475474
'call_indirect.wast', # Bug with 64-bit inline element segment parsing
476-
'memory64.wast', # Requires validations for memory size
477-
'imports0.wast', # Missing memory type validation on instantiation
478-
'imports2.wast', # Missing memory type validation on instantiation
479-
'imports3.wast', # Missing memory type validation on instantiation
480-
'linking0.wast', # Missing memory type validation on instantiation
481-
'linking3.wast', # Fatal error on missing table.
475+
# 'memory64.wast', # Requires wast `module definition` support
476+
# 'linking0.wast', # Missing memory type validation on instantiation
482477
'i16x8_relaxed_q15mulr_s.wast', # Requires wast `either` support
483478
'i32x4_relaxed_trunc.wast', # Requires wast `either` support
484479
'i8x16_relaxed_swizzle.wast', # Requires wast `either` support

src/shell-interface.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,9 @@ struct ShellExternalInterface : ModuleRunner::ExternalInterface {
134134
auto inst = getImportInstance(import);
135135
auto* exportedGlobal = inst->wasm.getExportOrNull(import->base);
136136
if (!exportedGlobal || exportedGlobal->kind != ExternalKind::Global) {
137-
Fatal() << "importGlobals: unknown import: " << import->module.str
138-
<< "." << import->name.str;
137+
trap((std::stringstream() << "unknown import: " << import->module.str
138+
<< "." << import->name.str)
139+
.str());
139140
}
140141
globals[import->name] = inst->globals[*exportedGlobal->getInternalName()];
141142
});
@@ -330,6 +331,11 @@ struct ShellExternalInterface : ModuleRunner::ExternalInterface {
330331
throw TrapException();
331332
}
332333

334+
void trap(std::string_view why) override {
335+
std::cout << "[trap " << why << "]\n";
336+
throw TrapException();
337+
}
338+
333339
void hostLimit(const char* why) override {
334340
std::cout << "[host limit " << why << "]\n";
335341
throw HostLimitException();

src/wasm-interpreter.h

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

src/wasm.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,6 +2435,28 @@ class Table : public Importable {
24352435
initial = 0;
24362436
max = kMaxSize;
24372437
}
2438+
2439+
static bool isSubType(const Table& a, const Table& b) {
2440+
if (a.addressType != b.addressType) {
2441+
return false;
2442+
}
2443+
2444+
if (!Type::isSubType(a.type, b.type)) {
2445+
return false;
2446+
}
2447+
2448+
if (a.initial > b.initial) {
2449+
return false;
2450+
}
2451+
2452+
if (a.max < b.max) {
2453+
return false;
2454+
}
2455+
2456+
return true;
2457+
}
2458+
2459+
bool isSubType(const Table& other) { return Table::isSubType(*this, other); }
24382460
};
24392461

24402462
class DataSegment : public Named {
@@ -2470,6 +2492,15 @@ class Memory : public Importable {
24702492
shared = false;
24712493
addressType = Type::i32;
24722494
}
2495+
2496+
static bool isSubType(const Memory& a, const Memory& b) {
2497+
return a.addressType == b.addressType && a.initial <= b.initial &&
2498+
a.max >= b.max;
2499+
}
2500+
2501+
bool isSubType(const Memory& other) {
2502+
return Memory::isSubType(*this, other);
2503+
}
24732504
};
24742505

24752506
class Global : public Importable {

0 commit comments

Comments
 (0)