Skip to content

Commit 0c6fae6

Browse files
authored
Validate RMW field types (#8554)
We were missing validation for referenced typed fields accessed by struct and array RMW operations. They must be subtypes of eqref or shared eqref.
1 parent 3cd49e3 commit 0c6fae6

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

src/wasm/wasm-validator.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3574,6 +3574,10 @@ void FunctionValidator::visitStructCmpxchg(StructCmpxchg* curr) {
35743574
} else if (field.type.isRef()) {
35753575
expectedExpectedType = Type(
35763576
HeapTypes::eq.getBasic(field.type.getHeapType().getShared()), Nullable);
3577+
shouldBeSubType(field.type,
3578+
expectedExpectedType,
3579+
curr,
3580+
"struct.atomic.rmw field type invalid for operation");
35773581
} else {
35783582
shouldBeTrue(
35793583
false, curr, "struct.atomic.rmw field type invalid for operation");
@@ -4127,6 +4131,10 @@ void FunctionValidator::visitArrayCmpxchg(ArrayCmpxchg* curr) {
41274131
} else if (element.type.isRef()) {
41284132
expectedExpectedType = Type(
41294133
HeapTypes::eq.getBasic(element.type.getHeapType().getShared()), Nullable);
4134+
shouldBeSubType(element.type,
4135+
expectedExpectedType,
4136+
curr,
4137+
"array.atomic.rmw element type invalid for operation");
41304138
} else {
41314139
shouldBeTrue(
41324140
false, curr, "array.atomic.rmw element type invalid for operation");

test/lit/validation/cmpxchg.wast

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
;; RUN: not wasm-opt %s -all 2>&1 | filecheck %s
2+
3+
(module
4+
;; Shared types
5+
(type $struct-any (shared (struct (field (mut (ref null (shared any)))))))
6+
(type $array-any (shared (array (mut (ref null (shared any))))))
7+
8+
;; Negative cases for struct.atomic.rmw.cmpxchg
9+
;; Use eqref for expected and replacement to isolate the error to the field type.
10+
(func $struct-cmpxchg-anyref (param $ref (ref $struct-any)) (param $eq (ref null (shared eq)))
11+
(drop
12+
(struct.atomic.rmw.cmpxchg $struct-any 0
13+
(local.get $ref)
14+
(local.get $eq)
15+
(local.get $eq)
16+
)
17+
)
18+
)
19+
;; CHECK: [wasm-validator error in function struct-cmpxchg-anyref] struct.atomic.rmw field type invalid for operation
20+
21+
;; Negative case for array.atomic.rmw.cmpxchg
22+
(func $array-cmpxchg-anyref (param $ref (ref $array-any)) (param $eq (ref null (shared eq)))
23+
(drop
24+
(array.atomic.rmw.cmpxchg $array-any
25+
(local.get $ref)
26+
(i32.const 0)
27+
(local.get $eq)
28+
(local.get $eq)
29+
)
30+
)
31+
)
32+
;; CHECK: [wasm-validator error in function array-cmpxchg-anyref] array.atomic.rmw element type invalid for operation
33+
34+
;; Unshared types
35+
(type $struct-unshared-any (struct (field (mut anyref))))
36+
(func $struct-cmpxchg-unshared-anyref (param $ref (ref $struct-unshared-any)) (param $eq eqref)
37+
(drop
38+
(struct.atomic.rmw.cmpxchg $struct-unshared-any 0
39+
(local.get $ref)
40+
(local.get $eq)
41+
(local.get $eq)
42+
)
43+
)
44+
)
45+
;; CHECK: [wasm-validator error in function struct-cmpxchg-unshared-anyref] struct.atomic.rmw field type invalid for operation
46+
47+
;; Check that it still fails for non-i32/i64/reference types.
48+
(type $struct-v128 (struct (field (mut v128))))
49+
(func $struct-cmpxchg-v128 (param $ref (ref $struct-v128)) (param $eq v128)
50+
(drop
51+
(struct.atomic.rmw.cmpxchg $struct-v128 0
52+
(local.get $ref)
53+
(local.get $eq)
54+
(local.get $eq)
55+
)
56+
)
57+
)
58+
;; CHECK: [wasm-validator error in function struct-cmpxchg-v128] unexpected false: struct.atomic.rmw field type invalid for operation
59+
)

0 commit comments

Comments
 (0)