diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 57 | ||||
-rw-r--r-- | src/tools/fuzzing/heap-types.cpp | 37 | ||||
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 5 | ||||
-rw-r--r-- | src/tools/wasm-reduce.cpp | 2 |
4 files changed, 77 insertions, 24 deletions
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 2b368a4e8..09df9ac31 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -1976,7 +1976,7 @@ Expression* TranslateToFuzzReader::makeRefFuncConst(Type type) { // to add a ref.as_non_null to validate, and the code will trap when we get // here). if ((type.isNullable() && oneIn(2)) || (type.isNonNullable() && oneIn(16))) { - Expression* ret = builder.makeRefNull(Type(heapType, Nullable)); + Expression* ret = builder.makeRefNull(HeapType::nofunc); if (!type.isNullable()) { ret = builder.makeRefAs(RefAsNonNull, ret); } @@ -2000,7 +2000,7 @@ Expression* TranslateToFuzzReader::makeConst(Type type) { assert(wasm.features.hasReferenceTypes()); // With a low chance, just emit a null if that is valid. if (type.isNullable() && oneIn(8)) { - return builder.makeRefNull(type); + return builder.makeRefNull(type.getHeapType()); } if (type.getHeapType().isBasic()) { return makeConstBasicRef(type); @@ -2050,7 +2050,7 @@ Expression* TranslateToFuzzReader::makeConstBasicRef(Type type) { // a subtype of anyref, but we cannot create constants of it, except // for null. assert(type.isNullable()); - return builder.makeRefNull(type); + return builder.makeRefNull(HeapType::none); } auto nullability = getSubType(type.getNullability()); // i31.new is not allowed in initializer expressions. @@ -2065,7 +2065,7 @@ Expression* TranslateToFuzzReader::makeConstBasicRef(Type type) { case HeapType::i31: { assert(wasm.features.hasGC()); if (type.isNullable() && oneIn(4)) { - return builder.makeRefNull(type); + return builder.makeRefNull(HeapType::none); } return builder.makeI31New(makeConst(Type::i32)); } @@ -2086,10 +2086,22 @@ Expression* TranslateToFuzzReader::makeConstBasicRef(Type type) { return builder.makeArrayInit(trivialArray, {}); } } - default: { - WASM_UNREACHABLE("invalid basic ref type"); + case HeapType::string: + case HeapType::stringview_wtf8: + case HeapType::stringview_wtf16: + case HeapType::stringview_iter: + WASM_UNREACHABLE("TODO: strings"); + case HeapType::none: + case HeapType::noext: + case HeapType::nofunc: { + auto null = builder.makeRefNull(heapType); + if (!type.isNullable()) { + return builder.makeRefAs(RefAsNonNull, null); + } + return null; } } + WASM_UNREACHABLE("invalid basic ref type"); } Expression* TranslateToFuzzReader::makeConstCompoundRef(Type type) { @@ -2104,15 +2116,14 @@ Expression* TranslateToFuzzReader::makeConstCompoundRef(Type type) { // We weren't able to directly materialize a non-null constant. Try again to // create a null. if (type.isNullable()) { - return builder.makeRefNull(type); + return builder.makeRefNull(heapType); } // We have to produce a non-null value. Possibly create a null and cast it // to non-null even though that will trap at runtime. We must have a // function context for this because the cast is not allowed in globals. if (funcContext) { - return builder.makeRefAs(RefAsNonNull, - builder.makeRefNull(Type(heapType, Nullable))); + return builder.makeRefAs(RefAsNonNull, builder.makeRefNull(heapType)); } // Otherwise, we are not in a function context. This can happen if we need @@ -3138,33 +3149,49 @@ Nullability TranslateToFuzzReader::getSubType(Nullability nullability) { } HeapType TranslateToFuzzReader::getSubType(HeapType type) { + if (oneIn(2)) { + return type; + } if (type.isBasic()) { switch (type.getBasic()) { case HeapType::func: // TODO: Typed function references. - return HeapType::func; + return pick(FeatureOptions<HeapType>() + .add(FeatureSet::ReferenceTypes, HeapType::func) + .add(FeatureSet::GC, HeapType::nofunc)); case HeapType::ext: - return HeapType::ext; + return pick(FeatureOptions<HeapType>() + .add(FeatureSet::ReferenceTypes, HeapType::ext) + .add(FeatureSet::GC, HeapType::noext)); case HeapType::any: // TODO: nontrivial types as well. assert(wasm.features.hasReferenceTypes()); assert(wasm.features.hasGC()); - return pick(HeapType::any, HeapType::eq, HeapType::i31, HeapType::data); + return pick(HeapType::any, + HeapType::eq, + HeapType::i31, + HeapType::data, + HeapType::none); case HeapType::eq: // TODO: nontrivial types as well. assert(wasm.features.hasReferenceTypes()); assert(wasm.features.hasGC()); - return pick(HeapType::eq, HeapType::i31, HeapType::data); + return pick( + HeapType::eq, HeapType::i31, HeapType::data, HeapType::none); case HeapType::i31: - return HeapType::i31; + return pick(HeapType::i31, HeapType::none); case HeapType::data: // TODO: nontrivial types as well. - return HeapType::data; + return pick(HeapType::data, HeapType::none); case HeapType::string: case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: case HeapType::stringview_iter: WASM_UNREACHABLE("TODO: fuzz strings"); + case HeapType::none: + case HeapType::noext: + case HeapType::nofunc: + break; } } // TODO: nontrivial types as well. diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index ad87c6fab..351035f93 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -69,7 +69,7 @@ struct HeapTypeGeneratorImpl { typeIndices.insert({builder[i], i}); // Everything is a subtype of itself. subtypeIndices[i].push_back(i); - if (i < numRoots) { + if (i < numRoots || rand.oneIn(2)) { // This is a root type with no supertype. Choose a kind for this type. typeKinds.emplace_back(generateHeapTypeKind()); } else { @@ -148,6 +148,11 @@ struct HeapTypeGeneratorImpl { } HeapType::BasicHeapType generateBasicHeapType() { + // Choose bottom types more rarely. + if (rand.oneIn(16)) { + return rand.pick(HeapType::noext, HeapType::nofunc, HeapType::none); + } + // TODO: strings return rand.pick(HeapType::func, HeapType::ext, HeapType::any, @@ -254,6 +259,8 @@ struct HeapTypeGeneratorImpl { HeapType pickSubFunc() { if (auto type = pickKind<SignatureKind>()) { return *type; + } else if (rand.oneIn(2)) { + return HeapType::nofunc; } else { return HeapType::func; } @@ -262,6 +269,8 @@ struct HeapTypeGeneratorImpl { HeapType pickSubData() { if (auto type = pickKind<DataKind>()) { return *type; + } else if (rand.oneIn(2)) { + return HeapType::none; } else { return HeapType::data; } @@ -292,7 +301,7 @@ struct HeapTypeGeneratorImpl { // can only choose those defined before the end of the current recursion // group. std::vector<Index> candidateIndices; - for (auto i : subtypeIndices[typeIndices[type]]) { + for (auto i : subtypeIndices[it->second]) { if (i < recGroupEnds[index]) { candidateIndices.push_back(i); } @@ -301,6 +310,9 @@ struct HeapTypeGeneratorImpl { } else { // This is not a constructed type, so it must be a basic type. assert(type.isBasic()); + if (rand.oneIn(8)) { + return type.getBottom(); + } switch (type.getBasic()) { case HeapType::ext: return HeapType::ext; @@ -318,7 +330,10 @@ struct HeapTypeGeneratorImpl { case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: case HeapType::stringview_iter: - WASM_UNREACHABLE("TODO: fuzz strings"); + case HeapType::none: + case HeapType::noext: + case HeapType::nofunc: + return type; } WASM_UNREACHABLE("unexpected kind"); } @@ -403,6 +418,17 @@ struct HeapTypeGeneratorImpl { } HeapTypeKind getSubKind(HeapTypeKind super) { + if (rand.oneIn(16)) { + // Occasionally go directly to the bottom type. + if (auto* basic = std::get_if<BasicKind>(&super)) { + return HeapType(*basic).getBottom(); + } else if (std::get_if<SignatureKind>(&super)) { + return HeapType::nofunc; + } else if (std::get_if<DataKind>(&super)) { + return HeapType::none; + } + WASM_UNREACHABLE("unexpected kind"); + } if (auto* basic = std::get_if<BasicKind>(&super)) { if (rand.oneIn(8)) { return super; @@ -441,7 +467,10 @@ struct HeapTypeGeneratorImpl { case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: case HeapType::stringview_iter: - WASM_UNREACHABLE("TODO: fuzz strings"); + case HeapType::none: + case HeapType::noext: + case HeapType::nofunc: + return super; } WASM_UNREACHABLE("unexpected kind"); } else { diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 5e9874ccc..45cc63c37 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -553,10 +553,7 @@ public: // This is GC data, which we must handle in a more careful way. auto* data = value.getGCData().get(); - if (!data) { - // This is a null, so simply emit one. - return builder.makeRefNull(value.type); - } + assert(data); // There was actual GC data allocated here. auto type = value.type; diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 6febcf6b9..557e8a770 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -1142,7 +1142,7 @@ struct Reducer } // try to replace with a trivial value if (curr->type.isNullable()) { - RefNull* n = builder->makeRefNull(curr->type); + RefNull* n = builder->makeRefNull(curr->type.getHeapType()); return tryToReplaceCurrent(n); } if (curr->type.isTuple() && curr->type.isDefaultable()) { |