summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-03-09 15:04:35 -0800
committerGitHub <noreply@github.com>2023-03-09 15:04:35 -0800
commit4f28d966f3366827fb1d19cd107203935135658b (patch)
treecf8584722f1b60317eb28c34eccb5757b0ef5e9d /src
parent819b7ce54d6c1f2032ab6fb28213126b49f61996 (diff)
downloadbinaryen-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.h1
-rw-r--r--src/tools/fuzzing/fuzzing.cpp100
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)) {