diff options
author | Alon Zakai <alonzakai@gmail.com> | 2019-04-08 17:26:24 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-08 17:26:24 -0700 |
commit | b56c691ab87c2cd09255b2617213ec5d8e92a748 (patch) | |
tree | 29d8cd53c0481e200a643e68f9bf6d436726ef9b /src/tools/fuzzing.h | |
parent | c9eeaefbd839cc5176957e479475625fc8b2bcf0 (diff) | |
download | binaryen-b56c691ab87c2cd09255b2617213ec5d8e92a748.tar.gz binaryen-b56c691ab87c2cd09255b2617213ec5d8e92a748.tar.bz2 binaryen-b56c691ab87c2cd09255b2617213ec5d8e92a748.zip |
Better memory fuzzing (#1987)
Hash the contents of all of memory and log that out in random places in the fuzzer, so we are more sensitive there and can catch memory bugs.
Fix UB that was uncovered by this in the binary writing code - if a segment is empty, we should not look at &vector[0], and instead use vector.data().
Add Builder::addExport convenience method.
Diffstat (limited to 'src/tools/fuzzing.h')
-rw-r--r-- | src/tools/fuzzing.h | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index b8434353a..7b47dea8f 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -255,6 +255,7 @@ private: } void setupMemory() { + // Add memory itself MemoryUtils::ensureExists(wasm.memory); if (features.hasBulkMemory()) { size_t memCovered = 0; @@ -283,6 +284,41 @@ private: wasm.memory.segments[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.makeSetLocal(0, builder.makeConst(Literal(uint32_t(5381)))) + ); + for (Index i = 0; i < USABLE_MEMORY; i++) { + contents.push_back( + builder.makeSetLocal(0, + builder.makeBinary(XorInt32, + builder.makeBinary(AddInt32, + builder.makeBinary(ShlInt32, + builder.makeGetLocal(0, i32), + builder.makeConst(Literal(uint32_t(5))) + ), + builder.makeGetLocal(0, i32) + ), + builder.makeLoad(1, false, i, 1, builder.makeConst(Literal(uint32_t(0))), i32) + ) + ) + ); + } + contents.push_back( + builder.makeGetLocal(0, i32) + ); + auto* body = builder.makeBlock(contents); + auto* hasher = wasm.addFunction(builder.makeFunction("hashMemory", std::vector<Type>{}, i32, { i32 }, body)); + hasher->type = ensureFunctionType(getSig(hasher), &wasm)->name; + wasm.addExport(builder.makeExport(hasher->name, hasher->name, ExternalKind::Function)); } void setupTable() { @@ -675,6 +711,10 @@ private: invoke = builder.makeDrop(invoke); } invocations.push_back(invoke); + // log out memory in some cases + if (oneIn(2)) { + invocations.push_back(makeMemoryHashLogging()); + } } if (invocations.empty()) return; auto* invoker = new Function; @@ -770,7 +810,13 @@ private: Expression* _makenone() { auto choice = upTo(100); - if (choice < LOGGING_PERCENT) return makeLogging(); + if (choice < LOGGING_PERCENT) { + if (choice < LOGGING_PERCENT / 2) { + return makeLogging(); + } else { + return makeMemoryHashLogging(); + } + } choice = upTo(100); if (choice < 50) return makeSetLocal(none); if (choice < 60) return makeBlock(none); @@ -1814,6 +1860,11 @@ private: return builder.makeCall(std::string("log-") + printType(type), { make(type) }, none); } + Expression* makeMemoryHashLogging() { + auto* hash = builder.makeCall(std::string("hashMemory"), {}, i32); + return builder.makeCall(std::string("log-i32"), { hash }, none); + } + // special getters Type getType() { |