Skip to content

Commit be92434

Browse files
authored
Fuzz fix: if global does not exist, report error and don't run the rest of the checks (#1461)
1 parent e8b7539 commit be92434

File tree

1 file changed

+38
-37
lines changed

1 file changed

+38
-37
lines changed

src/wasm/wasm-validator.cpp

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,15 @@ struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> {
201201
if (curr->name.is()) self->breakTargets[curr->name] = curr;
202202
}
203203

204-
void visitBlock(Block *curr);
204+
void visitBlock(Block* curr);
205205

206206
static void visitPreLoop(FunctionValidator* self, Expression** currp) {
207207
auto* curr = (*currp)->cast<Loop>();
208208
if (curr->name.is()) self->breakTargets[curr->name] = curr;
209209
}
210210

211-
void visitLoop(Loop *curr);
212-
void visitIf(If *curr);
211+
void visitLoop(Loop* curr);
212+
void visitIf(If* curr);
213213

214214
// override scan to add a pre and a post check task to all nodes
215215
static void scan(FunctionValidator* self, Expression** currp) {
@@ -221,28 +221,28 @@ struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> {
221221
}
222222

223223
void noteBreak(Name name, Expression* value, Expression* curr);
224-
void visitBreak(Break *curr);
225-
void visitSwitch(Switch *curr);
226-
void visitCall(Call *curr);
227-
void visitCallImport(CallImport *curr);
228-
void visitCallIndirect(CallIndirect *curr);
224+
void visitBreak(Break* curr);
225+
void visitSwitch(Switch* curr);
226+
void visitCall(Call* curr);
227+
void visitCallImport(CallImport* curr);
228+
void visitCallIndirect(CallIndirect* curr);
229229
void visitGetLocal(GetLocal* curr);
230-
void visitSetLocal(SetLocal *curr);
230+
void visitSetLocal(SetLocal* curr);
231231
void visitGetGlobal(GetGlobal* curr);
232-
void visitSetGlobal(SetGlobal *curr);
233-
void visitLoad(Load *curr);
234-
void visitStore(Store *curr);
235-
void visitAtomicRMW(AtomicRMW *curr);
236-
void visitAtomicCmpxchg(AtomicCmpxchg *curr);
237-
void visitAtomicWait(AtomicWait *curr);
238-
void visitAtomicWake(AtomicWake *curr);
239-
void visitBinary(Binary *curr);
240-
void visitUnary(Unary *curr);
232+
void visitSetGlobal(SetGlobal* curr);
233+
void visitLoad(Load* curr);
234+
void visitStore(Store* curr);
235+
void visitAtomicRMW(AtomicRMW* curr);
236+
void visitAtomicCmpxchg(AtomicCmpxchg* curr);
237+
void visitAtomicWait(AtomicWait* curr);
238+
void visitAtomicWake(AtomicWake* curr);
239+
void visitBinary(Binary* curr);
240+
void visitUnary(Unary* curr);
241241
void visitSelect(Select* curr);
242242
void visitDrop(Drop* curr);
243243
void visitReturn(Return* curr);
244244
void visitHost(Host* curr);
245-
void visitFunction(Function *curr);
245+
void visitFunction(Function* curr);
246246

247247
// helpers
248248
private:
@@ -289,7 +289,7 @@ void FunctionValidator::noteLabelName(Name name) {
289289
labelNames.insert(name);
290290
}
291291

292-
void FunctionValidator::visitBlock(Block *curr) {
292+
void FunctionValidator::visitBlock(Block* curr) {
293293
// if we are break'ed to, then the value must be right for us
294294
if (curr->name.is()) {
295295
noteLabelName(curr->name);
@@ -344,7 +344,7 @@ void FunctionValidator::visitBlock(Block *curr) {
344344
}
345345
}
346346

347-
void FunctionValidator::visitLoop(Loop *curr) {
347+
void FunctionValidator::visitLoop(Loop* curr) {
348348
if (curr->name.is()) {
349349
noteLabelName(curr->name);
350350
breakTargets.erase(curr->name);
@@ -358,7 +358,7 @@ void FunctionValidator::visitLoop(Loop *curr) {
358358
}
359359
}
360360

361-
void FunctionValidator::visitIf(If *curr) {
361+
void FunctionValidator::visitIf(If* curr) {
362362
shouldBeTrue(curr->condition->type == unreachable || curr->condition->type == i32, curr, "if condition must be valid");
363363
if (!curr->ifFalse) {
364364
shouldBeFalse(isConcreteType(curr->ifTrue->type), curr, "if without else must not return a value in body");
@@ -412,22 +412,22 @@ void FunctionValidator::noteBreak(Name name, Expression* value, Expression* curr
412412
}
413413
}
414414
}
415-
void FunctionValidator::visitBreak(Break *curr) {
415+
void FunctionValidator::visitBreak(Break* curr) {
416416
noteBreak(curr->name, curr->value, curr);
417417
if (curr->condition) {
418418
shouldBeTrue(curr->condition->type == unreachable || curr->condition->type == i32, curr, "break condition must be i32");
419419
}
420420
}
421421

422-
void FunctionValidator::visitSwitch(Switch *curr) {
422+
void FunctionValidator::visitSwitch(Switch* curr) {
423423
for (auto& target : curr->targets) {
424424
noteBreak(target, curr->value, curr);
425425
}
426426
noteBreak(curr->default_, curr->value, curr);
427427
shouldBeTrue(curr->condition->type == unreachable || curr->condition->type == i32, curr, "br_table condition must be i32");
428428
}
429429

430-
void FunctionValidator::visitCall(Call *curr) {
430+
void FunctionValidator::visitCall(Call* curr) {
431431
if (!info.validateGlobally) return;
432432
auto* target = getModule()->getFunctionOrNull(curr->target);
433433
if (!shouldBeTrue(!!target, curr, "call target must exist")) {
@@ -444,7 +444,7 @@ void FunctionValidator::visitCall(Call *curr) {
444444
}
445445
}
446446

447-
void FunctionValidator::visitCallImport(CallImport *curr) {
447+
void FunctionValidator::visitCallImport(CallImport* curr) {
448448
if (!info.validateGlobally) return;
449449
auto* import = getModule()->getImportOrNull(curr->target);
450450
if (!shouldBeTrue(!!import, curr, "call_import target must exist")) return;
@@ -458,7 +458,7 @@ void FunctionValidator::visitCallImport(CallImport *curr) {
458458
}
459459
}
460460

461-
void FunctionValidator::visitCallIndirect(CallIndirect *curr) {
461+
void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
462462
if (!info.validateGlobally) return;
463463
auto* type = getModule()->getFunctionTypeOrNull(curr->fullType);
464464
if (!shouldBeTrue(!!type, curr, "call_indirect type must exist")) return;
@@ -476,7 +476,7 @@ void FunctionValidator::visitGetLocal(GetLocal* curr) {
476476
shouldBeTrue(isConcreteType(curr->type), curr, "get_local must have a valid type - check what you provided when you constructed the node");
477477
}
478478

479-
void FunctionValidator::visitSetLocal(SetLocal *curr) {
479+
void FunctionValidator::visitSetLocal(SetLocal* curr) {
480480
shouldBeTrue(curr->index < getFunction()->getNumLocals(), curr, "set_local index must be small enough");
481481
if (curr->value->type != unreachable) {
482482
if (curr->type != none) { // tee is ok anyhow
@@ -491,15 +491,16 @@ void FunctionValidator::visitGetGlobal(GetGlobal* curr) {
491491
shouldBeTrue(getModule()->getGlobalOrNull(curr->name) || getModule()->getImportOrNull(curr->name), curr, "get_global name must be valid");
492492
}
493493

494-
void FunctionValidator::visitSetGlobal(SetGlobal *curr) {
494+
void FunctionValidator::visitSetGlobal(SetGlobal* curr) {
495495
if (!info.validateGlobally) return;
496496
auto* global = getModule()->getGlobalOrNull(curr->name);
497-
shouldBeTrue(global, curr, "set_global name must be valid (and not an import; imports can't be modified)");
498-
shouldBeTrue(global->mutable_, curr, "set_global global must be mutable");
499-
shouldBeEqualOrFirstIsUnreachable(curr->value->type, global->type, curr, "set_global value must have right type");
497+
if (shouldBeTrue(global, curr, "set_global name must be valid (and not an import; imports can't be modified)")) {
498+
shouldBeTrue(global->mutable_, curr, "set_global global must be mutable");
499+
shouldBeEqualOrFirstIsUnreachable(curr->value->type, global->type, curr, "set_global value must have right type");
500+
}
500501
}
501502

502-
void FunctionValidator::visitLoad(Load *curr) {
503+
void FunctionValidator::visitLoad(Load* curr) {
503504
if (curr->isAtomic) shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
504505
shouldBeFalse(curr->isAtomic && !getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
505506
validateMemBytes(curr->bytes, curr->type, curr);
@@ -508,7 +509,7 @@ void FunctionValidator::visitLoad(Load *curr) {
508509
if (curr->isAtomic) shouldBeFalse(curr->signed_, curr, "atomic loads must be unsigned");
509510
}
510511

511-
void FunctionValidator::visitStore(Store *curr) {
512+
void FunctionValidator::visitStore(Store* curr) {
512513
if (curr->isAtomic) shouldBeTrue(info.features & Feature::Atomics, curr, "Atomic operation (atomics are disabled)");
513514
shouldBeFalse(curr->isAtomic && !getModule()->memory.shared, curr, "Atomic operation with non-shared memory");
514515
validateMemBytes(curr->bytes, curr->valueType, curr);
@@ -575,7 +576,7 @@ void FunctionValidator::validateMemBytes(uint8_t bytes, Type type, Expression* c
575576
}
576577
}
577578

578-
void FunctionValidator::visitBinary(Binary *curr) {
579+
void FunctionValidator::visitBinary(Binary* curr) {
579580
if (curr->left->type != unreachable && curr->right->type != unreachable) {
580581
shouldBeEqual(curr->left->type, curr->right->type, curr, "binary child types must be equal");
581582
}
@@ -672,7 +673,7 @@ void FunctionValidator::visitBinary(Binary *curr) {
672673
}
673674
}
674675

675-
void FunctionValidator::visitUnary(Unary *curr) {
676+
void FunctionValidator::visitUnary(Unary* curr) {
676677
shouldBeUnequal(curr->value->type, none, curr, "unaries must not receive a none as their input");
677678
if (curr->value->type == unreachable) return; // nothing to check
678679
switch (curr->op) {
@@ -793,7 +794,7 @@ void FunctionValidator::visitHost(Host* curr) {
793794
}
794795
}
795796

796-
void FunctionValidator::visitFunction(Function *curr) {
797+
void FunctionValidator::visitFunction(Function* curr) {
797798
// if function has no result, it is ignored
798799
// if body is unreachable, it might be e.g. a return
799800
if (curr->body->type != unreachable) {

0 commit comments

Comments
 (0)