diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 9722faec4b5..8f89c1292ed 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -717,7 +717,7 @@ void TranslateToFuzzReader::setupTags() { } // Add the fuzzing support tags manually sometimes. - if (!preserveImportsAndExports && oneIn(2)) { + if (!preserveImportsAndExports && oneIn(2) && !random.finished()) { auto wasmTag = builder.makeTag(Names::getValidTagName(wasm, "wasmtag"), Signature(Type::i32, Type::none)); wasmTag->module = "fuzzing-support"; @@ -859,7 +859,8 @@ void TranslateToFuzzReader::shuffleExports() { // find more things). But we also keep a good chance for the natural order // here, as it may help some initial content. Note we cannot do this if we are // preserving the exports, as their order is something we must maintain. - if (wasm.exports.empty() || preserveImportsAndExports || oneIn(2)) { + if (wasm.exports.empty() || preserveImportsAndExports || oneIn(2) || + random.finished()) { return; } @@ -937,7 +938,7 @@ void TranslateToFuzzReader::addImportCallingSupport() { // Only add these some of the time, as they inhibit some fuzzing (things like // wasm-ctor-eval and wasm-merge are sensitive to the wasm being able to call // its own exports, and to care about the indexes of the exports). - if (oneIn(2)) { + if (oneIn(2) || random.finished()) { return; } @@ -1005,6 +1006,9 @@ void TranslateToFuzzReader::addImportCallingSupport() { } void TranslateToFuzzReader::addImportThrowingSupport() { + if (random.finished()) { + return; + } // Throw some kind of exception from JS. If we send 0 then a pure JS // exception is thrown, and any other value is the value in a wasm tag. throwImportName = Names::getValidFunctionName(wasm, "throw"); @@ -1026,7 +1030,7 @@ void TranslateToFuzzReader::addImportTableSupport() { // for them. For simplicity, use the funcref table we use internally, though // we could pick one at random, support non-funcref ones, and even export // multiple ones TODO - if (!funcrefTableName) { + if (!funcrefTableName || random.finished()) { return; } @@ -1068,7 +1072,7 @@ void TranslateToFuzzReader::addImportTableSupport() { void TranslateToFuzzReader::addImportSleepSupport() { // Fuzz this somewhat rarely, as it may be slow, and only when we can add // imports. - if (preserveImportsAndExports || !oneIn(4)) { + if (preserveImportsAndExports || !oneIn(4) || random.finished()) { return; } @@ -1086,7 +1090,7 @@ void TranslateToFuzzReader::addImportSleepSupport() { void TranslateToFuzzReader::addHashMemorySupport() { // Don't always add this. - if (oneIn(2)) { + if (oneIn(2) || random.finished()) { return; } @@ -5202,7 +5206,7 @@ Expression* TranslateToFuzzReader::makeI31Get(Type type) { Expression* TranslateToFuzzReader::makeThrow(Type type) { assert(type == Type::unreachable); Tag* tag; - if (trivialNesting) { + if (trivialNesting || random.finished()) { // We are nested under a makeTrivial call, so only emit something trivial. // Get (or create) a trivial tag, so we have no operands (and will not call // make(), below). Otherwise, we might recurse very deeply if we threw a diff --git a/src/tools/fuzzing/random.cpp b/src/tools/fuzzing/random.cpp index 8beda478b84..cfcdbdd970e 100644 --- a/src/tools/fuzzing/random.cpp +++ b/src/tools/fuzzing/random.cpp @@ -26,6 +26,14 @@ Random::Random(std::vector&& bytes_, FeatureSet features) if (bytes.empty()) { bytes.push_back(0); } + if (auto* maxBytes = getenv("BINARYEN_FUZZER_MAX_BYTES")) { + unsigned max = atoi(maxBytes); + if (max < bytes.size()) { + std::cerr << "fuzzer: resizing from " << bytes.size() << " to " << max + << '\n'; + bytes.resize(max); + } + } } int8_t Random::get() { @@ -58,6 +66,9 @@ float Random::getFloat() { return Literal(get32()).reinterpretf32(); } double Random::getDouble() { return Literal(get64()).reinterpretf64(); } uint32_t Random::upTo(uint32_t x) { + if (finished()) { + return 0; + } if (x == 0) { return 0; } diff --git a/test/passes/fuzz_metrics_noprint.bin.txt b/test/passes/fuzz_metrics_noprint.bin.txt index 0c204cff762..50632e024d7 100644 --- a/test/passes/fuzz_metrics_noprint.bin.txt +++ b/test/passes/fuzz_metrics_noprint.bin.txt @@ -9,15 +9,15 @@ total [table-data] : 25 [tables] : 1 [tags] : 0 - [total] : 6791 + [total] : 6794 [vars] : 256 Binary : 454 - Block : 1201 + Block : 1202 Break : 188 Call : 205 CallIndirect : 61 - Const : 1131 - Drop : 88 + Const : 1132 + Drop : 89 GlobalGet : 635 GlobalSet : 487 If : 378 diff --git a/test/passes/fuzz_metrics_passes_noprint.bin.txt b/test/passes/fuzz_metrics_passes_noprint.bin.txt index 29d1cfcf2b5..9994355a595 100644 --- a/test/passes/fuzz_metrics_passes_noprint.bin.txt +++ b/test/passes/fuzz_metrics_passes_noprint.bin.txt @@ -1,6 +1,6 @@ Metrics total - [exports] : 37 + [exports] : 38 [funcs] : 59 [globals] : 4 [imports] : 6 @@ -9,27 +9,27 @@ total [table-data] : 28 [tables] : 1 [tags] : 0 - [total] : 9390 + [total] : 9393 [vars] : 189 Binary : 651 - Block : 1536 + Block : 1535 Break : 316 Call : 296 CallIndirect : 91 - Const : 1666 + Const : 1670 Drop : 66 GlobalGet : 650 GlobalSet : 582 If : 506 Load : 149 - LocalGet : 827 + LocalGet : 823 LocalSet : 497 Loop : 232 Nop : 114 RefFunc : 28 - Return : 81 + Return : 83 Select : 75 Store : 71 Switch : 7 - Unary : 657 + Unary : 659 Unreachable : 292 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 c949e40bb85..5bdbbb27ea9 100644 --- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt +++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt @@ -1,7 +1,7 @@ Metrics total - [exports] : 16 - [funcs] : 21 + [exports] : 14 + [funcs] : 20 [globals] : 26 [imports] : 12 [memories] : 1 @@ -9,42 +9,42 @@ total [table-data] : 6 [tables] : 2 [tags] : 1 - [total] : 887 - [vars] : 47 - ArrayNewFixed : 6 + [total] : 734 + [vars] : 45 + ArrayNewFixed : 5 AtomicCmpxchg : 1 AtomicFence : 1 AtomicNotify : 2 AtomicRMW : 1 - Binary : 93 - Block : 116 + Binary : 43 + Block : 115 BrOn : 1 Break : 11 Call : 27 CallRef : 2 - Const : 178 + Const : 144 Drop : 15 GlobalGet : 66 GlobalSet : 50 If : 32 - Load : 21 - LocalGet : 54 - LocalSet : 29 + Load : 5 + LocalGet : 20 + LocalSet : 11 Loop : 5 MemoryCopy : 1 MemoryFill : 1 MemoryInit : 1 - Nop : 14 + Nop : 13 RefEq : 3 RefFunc : 11 - RefI31 : 11 + RefI31 : 12 RefNull : 11 RefTest : 1 Return : 6 SIMDExtract : 2 Select : 3 Store : 3 - StringConst : 12 + StringConst : 13 StringEq : 2 StringWTF16Get : 1 StructNew : 14