summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-12-09 14:46:24 -0800
committerGitHub <noreply@github.com>2024-12-09 14:46:24 -0800
commit7f62a423ee4bd908f485d01945b71786176b926a (patch)
treeaae42c49412b0153c34ef5a26fea888bb404bdd7 /test
parent729ea41d145d369b203dca6f70b251ea365cb3d0 (diff)
downloadbinaryen-7f62a423ee4bd908f485d01945b71786176b926a.tar.gz
binaryen-7f62a423ee4bd908f485d01945b71786176b926a.tar.bz2
binaryen-7f62a423ee4bd908f485d01945b71786176b926a.zip
Fuzzer: Add call-ref, call-ref-catch imports (#7137)
Similar to call-export*, these imports call a wasm function from outside the module. The difference is that we send a function reference for them to call (rather than an export index). This gives more coverage, first by sending a ref from wasm to JS, and also since we will now try to call anything that is sent. Exports, in comparison, are filtered by the fuzzer to things that JS can handle, so this may lead to more traps, but maybe also some new situations. This also leads to adding more logic to execution-results.h to model JS trapping properly. fuzz_shell.js is refactored to allow sharing code between call-export* and call-ref*.
Diffstat (limited to 'test')
-rw-r--r--test/lit/exec/fuzzing-api.wast199
-rw-r--r--test/lit/passes/gufa-closed-open.wast6
-rw-r--r--test/passes/fuzz_metrics_noprint.bin.txt52
-rw-r--r--test/passes/fuzz_metrics_passes_noprint.bin.txt53
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt87
5 files changed, 298 insertions, 99 deletions
diff --git a/test/lit/exec/fuzzing-api.wast b/test/lit/exec/fuzzing-api.wast
index 38a8ce41b..eae95fc0a 100644
--- a/test/lit/exec/fuzzing-api.wast
+++ b/test/lit/exec/fuzzing-api.wast
@@ -16,6 +16,9 @@
(import "fuzzing-support" "call-export" (func $call.export (param i32)))
(import "fuzzing-support" "call-export-catch" (func $call.export.catch (param i32) (result i32)))
+ (import "fuzzing-support" "call-ref" (func $call.ref (param funcref)))
+ (import "fuzzing-support" "call-ref-catch" (func $call.ref.catch (param funcref) (result i32)))
+
(table $table 10 20 funcref)
;; Note that the exported table appears first here, but in the binary and in
@@ -102,7 +105,6 @@
;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
- ;; CHECK-NEXT: warning: no passes specified, not doing any work
(func $export.calling.catching (export "export.calling.catching")
;; At index 0 in the exports we have $logging, so we will do those loggings,
;; then log a 0 as no exception happens.
@@ -118,6 +120,162 @@
)
)
)
+
+ ;; CHECK: [fuzz-exec] calling ref.calling
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+ ;; CHECK-NEXT: [exception thrown: __private ()]
+ (func $ref.calling (export "ref.calling")
+ ;; This will emit some logging.
+ (call $call.ref
+ (ref.func $logging)
+ )
+ ;; This will throw.
+ (call $call.ref
+ (ref.null func)
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.catching
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.catching (export "ref.calling.catching")
+ ;; This will emit some logging, then log 0 as we do not error.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $logging)
+ )
+ )
+ ;; The exception here is caught, and we'll log 1.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.null func)
+ )
+ )
+ )
+
+ (func $legal (param $x i32) (result i32)
+ ;; Helper for the function below. All types here are legal for JS.
+ (call $log-i32
+ (i32.const 12)
+ )
+ ;; Also log the param to show it is 0, which is what $call.ref does for all
+ ;; params.
+ (call $log-i32
+ (local.get $x)
+ )
+ (i32.const 34)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.legal
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 12]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+ (func $ref.calling.legal (export "ref.calling.legal")
+ ;; It is fine to call-ref a function with params and results. The params get
+ ;; default values, and the results are ignored. All we will see here is the
+ ;; logging from the function, "12".
+ (call $call.ref
+ (ref.func $legal)
+ )
+ )
+
+ (func $illegal (param $x i64)
+ ;; Helper for the function below. The param, an i64, causes a problem: when we
+ ;; call from JS we provide 0, but 0 throws when it tries to convert to BigInt.
+ (call $log-i32
+ (i32.const 56)
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.illegal
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.illegal (export "ref.calling.illegal")
+ ;; The i64 param causes an error here, so we will only log 1 because we catch an exception.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $illegal)
+ )
+ )
+ )
+
+ (func $illegal-v128 (param $x v128)
+ ;; Helper for the function below.
+ (call $log-i32
+ (i32.const 56)
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.illegal-v128
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.illegal-v128 (export "ref.calling.illegal-v128")
+ ;; As above, we throw on the v128 param, and log 1.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $illegal-v128)
+ )
+ )
+ )
+
+ (func $illegal-result (result v128)
+ ;; Helper for the function below. The result is illegal for JS.
+ (call $log-i32
+ (i32.const 910)
+ )
+ (v128.const i32x4 1 2 3 4)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.illegal-result
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.illegal-result (export "ref.calling.illegal-result")
+ ;; The v128 result causes an error here, so we will log 1 as an exception. The JS
+ ;; semantics determine that we do that check *before* the call, so the logging
+ ;; of 910 does not go through.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $illegal-result)
+ )
+ )
+ )
+
+ (func $legal-result (result i64)
+ ;; Helper for the function below.
+ (call $log-i32
+ (i32.const 910)
+ )
+ (i64.const 90)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.legal-result
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 910]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+ (func $ref.calling.legal-result (export "ref.calling.legal-result")
+ ;; Unlike v128, i64 is legal in a result. The JS VM just returns a BigInt.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $legal-result)
+ )
+ )
+ )
+
+ (func $trap
+ ;; Helper for the function below.
+ (unreachable)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.trap
+ ;; CHECK-NEXT: [trap unreachable]
+ ;; CHECK-NEXT: warning: no passes specified, not doing any work
+ (func $ref.calling.trap (export "ref.calling.trap")
+ ;; We try to catch an exception here, but the target function traps, which is
+ ;; not something we can catch. We will trap here, and not log at all.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $trap)
+ )
+ )
+ )
)
;; CHECK: [fuzz-exec] calling logging
;; CHECK-NEXT: [LoggingExternalInterface logging 42]
@@ -144,9 +302,48 @@
;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling
+;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+;; CHECK-NEXT: [exception thrown: __private ()]
+
+;; CHECK: [fuzz-exec] calling ref.calling.catching
+;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.legal
+;; CHECK-NEXT: [LoggingExternalInterface logging 12]
+;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+
+;; CHECK: [fuzz-exec] calling ref.calling.illegal
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.illegal-v128
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.illegal-result
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.legal-result
+;; CHECK-NEXT: [LoggingExternalInterface logging 910]
+;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+
+;; CHECK: [fuzz-exec] calling ref.calling.trap
+;; CHECK-NEXT: [trap unreachable]
;; CHECK-NEXT: [fuzz-exec] comparing export.calling
;; CHECK-NEXT: [fuzz-exec] comparing export.calling.catching
;; CHECK-NEXT: [fuzz-exec] comparing logging
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.catching
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.illegal
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.illegal-result
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.illegal-v128
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.legal
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.legal-result
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.trap
;; CHECK-NEXT: [fuzz-exec] comparing table.getting
;; CHECK-NEXT: [fuzz-exec] comparing table.setting
;; CHECK-NEXT: [fuzz-exec] comparing throwing
diff --git a/test/lit/passes/gufa-closed-open.wast b/test/lit/passes/gufa-closed-open.wast
index 47add9df5..689ee194f 100644
--- a/test/lit/passes/gufa-closed-open.wast
+++ b/test/lit/passes/gufa-closed-open.wast
@@ -12,15 +12,15 @@
;; OPEND: (type $2 (func (param i32)))
- ;; OPEND: (import "fuzzing-support" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
+ ;; OPEND: (import "outside" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
;; CLOSE: (type $0 (func (param funcref)))
;; CLOSE: (type $1 (func))
;; CLOSE: (type $2 (func (param i32)))
- ;; CLOSE: (import "fuzzing-support" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
- (import "fuzzing-support" "call-ref-catch" (func $external-caller (param funcref)))
+ ;; CLOSE: (import "outside" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
+ (import "outside" "call-ref-catch" (func $external-caller (param funcref)))
;; OPEND: (elem declare func $func)
diff --git a/test/passes/fuzz_metrics_noprint.bin.txt b/test/passes/fuzz_metrics_noprint.bin.txt
index 0fa206e0a..a2f996bcb 100644
--- a/test/passes/fuzz_metrics_noprint.bin.txt
+++ b/test/passes/fuzz_metrics_noprint.bin.txt
@@ -1,35 +1,35 @@
Metrics
total
- [exports] : 45
- [funcs] : 60
+ [exports] : 49
+ [funcs] : 74
[globals] : 18
- [imports] : 5
+ [imports] : 4
[memories] : 1
[memory-data] : 24
- [table-data] : 15
+ [table-data] : 19
[tables] : 1
[tags] : 0
- [total] : 5475
- [vars] : 222
- Binary : 410
- Block : 870
- Break : 148
- Call : 271
- CallIndirect : 30
- Const : 915
- Drop : 51
- GlobalGet : 458
- GlobalSet : 323
- If : 293
- Load : 96
- LocalGet : 442
- LocalSet : 284
- Loop : 99
- Nop : 76
- RefFunc : 15
- Return : 78
- Select : 47
- Store : 44
+ [total] : 5695
+ [vars] : 227
+ Binary : 430
+ Block : 976
+ Break : 188
+ Call : 272
+ CallIndirect : 20
+ Const : 876
+ Drop : 99
+ GlobalGet : 504
+ GlobalSet : 373
+ If : 299
+ Load : 111
+ LocalGet : 365
+ LocalSet : 299
+ Loop : 108
+ Nop : 58
+ RefFunc : 19
+ Return : 74
+ Select : 40
+ Store : 34
Switch : 2
Unary : 365
- Unreachable : 158
+ Unreachable : 183
diff --git a/test/passes/fuzz_metrics_passes_noprint.bin.txt b/test/passes/fuzz_metrics_passes_noprint.bin.txt
index 9c8c25c12..c3881104d 100644
--- a/test/passes/fuzz_metrics_passes_noprint.bin.txt
+++ b/test/passes/fuzz_metrics_passes_noprint.bin.txt
@@ -1,35 +1,34 @@
Metrics
total
- [exports] : 54
- [funcs] : 84
+ [exports] : 30
+ [funcs] : 47
[globals] : 17
[imports] : 4
[memories] : 1
[memory-data] : 11
- [table-data] : 22
+ [table-data] : 18
[tables] : 1
[tags] : 0
- [total] : 8343
- [vars] : 264
- Binary : 597
- Block : 1335
- Break : 226
- Call : 346
- CallIndirect : 65
- Const : 1375
- Drop : 107
- GlobalGet : 719
- GlobalSet : 522
- If : 458
- Load : 139
- LocalGet : 650
- LocalSet : 441
- Loop : 165
- Nop : 97
- RefFunc : 22
- Return : 120
- Select : 71
- Store : 56
- Switch : 2
- Unary : 574
- Unreachable : 256
+ [total] : 4738
+ [vars] : 133
+ Binary : 338
+ Block : 781
+ Break : 122
+ Call : 249
+ CallIndirect : 27
+ Const : 780
+ Drop : 105
+ GlobalGet : 378
+ GlobalSet : 288
+ If : 216
+ Load : 79
+ LocalGet : 396
+ LocalSet : 252
+ Loop : 89
+ Nop : 43
+ RefFunc : 18
+ Return : 70
+ Select : 37
+ Store : 36
+ Unary : 294
+ Unreachable : 140
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 8df9d033c..e2e9b8053 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -1,54 +1,57 @@
Metrics
total
- [exports] : 9
- [funcs] : 10
+ [exports] : 6
+ [funcs] : 6
[globals] : 4
[imports] : 8
[memories] : 1
[memory-data] : 112
- [table-data] : 2
+ [table-data] : 1
[tables] : 1
[tags] : 1
- [total] : 682
- [vars] : 37
- ArrayLen : 1
- ArrayNew : 7
- ArrayNewFixed : 5
+ [total] : 592
+ [vars] : 38
+ ArrayGet : 2
+ ArrayLen : 2
+ ArrayNew : 6
+ ArrayNewFixed : 4
ArraySet : 1
- AtomicNotify : 1
- Binary : 79
- Block : 72
- BrOn : 4
- Break : 7
- Call : 19
- Const : 149
- Drop : 15
- GlobalGet : 35
- GlobalSet : 32
- If : 20
- Load : 20
- LocalGet : 55
- LocalSet : 26
- Loop : 7
- MemoryFill : 1
- Nop : 9
- Pop : 1
+ AtomicCmpxchg : 1
+ AtomicFence : 1
+ AtomicRMW : 2
+ Binary : 81
+ Block : 62
+ BrOn : 1
+ Break : 11
+ Call : 13
+ CallIndirect : 2
+ Const : 123
+ Drop : 2
+ GlobalGet : 22
+ GlobalSet : 22
+ If : 17
+ Load : 25
+ LocalGet : 63
+ LocalSet : 35
+ Loop : 6
+ Nop : 8
+ Pop : 3
RefAs : 1
- RefCast : 1
RefEq : 1
- RefFunc : 17
- RefI31 : 2
- RefIsNull : 2
- RefNull : 8
- Return : 5
- SIMDExtract : 3
- Store : 1
- StringConst : 3
+ RefFunc : 6
+ RefNull : 3
+ Return : 4
+ SIMDExtract : 2
+ Select : 2
+ StringConst : 5
+ StringEncode : 1
+ StringEq : 2
StringMeasure : 1
- StringWTF16Get : 1
- StructNew : 23
- Try : 1
- TupleExtract : 3
- TupleMake : 4
- Unary : 23
- Unreachable : 16
+ StringWTF16Get : 2
+ StructNew : 9
+ Try : 3
+ TryTable : 3
+ TupleExtract : 1
+ TupleMake : 2
+ Unary : 18
+ Unreachable : 11