diff options
author | Alon Zakai <azakai@google.com> | 2023-03-09 15:04:35 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-09 15:04:35 -0800 |
commit | 4f28d966f3366827fb1d19cd107203935135658b (patch) | |
tree | cf8584722f1b60317eb28c34eccb5757b0ef5e9d /src | |
parent | 819b7ce54d6c1f2032ab6fb28213126b49f61996 (diff) | |
download | binaryen-4f28d966f3366827fb1d19cd107203935135658b.tar.gz binaryen-4f28d966f3366827fb1d19cd107203935135658b.tar.bz2 binaryen-4f28d966f3366827fb1d19cd107203935135658b.zip |
Emit the fuzzer hashMemory function after modifications (#5558)
Previously we emitted it early, and would then modify it in random ways
like other initial content. But this function is called frequently during
execution, so if we were unlucky and modded that function to trap then
basically all other functions would trap as well.
After fixing this, some places assert on not having any functions or types
to pick a random one from, so fix those places too.
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/fuzzing.h | 1 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 100 |
2 files changed, 54 insertions, 47 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 830e204f8..9789a3a5b 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -176,6 +176,7 @@ private: void prepareHangLimitSupport(); void addHangLimitSupport(); void addImportLoggingSupport(); + void addHashMemorySupport(); // Special expression makers Expression* makeHangLimitCheck(); diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 42d3ec3ba..db4d0196e 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -187,6 +187,7 @@ void TranslateToFuzzReader::build() { } if (allowMemory) { finalizeMemory(); + addHashMemorySupport(); } finalizeTable(); } @@ -227,49 +228,6 @@ void TranslateToFuzzReader::setupMemory() { wasm.dataSegments[0]->data.push_back(value >= 256 ? 0 : (value & 0xff)); } } - // Add memory hasher helper (for the hash, see hash.h). The function looks - // like: - // function hashMemory() { - // hash = 5381; - // hash = ((hash << 5) + hash) ^ mem[0]; - // hash = ((hash << 5) + hash) ^ mem[1]; - // .. - // return hash; - // } - std::vector<Expression*> contents; - contents.push_back( - builder.makeLocalSet(0, builder.makeConst(uint32_t(5381)))); - auto zero = Literal::makeFromInt32(0, wasm.memories[0]->indexType); - for (Index i = 0; i < USABLE_MEMORY; i++) { - contents.push_back(builder.makeLocalSet( - 0, - builder.makeBinary( - XorInt32, - builder.makeBinary( - AddInt32, - builder.makeBinary(ShlInt32, - builder.makeLocalGet(0, Type::i32), - builder.makeConst(uint32_t(5))), - builder.makeLocalGet(0, Type::i32)), - builder.makeLoad(1, - false, - i, - 1, - builder.makeConst(zero), - Type::i32, - wasm.memories[0]->name)))); - } - contents.push_back(builder.makeLocalGet(0, Type::i32)); - auto* body = builder.makeBlock(contents); - auto* hasher = wasm.addFunction(builder.makeFunction( - "hashMemory", Signature(Type::none, Type::i32), {Type::i32}, body)); - wasm.addExport( - builder.makeExport(hasher->name, hasher->name, ExternalKind::Function)); - // Export memory so JS fuzzing can use it - if (!wasm.getExportOrNull("memory")) { - wasm.addExport(builder.makeExport( - "memory", wasm.memories[0]->name, ExternalKind::Memory)); - } } void TranslateToFuzzReader::setupHeapTypes() { @@ -479,6 +437,52 @@ void TranslateToFuzzReader::addImportLoggingSupport() { } } +void TranslateToFuzzReader::addHashMemorySupport() { + // Add memory hasher helper (for the hash, see hash.h). The function looks + // like: + // function hashMemory() { + // hash = 5381; + // hash = ((hash << 5) + hash) ^ mem[0]; + // hash = ((hash << 5) + hash) ^ mem[1]; + // .. + // return hash; + // } + std::vector<Expression*> contents; + contents.push_back( + builder.makeLocalSet(0, builder.makeConst(uint32_t(5381)))); + auto zero = Literal::makeFromInt32(0, wasm.memories[0]->indexType); + for (Index i = 0; i < USABLE_MEMORY; i++) { + contents.push_back(builder.makeLocalSet( + 0, + builder.makeBinary( + XorInt32, + builder.makeBinary( + AddInt32, + builder.makeBinary(ShlInt32, + builder.makeLocalGet(0, Type::i32), + builder.makeConst(uint32_t(5))), + builder.makeLocalGet(0, Type::i32)), + builder.makeLoad(1, + false, + i, + 1, + builder.makeConst(zero), + Type::i32, + wasm.memories[0]->name)))); + } + contents.push_back(builder.makeLocalGet(0, Type::i32)); + auto* body = builder.makeBlock(contents); + auto* hasher = wasm.addFunction(builder.makeFunction( + "hashMemory", Signature(Type::none, Type::i32), {Type::i32}, body)); + wasm.addExport( + builder.makeExport(hasher->name, hasher->name, ExternalKind::Function)); + // Export memory so JS fuzzing can use it + if (!wasm.getExportOrNull("memory")) { + wasm.addExport(builder.makeExport( + "memory", wasm.memories[0]->name, ExternalKind::Memory)); + } +} + TranslateToFuzzReader::FunctionCreationContext::~FunctionCreationContext() { if (HANG_LIMIT > 0) { parent.addHangLimitChecks(func); @@ -1990,7 +1994,7 @@ Expression* TranslateToFuzzReader::makeRefFuncConst(Type type) { // If there is no last function, and we have others, pick between them. Also // pick between them with some random probability even if there is a last // function. - if (!target || (!wasm.functions.empty() && !oneIn(wasm.functions.size()))) { + if (!wasm.functions.empty() && (!target || !oneIn(wasm.functions.size()))) { target = pick(wasm.functions).get(); } if (target) { @@ -3112,7 +3116,8 @@ Expression* TranslateToFuzzReader::makeMemoryFill() { } Type TranslateToFuzzReader::getSingleConcreteType() { - if (wasm.features.hasReferenceTypes() && oneIn(3)) { + if (wasm.features.hasReferenceTypes() && !interestingHeapTypes.empty() && + oneIn(3)) { auto heapType = pick(interestingHeapTypes); auto nullability = getNullability(); return Type(heapType, nullability); @@ -3146,7 +3151,8 @@ Type TranslateToFuzzReader::getSingleConcreteType() { } Type TranslateToFuzzReader::getReferenceType() { - if (wasm.features.hasReferenceTypes() && oneIn(2)) { + if (wasm.features.hasReferenceTypes() && !interestingHeapTypes.empty() && + oneIn(2)) { auto heapType = pick(interestingHeapTypes); auto nullability = getNullability(); return Type(heapType, nullability); @@ -3168,7 +3174,7 @@ Type TranslateToFuzzReader::getReferenceType() { } Type TranslateToFuzzReader::getEqReferenceType() { - if (oneIn(2)) { + if (oneIn(2) && !interestingHeapTypes.empty()) { // Try to find an interesting eq-compatible type. auto heapType = pick(interestingHeapTypes); if (HeapType::isSubType(heapType, HeapType::eq)) { |