summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/fuzzing.h4
-rw-r--r--src/tools/fuzzing/fuzzing.cpp62
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt77
3 files changed, 75 insertions, 68 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index a40a76106..837713dce 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -289,10 +289,6 @@ private:
Expression* makeCallRef(Type type);
Expression* makeLocalGet(Type type);
Expression* makeLocalSet(Type type);
- // Some globals are for internal use, and should not be modified by random
- // fuzz code.
- bool isValidGlobal(Name name);
-
Expression* makeGlobalGet(Type type);
Expression* makeGlobalSet(Type type);
Expression* makeTupleMake(Type type);
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index ef7b3a5b7..d9e0f6baf 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -379,6 +379,24 @@ void TranslateToFuzzReader::setupGlobals() {
}
}
}
+
+ // Randomly assign some globals from initial content to be ignored for the
+ // fuzzer to use. Such globals will only be used from initial content. This is
+ // important to preserve some real-world patterns, like the "once" pattern in
+ // which a global is used in one function only. (If we randomly emitted gets
+ // and sets of such globals, we'd with very high probability end up breaking
+ // that pattern, and not fuzzing it at all.)
+ //
+ // Pick a percentage of initial globals to ignore later down when we decide
+ // which to allow uses from.
+ auto numInitialGlobals = wasm.globals.size();
+ unsigned percentIgnoredInitialGlobals = 0;
+ if (numInitialGlobals) {
+ // Only generate this random number if it will be used.
+ percentIgnoredInitialGlobals = upTo(100);
+ }
+
+ // Create new random globals.
for (size_t index = upTo(MAX_GLOBALS); index > 0; --index) {
auto type = getConcreteType();
auto* init = makeConst(type);
@@ -394,12 +412,24 @@ void TranslateToFuzzReader::setupGlobals() {
auto mutability = oneIn(2) ? Builder::Mutable : Builder::Immutable;
auto global = builder.makeGlobal(
Names::getValidGlobalName(wasm, "global$"), type, init, mutability);
- globalsByType[type].push_back(global->name);
- if (mutability == Builder::Mutable) {
- mutableGlobalsByType[type].push_back(global->name);
- }
wasm.addGlobal(std::move(global));
}
+
+ // Set up data structures for picking globals later for get/set operations.
+ for (Index i = 0; i < wasm.globals.size(); i++) {
+ auto& global = wasm.globals[i];
+
+ // Apply the chance for initial globals to be ignored, see above.
+ if (i < numInitialGlobals && upTo(100) < percentIgnoredInitialGlobals) {
+ continue;
+ }
+
+ // This is a global we can use later, note it.
+ globalsByType[global->type].push_back(global->name);
+ if (global->mutable_) {
+ mutableGlobalsByType[global->type].push_back(global->name);
+ }
+ }
}
void TranslateToFuzzReader::setupTags() {
@@ -1696,21 +1726,16 @@ Expression* TranslateToFuzzReader::makeLocalSet(Type type) {
}
}
-bool TranslateToFuzzReader::isValidGlobal(Name name) {
- return name != HANG_LIMIT_GLOBAL;
-}
-
Expression* TranslateToFuzzReader::makeGlobalGet(Type type) {
auto it = globalsByType.find(type);
if (it == globalsByType.end() || it->second.empty()) {
- return makeConst(type);
- }
- auto name = pick(it->second);
- if (isValidGlobal(name)) {
- return builder.makeGlobalGet(name, type);
- } else {
return makeTrivial(type);
}
+
+ auto name = pick(it->second);
+ // We don't want random fuzz code to use the hang limit global.
+ assert(name != HANG_LIMIT_GLOBAL);
+ return builder.makeGlobalGet(name, type);
}
Expression* TranslateToFuzzReader::makeGlobalSet(Type type) {
@@ -1720,12 +1745,11 @@ Expression* TranslateToFuzzReader::makeGlobalSet(Type type) {
if (it == mutableGlobalsByType.end() || it->second.empty()) {
return makeTrivial(Type::none);
}
+
auto name = pick(it->second);
- if (isValidGlobal(name)) {
- return builder.makeGlobalSet(name, make(type));
- } else {
- return makeTrivial(Type::none);
- }
+ // We don't want random fuzz code to use the hang limit global.
+ assert(name != HANG_LIMIT_GLOBAL);
+ return builder.makeGlobalSet(name, make(type));
}
Expression* TranslateToFuzzReader::makeTupleMake(Type type) {
diff --git a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
index 6f5078909..9697da8bd 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -8,48 +8,35 @@ total
[table-data] : 1
[tables] : 1
[tags] : 2
- [total] : 643
- [vars] : 36
- ArrayCopy : 1
- ArrayFill : 1
- ArrayGet : 1
- ArrayLen : 5
- ArrayNew : 7
- ArraySet : 1
- AtomicNotify : 1
- AtomicRMW : 1
- Binary : 84
- Block : 58
- Break : 9
- Call : 22
- CallRef : 2
- Const : 144
- Drop : 2
- GlobalGet : 16
- GlobalSet : 16
- I31Get : 2
- If : 20
- Load : 20
- LocalGet : 75
- LocalSet : 48
- Loop : 4
- MemoryInit : 1
- Nop : 4
- Pop : 4
- RefAs : 4
- RefFunc : 6
- RefI31 : 3
- RefNull : 11
- RefTest : 1
- Return : 7
- SIMDExtract : 1
- Select : 5
- Store : 3
- StructGet : 3
- StructNew : 7
- StructSet : 1
- Try : 3
- TupleExtract : 7
- TupleMake : 10
- Unary : 14
- Unreachable : 8
+ [total] : 314
+ [vars] : 38
+ ArrayNew : 2
+ ArrayNewFixed : 1
+ AtomicFence : 1
+ Binary : 58
+ Block : 28
+ Break : 6
+ Call : 10
+ Const : 72
+ Drop : 3
+ GlobalGet : 10
+ GlobalSet : 10
+ I31Get : 1
+ If : 7
+ Load : 18
+ LocalGet : 36
+ LocalSet : 21
+ Loop : 1
+ Nop : 2
+ RefEq : 1
+ RefFunc : 2
+ RefI31 : 2
+ RefNull : 1
+ Return : 2
+ Select : 1
+ Store : 1
+ StructGet : 1
+ StructNew : 3
+ TupleMake : 2
+ Unary : 6
+ Unreachable : 5