Skip to content

Commit b41327e

Browse files
authored
Fuzzer: Shuffle exports (#7199)
This adds more variety in some situations.
1 parent 666c9df commit b41327e

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

src/tools/fuzzing.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ class TranslateToFuzzReader {
233233
void addTag();
234234
void finalizeMemory();
235235
void finalizeTable();
236+
void shuffleExports();
236237
void prepareHangLimitSupport();
237238
void addHangLimitSupport();
238239
void addImportLoggingSupport();

src/tools/fuzzing/fuzzing.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ void TranslateToFuzzReader::build() {
332332
addHashMemorySupport();
333333
}
334334
finalizeTable();
335+
shuffleExports();
335336
}
336337

337338
void TranslateToFuzzReader::setupMemory() {
@@ -746,6 +747,37 @@ void TranslateToFuzzReader::finalizeTable() {
746747
}
747748
}
748749

750+
void TranslateToFuzzReader::shuffleExports() {
751+
// Randomly ordering the exports is useful for a few reasons. First, initial
752+
// content may have a natural order in which to execute things (an "init"
753+
// export first, for example), and changing that order may lead to very
754+
// different execution. Second, even in the fuzzer's own random content there
755+
// is a "direction", since we generate as we go (e.g. no function calls a
756+
// later function that does not exist yet / will be created later), and also
757+
// we emit invokes for a function right after it (so we end up calling the
758+
// same code several times in succession, but interleaving it with others may
759+
// find more things). But we also keep a good chance for the natural order
760+
// here, as it may help some initial content.
761+
if (wasm.exports.empty() || oneIn(2)) {
762+
return;
763+
}
764+
765+
// Sort the exports in the simple Fisher-Yates manner.
766+
// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
767+
for (Index i = 0; i < wasm.exports.size() - 1; i++) {
768+
// Pick the index of the item to place at index |i|. The number of items to
769+
// pick from begins at the full length, then decreases with i.
770+
auto j = i + upTo(wasm.exports.size() - i);
771+
772+
// Swap the item over here.
773+
if (j != i) {
774+
std::swap(wasm.exports[i], wasm.exports[j]);
775+
}
776+
}
777+
778+
wasm.updateMaps();
779+
}
780+
749781
void TranslateToFuzzReader::prepareHangLimitSupport() {
750782
HANG_LIMIT_GLOBAL = Names::getValidGlobalName(wasm, "hangLimit");
751783
}

0 commit comments

Comments
 (0)