summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-04-29 11:29:57 -0700
committerGitHub <noreply@github.com>2024-04-29 11:29:57 -0700
commit63d308f4f2ce6daae3dd3c6ec0b3808134d8791a (patch)
treee2ee30fcbf46dabe5fa70a62606dc27f48a33206 /src
parent4e4cb620d52de7b605eee7dc29cea3be1714f856 (diff)
downloadbinaryen-63d308f4f2ce6daae3dd3c6ec0b3808134d8791a.tar.gz
binaryen-63d308f4f2ce6daae3dd3c6ec0b3808134d8791a.tar.bz2
binaryen-63d308f4f2ce6daae3dd3c6ec0b3808134d8791a.zip
[Strings] Work around ref.cast not working on string views, and add fuzzing (#6549)
As suggested in #6434 (comment) , lower ref.cast of string views to ref.as_non_null in binary writing. It is a simple hack that avoids the problem of V8 not allowing them to be cast. Add fuzzing support for the last three core string operations, after which that problem becomes very frequent. Also add yet another makeTrappingRefUse that was missing in that fuzzer code.
Diffstat (limited to 'src')
-rw-r--r--src/tools/fuzzing.h3
-rw-r--r--src/tools/fuzzing/fuzzing.cpp35
-rw-r--r--src/wasm/wasm-stack.cpp18
3 files changed, 52 insertions, 4 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index c60744dea..786527236 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -327,7 +327,10 @@ private:
Expression* makeStringNewArray();
Expression* makeStringNewCodePoint();
Expression* makeStringConcat();
+ Expression* makeStringSlice();
Expression* makeStringEq(Type type);
+ Expression* makeStringMeasure(Type type);
+ Expression* makeStringGet(Type type);
Expression* makeStringEncode(Type type);
// Similar to makeBasic/CompoundRef, but indicates that this value will be
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index add0494ea..6c62e5191 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -1369,7 +1369,9 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
FeatureSet::Strings,
&Self::makeStringEncode,
- &Self::makeStringEq);
+ &Self::makeStringEq,
+ &Self::makeStringMeasure,
+ &Self::makeStringGet);
}
if (type.isTuple()) {
options.add(FeatureSet::Multivalue, &Self::makeTupleMake);
@@ -2620,7 +2622,7 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) {
if (!funcContext) {
return makeStringConst();
}
- switch (upTo(9)) {
+ switch (upTo(11)) {
case 0:
case 1:
case 2:
@@ -2639,13 +2641,16 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) {
// generate two string children, i.e., it can lead to exponential
// growth.
return makeStringConcat();
+ case 9:
+ case 10:
+ return makeStringSlice();
}
WASM_UNREACHABLE("bad switch");
}
case HeapType::stringview_wtf16:
// We fully support wtf16 strings.
- return builder.makeStringAs(
- StringAsWTF16, makeBasicRef(Type(HeapType::string, NonNullable)));
+ return builder.makeStringAs(StringAsWTF16,
+ makeTrappingRefUse(HeapType::string));
case HeapType::stringview_wtf8:
case HeapType::stringview_iter:
// We do not have interpreter support for wtf8 and iter, so emit something
@@ -2818,6 +2823,13 @@ Expression* TranslateToFuzzReader::makeStringConcat() {
return builder.makeStringConcat(left, right);
}
+Expression* TranslateToFuzzReader::makeStringSlice() {
+ auto* ref = makeTrappingRefUse(HeapType::stringview_wtf16);
+ auto* start = make(Type::i32);
+ auto* end = make(Type::i32);
+ return builder.makeStringSliceWTF(StringSliceWTF16, ref, start, end);
+}
+
Expression* TranslateToFuzzReader::makeStringEq(Type type) {
assert(type == Type::i32);
@@ -2833,6 +2845,21 @@ Expression* TranslateToFuzzReader::makeStringEq(Type type) {
return builder.makeStringEq(StringEqCompare, left, right);
}
+Expression* TranslateToFuzzReader::makeStringMeasure(Type type) {
+ assert(type == Type::i32);
+
+ auto* ref = makeTrappingRefUse(HeapType::string);
+ return builder.makeStringMeasure(StringMeasureWTF16, ref);
+}
+
+Expression* TranslateToFuzzReader::makeStringGet(Type type) {
+ assert(type == Type::i32);
+
+ auto* ref = makeTrappingRefUse(HeapType::stringview_wtf16);
+ auto* pos = make(Type::i32);
+ return builder.makeStringWTF16Get(ref, pos);
+}
+
Expression* TranslateToFuzzReader::makeTrappingRefUse(HeapType type) {
auto percent = upTo(100);
// Only give a low probability to emit a nullable reference.
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 4e3194e84..f1413847f 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2089,6 +2089,24 @@ void BinaryInstWriter::visitRefTest(RefTest* curr) {
}
void BinaryInstWriter::visitRefCast(RefCast* curr) {
+ // We allow ref.cast of string views, but V8 does not. Work around that by
+ // emitting a ref.as_non_null (or nothing).
+ auto type = curr->type;
+ if (type.isRef()) {
+ auto heapType = type.getHeapType();
+ if (heapType == HeapType::stringview_wtf8 ||
+ heapType == HeapType::stringview_wtf16 ||
+ heapType == HeapType::stringview_iter) {
+ // We cannot cast string views to/from anything, so the input must also
+ // be a view.
+ assert(curr->ref->type.getHeapType() == heapType);
+ if (type.isNonNullable() && curr->ref->type.isNullable()) {
+ o << int8_t(BinaryConsts::RefAsNonNull);
+ }
+ return;
+ }
+ }
+
o << int8_t(BinaryConsts::GCPrefix);
if (curr->type.isNullable()) {
o << U32LEB(BinaryConsts::RefCastNull);