summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/fuzzing.h3
-rw-r--r--src/tools/fuzzing/fuzzing.cpp64
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt61
3 files changed, 82 insertions, 46 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index ea9598f85..dc17f7c91 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -327,6 +327,7 @@ private:
Expression* makeStringNewArray();
Expression* makeStringNewCodePoint();
Expression* makeStringConcat();
+ Expression* makeStringEncode(Type type);
// Similar to makeBasic/CompoundRef, but indicates that this value will be
// used in a place that will trap on null. For example, the reference of a
@@ -391,13 +392,13 @@ private:
Type getLoggableType();
bool isLoggableType(Type type);
Nullability getNullability();
- Mutability getMutability();
Nullability getSubType(Nullability nullability);
HeapType getSubType(HeapType type);
Type getSubType(Type type);
Nullability getSuperType(Nullability nullability);
HeapType getSuperType(HeapType type);
Type getSuperType(Type type);
+ Type getArrayTypeForString();
// Utilities
Name getTargetName(Expression* target);
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index a35a94d71..541b58b0f 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -1366,6 +1366,9 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
&Self::makeRefEq,
&Self::makeRefTest,
&Self::makeI31Get);
+ options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
+ FeatureSet::Strings,
+ &Self::makeStringEncode);
}
if (type.isTuple()) {
options.add(FeatureSet::Multivalue, &Self::makeTupleMake);
@@ -2752,12 +2755,7 @@ Expression* TranslateToFuzzReader::makeCompoundRef(Type type) {
}
Expression* TranslateToFuzzReader::makeStringNewArray() {
- auto mutability = getMutability();
- auto arrayHeapType =
- HeapType(Array(Field(Field::PackedType::i16, mutability)));
- auto nullability = getNullability();
- auto arrayType = Type(arrayHeapType, nullability);
- auto array = make(arrayType);
+ auto* array = make(getArrayTypeForString());
auto* start = make(Type::i32);
auto* end = make(Type::i32);
return builder.makeStringNew(StringNewWTF16Array, array, start, end, false);
@@ -2814,8 +2812,8 @@ Expression* TranslateToFuzzReader::makeStringConst() {
}
Expression* TranslateToFuzzReader::makeStringConcat() {
- auto left = make(Type(HeapType::string, getNullability()));
- auto right = make(Type(HeapType::string, getNullability()));
+ auto* left = make(Type(HeapType::string, getNullability()));
+ auto* right = make(Type(HeapType::string, getNullability()));
return builder.makeStringConcat(left, right);
}
@@ -3806,9 +3804,9 @@ static auto makeArrayBoundsCheck(Expression* ref,
// An additional use of the reference (we stored the reference in a local,
// so this reads from that local).
Expression* getRef;
- // An addition use of the index (as with the ref, it reads from a local).
+ // An additional use of the index (as with the ref, it reads from a local).
Expression* getIndex;
- // An addition use of the length, if it was provided.
+ // An additional use of the length, if it was provided.
Expression* getLength = nullptr;
} result = {builder.makeBinary(LtUInt32, effectiveIndex, getSize),
builder.makeLocalGet(tempRef, ref->type),
@@ -3919,6 +3917,40 @@ Expression* TranslateToFuzzReader::makeArrayBulkMemoryOp(Type type) {
}
}
+Expression* TranslateToFuzzReader::makeStringEncode(Type type) {
+ assert(type == Type::i32);
+
+ auto* ref = make(Type(HeapType::string, getNullability()));
+ auto* array = make(getArrayTypeForString());
+ auto* start = make(Type::i32);
+
+ // Only rarely emit without a bounds check, which might trap. See related
+ // logic in other array operations.
+ if (allowOOB || oneIn(10)) {
+ return builder.makeStringEncode(StringEncodeWTF16Array, ref, array, start);
+ }
+
+ // Stash the string reference while computing its length for a bounds check.
+ auto refLocal = builder.addVar(funcContext->func, ref->type);
+ auto* setRef = builder.makeLocalSet(refLocal, ref);
+ auto* strLen = builder.makeStringMeasure(
+ StringMeasureWTF16, builder.makeLocalGet(refLocal, ref->type));
+
+ // Do a bounds check on the array.
+ auto check =
+ makeArrayBoundsCheck(array, start, funcContext->func, builder, strLen);
+ array = check.getRef;
+ start = check.getIndex;
+ auto* getRef = builder.makeLocalGet(refLocal, ref->type);
+ auto* encode =
+ builder.makeStringEncode(StringEncodeWTF16Array, getRef, array, start);
+
+ // Emit the set of the string reference and then an if that picks which code
+ // path to visit, depending on the outcome of the bounds check.
+ auto* iff = builder.makeIf(check.condition, encode, make(Type::i32));
+ return builder.makeSequence(setRef, iff);
+}
+
Expression* TranslateToFuzzReader::makeI31Get(Type type) {
assert(type == Type::i32);
assert(wasm.features.hasReferenceTypes() && wasm.features.hasGC());
@@ -4136,10 +4168,6 @@ Nullability TranslateToFuzzReader::getNullability() {
return Nullable;
}
-Mutability TranslateToFuzzReader::getMutability() {
- return oneIn(2) ? Mutable : Immutable;
-}
-
Nullability TranslateToFuzzReader::getSubType(Nullability nullability) {
if (nullability == NonNullable) {
return NonNullable;
@@ -4279,6 +4307,14 @@ Type TranslateToFuzzReader::getSuperType(Type type) {
return superType;
}
+Type TranslateToFuzzReader::getArrayTypeForString() {
+ // Emit an array that can be used with JS-style strings, containing 16-bit
+ // elements. For now, this must be a mutable type as that is all V8 accepts.
+ auto arrayHeapType = HeapType(Array(Field(Field::PackedType::i16, Mutable)));
+ auto nullability = getNullability();
+ return Type(arrayHeapType, nullability);
+}
+
Name TranslateToFuzzReader::getTargetName(Expression* target) {
if (auto* block = target->dynCast<Block>()) {
return block->name;
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 84f62758f..648cb053b 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -1,44 +1,43 @@
total
- [exports] : 3
- [funcs] : 5
+ [exports] : 7
+ [funcs] : 12
[globals] : 14
[imports] : 5
[memories] : 1
[memory-data] : 20
- [table-data] : 1
+ [table-data] : 6
[tables] : 1
[tags] : 1
- [total] : 387
- [vars] : 23
+ [total] : 493
+ [vars] : 31
ArrayNew : 1
- ArrayNewFixed : 3
- AtomicCmpxchg : 1
- AtomicNotify : 1
- Binary : 57
- Block : 33
+ ArrayNewFixed : 1
+ Binary : 61
+ Block : 59
Break : 2
- Call : 4
- Const : 95
- Drop : 2
- GlobalGet : 15
- GlobalSet : 15
- If : 9
+ Call : 29
+ CallRef : 1
+ Const : 101
+ Drop : 10
+ GlobalGet : 28
+ GlobalSet : 26
+ I31Get : 1
+ If : 17
Load : 16
- LocalGet : 41
- LocalSet : 20
- Loop : 3
- Nop : 2
- Pop : 1
- RefAs : 3
- RefFunc : 2
+ LocalGet : 36
+ LocalSet : 29
+ Loop : 2
+ Nop : 5
+ RefAs : 1
+ RefCast : 2
+ RefFunc : 8
RefI31 : 4
- RefNull : 5
+ RefNull : 4
Return : 3
- Store : 1
+ SIMDExtract : 1
StringConst : 1
- StructNew : 11
- Try : 1
- TupleExtract : 7
- TupleMake : 11
- Unary : 9
- Unreachable : 8
+ StructNew : 5
+ TupleExtract : 1
+ TupleMake : 7
+ Unary : 16
+ Unreachable : 15