Skip to content

Commit f2cce24

Browse files
authored
Tweak heap type fuzzer for JS prototypes (#8426)
Make the fuzzer more likely to produce descriptor fields that can be used to configure JS prototypes. This will help the main fuzzer, which uses types generated by the heap type fuzzer, to find bugs where configured prototypes are incorrectly removed.
1 parent 493e320 commit f2cce24

File tree

2 files changed

+58
-57
lines changed

2 files changed

+58
-57
lines changed

src/tools/fuzzing/heap-types.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
#include "ir/gc-type-utils.h"
2121
#include "ir/subtypes.h"
22-
#include "support/insert_ordered.h"
2322
#include "tools/fuzzing.h"
2423
#include "tools/fuzzing/heap-types.h"
2524

@@ -275,12 +274,13 @@ struct HeapTypeGeneratorImpl {
275274
builder[index].setOpen(subtypeIndices[index].size() > 1 || rand.oneIn(2));
276275
auto kind = typeKinds[index];
277276
auto share = HeapType(builder[index]).getShared();
277+
bool isDesc = describedIndices[index].has_value();
278278
if (!supertypeIndices[index]) {
279279
// No nontrivial supertype, so create a root type.
280280
if (std::get_if<SignatureKind>(&kind)) {
281281
builder[index] = generateSignature();
282282
} else if (std::get_if<StructKind>(&kind)) {
283-
builder[index] = generateStruct(share);
283+
builder[index] = generateStruct(share, isDesc);
284284
} else if (std::get_if<ArrayKind>(&kind)) {
285285
builder[index] = generateArray(share);
286286
} else {
@@ -415,7 +415,13 @@ struct HeapTypeGeneratorImpl {
415415
return {params, generateReturnType()};
416416
}
417417

418-
Field generateField(Shareability share) {
418+
Field generateField(Shareability share, bool isPrototypeField = false) {
419+
// If this field could configure a prototype, then we want to give it a type
420+
// that lets it do so a significant portion of the time.
421+
if (isPrototypeField && share == Unshared && rand.oneIn(2)) {
422+
auto nullability = rand.oneIn(2) ? NonNullable : Nullable;
423+
return {Type(HeapType::ext, nullability), Immutable};
424+
}
419425
auto mutability = rand.oneIn(2) ? Mutable : Immutable;
420426
if (rand.oneIn(6)) {
421427
return {rand.oneIn(2) ? Field::i8 : Field::i16, mutability};
@@ -424,10 +430,13 @@ struct HeapTypeGeneratorImpl {
424430
}
425431
}
426432

427-
Struct generateStruct(Shareability share) {
433+
Struct generateStruct(Shareability share, bool isDesc) {
428434
std::vector<Field> fields(rand.upTo(params.MAX_STRUCT_SIZE + 1));
435+
// Prototypes are configured on the first field of descriptors types.
436+
bool isPrototypeField = isDesc;
429437
for (auto& field : fields) {
430-
field = generateField(share);
438+
field = generateField(share, isPrototypeField);
439+
isPrototypeField = false;
431440
}
432441
return {fields};
433442
}

test/lit/fuzz-types.test

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,56 @@
1-
;; RUN: wasm-fuzz-types -v --seed=0 | filecheck %s
1+
;; RUN: wasm-fuzz-types -v --seed=2 | filecheck %s
22

3-
;; CHECK: Running with seed 0
3+
;; CHECK: Running with seed 2
44
;; CHECK-NEXT: Built 20 types:
5-
;; CHECK-NEXT: (rec
6-
;; CHECK-NEXT: (type $0 (sub (shared (array i8))))
7-
;; CHECK-NEXT: (type $1 (shared (array (ref $1))))
8-
;; CHECK-NEXT: (type $2 (sub (shared (func (param i64 (ref null $5) i64) (result (ref $2))))))
9-
;; CHECK-NEXT: (type $3 (sub $0 (shared (array i8))))
10-
;; CHECK-NEXT: (type $4 (sub (array (ref null $9))))
11-
;; CHECK-NEXT: (type $5 (sub final $0 (shared (array i8))))
12-
;; CHECK-NEXT: (type $6 (sub $2 (shared (func (param i64 (ref null (shared eq)) i64) (result (ref $8))))))
13-
;; CHECK-NEXT: (type $7 (sub (shared (descriptor $9) (struct (field (ref null $7)) (field (mut i64)) (field (mut i8)) (field i32) (field (mut i32))))))
14-
;; CHECK-NEXT: (type $8 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $8))))))
15-
;; CHECK-NEXT: (type $9 (shared (describes $7) (descriptor $12) (struct (field i32) (field (mut (ref $8))) (field f64))))
16-
;; CHECK-NEXT: (type $10 (sub (array (mut externref))))
17-
;; CHECK-NEXT: (type $11 (sub $4 (array (ref $9))))
18-
;; CHECK-NEXT: (type $12 (sub (shared (describes $9) (struct (field (mut f64)) (field (mut i32)) (field (mut f64))))))
19-
;; CHECK-NEXT: )
20-
;; CHECK-NEXT: (rec
21-
;; CHECK-NEXT: (type $13 (sub (struct (field (mut i16)) (field i64) (field (mut (ref (shared func)))))))
22-
;; CHECK-NEXT: (type $14 (sub (shared (array (ref null $14)))))
23-
;; CHECK-NEXT: )
24-
;; CHECK-NEXT: (rec
25-
;; CHECK-NEXT: (type $15 (shared (array (ref null (shared extern)))))
26-
;; CHECK-NEXT: (type $16 (sub final $14 (shared (array (ref null $16)))))
5+
;; CHECK-NEXT: (type $0 (shared (struct)))
6+
;; CHECK-NEXT: (rec
7+
;; CHECK-NEXT: (type $1 (array (ref $2)))
8+
;; CHECK-NEXT: (type $2 (sub (shared (array (mut i16)))))
9+
;; CHECK-NEXT: (type $3 (sub (shared (array i32))))
10+
;; CHECK-NEXT: (type $4 (sub (descriptor $5) (struct (field (mut (ref $0))))))
11+
;; CHECK-NEXT: (type $5 (sub (describes $4) (struct (field f64) (field (mut i64)))))
12+
;; CHECK-NEXT: (type $6 (sub (array v128)))
13+
;; CHECK-NEXT: (type $7 (shared (struct (field f32) (field (mut (ref $0))))))
14+
;; CHECK-NEXT: (type $8 (sub (shared (struct (field f64) (field (mut (ref (shared struct)))) (field (mut f64)) (field i16) (field i32) (field i64)))))
2715
;; CHECK-NEXT: )
2816
;; CHECK-NEXT: (rec
29-
;; CHECK-NEXT: (type $17 (shared (struct (field (mut (ref null $2))) (field i32) (field (mut (ref $14))))))
30-
;; CHECK-NEXT: (type $18 (sub $11 (array (ref $9))))
31-
;; CHECK-NEXT: (type $19 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $6))))))
17+
;; CHECK-NEXT: (type $9 (descriptor $12) (struct (field i64) (field i16)))
18+
;; CHECK-NEXT: (type $10 (array (mut (ref null $5))))
19+
;; CHECK-NEXT: (type $11 (sub (shared (func (param (ref $7) f64 (ref $9)) (result (ref null $10))))))
20+
;; CHECK-NEXT: (type $12 (sub (describes $9) (descriptor $13) (struct (field (ref (shared any))) (field (mut (ref extern))) (field v128) (field (ref null $17)))))
21+
;; CHECK-NEXT: (type $13 (sub (describes $12) (descriptor $17) (struct (field externref) (field (mut i8)) (field (mut i32)) (field (mut f32)) (field i16) (field (mut (ref null $6))))))
22+
;; CHECK-NEXT: (type $14 (sub (func (result i64))))
23+
;; CHECK-NEXT: (type $15 (sub (shared (func))))
24+
;; CHECK-NEXT: (type $16 (shared (func (result (ref null $0)))))
25+
;; CHECK-NEXT: (type $17 (sub (describes $13) (struct (field (ref extern)))))
26+
;; CHECK-NEXT: (type $18 (sub (func (param v128 (ref null $10)))))
27+
;; CHECK-NEXT: (type $19 (sub final $11 (shared (func (param (ref null (shared any)) f64 (ref any)) (result (ref $10))))))
3228
;; CHECK-NEXT: )
3329
;; CHECK-NEXT:
3430
;; CHECK-NEXT: Inhabitable types:
3531
;; CHECK-NEXT:
3632
;; CHECK-NEXT: Built 20 types:
37-
;; CHECK-NEXT: (rec
38-
;; CHECK-NEXT: (type $0 (sub (shared (array i8))))
39-
;; CHECK-NEXT: (type $1 (shared (array (ref null $1))))
40-
;; CHECK-NEXT: (type $2 (sub (shared (func (param i64 (ref null $5) i64) (result (ref $2))))))
41-
;; CHECK-NEXT: (type $3 (sub $0 (shared (array i8))))
42-
;; CHECK-NEXT: (type $4 (sub (array (ref null $9))))
43-
;; CHECK-NEXT: (type $5 (sub final $0 (shared (array i8))))
44-
;; CHECK-NEXT: (type $6 (sub $2 (shared (func (param i64 (ref null (shared eq)) i64) (result (ref $8))))))
45-
;; CHECK-NEXT: (type $7 (sub (shared (descriptor $9) (struct (field (ref null $7)) (field (mut i64)) (field (mut i8)) (field i32) (field (mut i32))))))
46-
;; CHECK-NEXT: (type $8 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $8))))))
47-
;; CHECK-NEXT: (type $9 (shared (describes $7) (descriptor $12) (struct (field i32) (field (mut (ref $8))) (field f64))))
48-
;; CHECK-NEXT: (type $10 (sub (array (mut externref))))
49-
;; CHECK-NEXT: (type $11 (sub $4 (array (ref $9))))
50-
;; CHECK-NEXT: (type $12 (sub (shared (describes $9) (struct (field (mut f64)) (field (mut i32)) (field (mut f64))))))
51-
;; CHECK-NEXT: )
52-
;; CHECK-NEXT: (rec
53-
;; CHECK-NEXT: (type $13 (sub (struct (field (mut i16)) (field i64) (field (mut (ref (shared func)))))))
54-
;; CHECK-NEXT: (type $14 (sub (shared (array (ref null $14)))))
33+
;; CHECK-NEXT: (type $0 (shared (struct)))
34+
;; CHECK-NEXT: (rec
35+
;; CHECK-NEXT: (type $1 (array (ref $2)))
36+
;; CHECK-NEXT: (type $2 (sub (shared (array (mut i16)))))
37+
;; CHECK-NEXT: (type $3 (sub (shared (array i32))))
38+
;; CHECK-NEXT: (type $4 (sub (descriptor $5) (struct (field (mut (ref $0))))))
39+
;; CHECK-NEXT: (type $5 (sub (describes $4) (struct (field f64) (field (mut i64)))))
40+
;; CHECK-NEXT: (type $6 (sub (array v128)))
41+
;; CHECK-NEXT: (type $7 (shared (struct (field f32) (field (mut (ref $0))))))
42+
;; CHECK-NEXT: (type $8 (sub (shared (struct (field f64) (field (mut (ref (shared struct)))) (field (mut f64)) (field i16) (field i32) (field i64)))))
5543
;; CHECK-NEXT: )
5644
;; CHECK-NEXT: (rec
57-
;; CHECK-NEXT: (type $15 (shared (array (ref null (shared extern)))))
58-
;; CHECK-NEXT: (type $16 (sub final $14 (shared (array (ref null $16)))))
45+
;; CHECK-NEXT: (type $9 (descriptor $12) (struct (field i64) (field i16)))
46+
;; CHECK-NEXT: (type $10 (array (mut (ref null $5))))
47+
;; CHECK-NEXT: (type $11 (sub (shared (func (param (ref $7) f64 (ref $9)) (result (ref null $10))))))
48+
;; CHECK-NEXT: (type $12 (sub (describes $9) (descriptor $13) (struct (field (ref (shared any))) (field (mut externref)) (field v128) (field (ref null $17)))))
49+
;; CHECK-NEXT: (type $13 (sub (describes $12) (descriptor $17) (struct (field externref) (field (mut i8)) (field (mut i32)) (field (mut f32)) (field i16) (field (mut (ref null $6))))))
50+
;; CHECK-NEXT: (type $14 (sub (func (result i64))))
51+
;; CHECK-NEXT: (type $15 (sub (shared (func))))
52+
;; CHECK-NEXT: (type $16 (shared (func (result (ref null $0)))))
53+
;; CHECK-NEXT: (type $17 (sub (describes $13) (struct (field externref))))
54+
;; CHECK-NEXT: (type $18 (sub (func (param v128 (ref null $10)))))
55+
;; CHECK-NEXT: (type $19 (sub final $11 (shared (func (param (ref null (shared any)) f64 (ref any)) (result (ref $10))))))
5956
;; CHECK-NEXT: )
60-
;; CHECK-NEXT: (rec
61-
;; CHECK-NEXT: (type $17 (shared (struct (field (mut (ref null $2))) (field i32) (field (mut (ref $14))))))
62-
;; CHECK-NEXT: (type $18 (sub $11 (array (ref $9))))
63-
;; CHECK-NEXT: (type $19 (sub $2 (shared (func (param i64 (ref null $0) i64) (result (ref $6))))))
64-
;; CHECK-NEXT: )

0 commit comments

Comments
 (0)