Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions scripts/test/fuzzing.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,6 @@
# the fuzzer does not support imported memories
'multi-memory-lowering-import.wast',
'multi-memory-lowering-import-error.wast',
# the fuzzer does not support struct RMW ops
'gc-atomics.wast',
'gc-atomics-null-refs.wast',
'shared-structs.wast',
'heap2local-rmw.wast',
'optimize-instructions-struct-rmw.wast',
'gto-removals-rmw.wast',
'type-refining-rmw.wast',
'type-ssa-exact-rmw.wast',
'cfp-rmw.wast',
'unsubtyping-cmpxchg.wast',
'struct-atomic-threads.wast',
'type-refining-gufa-rmw.wast',
'struct-cmpxchg-shared-expected.wast',
'precompute-gc-atomics-rmw.wast',
# contains too many segments to run in a wasm VM
'limit-segments_disable-bulk-memory.wast',
# https://github.com/WebAssembly/binaryen/issues/7176
Expand Down
2 changes: 2 additions & 0 deletions src/tools/fuzzing.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ class TranslateToFuzzReader {
bool maybeSignedGet(const Field& field);

Expression* makeStructGet(Type type);
Expression* makeStructRMW(Type type);
Expression* makeStructCmpxchg(Type type);
Expression* makeStructSet(Type type);
Expression* makeArrayGet(Type type);
Expression* makeArraySet(Type type);
Expand Down
75 changes: 72 additions & 3 deletions src/tools/fuzzing/fuzzing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2598,6 +2598,12 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
if (typeStructFields.find(type) != typeStructFields.end()) {
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
&Self::makeStructGet);
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
FeatureSet::Atomics | FeatureSet::SharedEverything,
&Self::makeStructRMW);
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
FeatureSet::Atomics | FeatureSet::SharedEverything,
&Self::makeStructCmpxchg);
}
if (typeArrays.find(type) != typeArrays.end()) {
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
Expand Down Expand Up @@ -5583,8 +5589,66 @@ Expression* TranslateToFuzzReader::makeStructGet(Type type) {
auto [structType, fieldIndex] = pick(structFields);
auto* ref = makeTrappingRefUse(structType);
auto signed_ = maybeSignedGet(structType.getStruct().fields[fieldIndex]);
return builder.makeStructGet(
fieldIndex, ref, MemoryOrder::Unordered, type, signed_);
auto order = MemoryOrder::Unordered;
if (wasm.features.hasAtomics() && wasm.features.hasSharedEverything() &&
oneIn(2)) {
order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
}
return builder.makeStructGet(fieldIndex, ref, order, type, signed_);
}

Expression* TranslateToFuzzReader::makeStructRMW(Type type) {
bool isAny =
type.isRef() &&
Type::isSubType(
type,
Type(HeapTypes::any.getBasic(type.getHeapType().getShared()), Nullable));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Type::isSubType(
type,
Type(HeapTypes::any.getBasic(type.getHeapType().getShared()), Nullable));
type.getHeapType().getTop().isMaybeShared(HeapTypes::any)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works here, but for cmpxchg below we're checking for a subtype of eq, so we can't just use getTop().

if (type != Type::i32 && type != Type::i64 && !isAny) {
// Not a valid field type for an RMW operation.
return makeStructGet(type);
}
auto& structFields = typeStructFields[type];
assert(!structFields.empty());
auto [structType, fieldIndex] = pick(structFields);
const auto& field = structType.getStruct().fields[fieldIndex];
if (field.isPacked() || field.mutable_ == Immutable) {
// Cannot RMW a packed or immutable field.
return makeStructGet(type);
}
AtomicRMWOp op = RMWXchg;
if (type == Type::i32 || type == Type::i64) {
op = pick(RMWAdd, RMWSub, RMWAnd, RMWOr, RMWXor, RMWXchg);
}
auto* ref = makeTrappingRefUse(structType);
auto* value = make(type);
auto order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
return builder.makeStructRMW(op, fieldIndex, ref, value, order);
}

Expression* TranslateToFuzzReader::makeStructCmpxchg(Type type) {
bool isEq =
type.isRef() &&
Type::isSubType(
type,
Type(HeapTypes::eq.getBasic(type.getHeapType().getShared()), Nullable));
if (type != Type::i32 && type != Type::i64 && !isEq) {
// Not a valid field type for a cmpxchg operation.
return makeStructGet(type);
}
auto& structFields = typeStructFields[type];
assert(!structFields.empty());
auto [structType, fieldIndex] = pick(structFields);
const auto& field = structType.getStruct().fields[fieldIndex];
if (field.isPacked() || field.mutable_ == Immutable) {
// Cannot RMW a packed or immutable field.
return makeStructGet(type);
}
auto* ref = makeTrappingRefUse(structType);
auto* expected = make(type);
auto* replacement = make(type);
auto order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
return builder.makeStructCmpxchg(
fieldIndex, ref, expected, replacement, order);
}

Expression* TranslateToFuzzReader::makeStructSet(Type type) {
Expand All @@ -5596,7 +5660,12 @@ Expression* TranslateToFuzzReader::makeStructSet(Type type) {
auto fieldType = structType.getStruct().fields[fieldIndex].type;
auto* ref = makeTrappingRefUse(structType);
auto* value = make(fieldType);
return builder.makeStructSet(fieldIndex, ref, value, MemoryOrder::Unordered);
auto order = MemoryOrder::Unordered;
if (wasm.features.hasAtomics() && wasm.features.hasSharedEverything() &&
oneIn(2)) {
order = oneIn(2) ? MemoryOrder::SeqCst : MemoryOrder::AcqRel;
}
return builder.makeStructSet(fieldIndex, ref, value, order);
}

// Make a bounds check for an array operation, given a ref + index. An optional
Expand Down
Loading