Skip to content

Commit 8f21770

Browse files
authored
Fix validation of atomic mutation of shared globals (#2473)
This commit updates validation of atomic-related mutation instructions, only applicable with the shared-everything-threads proposal, to require that the global in question is flagged as mutable. This seems like an oversight in the current implementation, so mutability is required for now.
1 parent 25b8490 commit 8f21770

5 files changed

Lines changed: 155 additions & 13 deletions

File tree

crates/wasmparser/src/validator/operators.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,7 +1559,14 @@ where
15591559
/// Common helper for checking the types of globals accessed with atomic RMW
15601560
/// instructions, which only allow `i32` and `i64`.
15611561
fn check_atomic_global_rmw_ty(&self, global_index: u32) -> Result<ValType> {
1562-
let ty = self.global_type_at(global_index)?.content_type;
1562+
let global = self.global_type_at(global_index)?;
1563+
if !global.mutable {
1564+
bail!(
1565+
self.offset,
1566+
"global is immutable: cannot modify it with `global.atomic.rmw.*`"
1567+
);
1568+
}
1569+
let ty = global.content_type;
15631570
if !(ty == ValType::I32 || ty == ValType::I64) {
15641571
bail!(
15651572
self.offset,
@@ -2452,7 +2459,14 @@ where
24522459
_ordering: crate::Ordering,
24532460
global_index: u32,
24542461
) -> Self::Output {
2455-
let ty = self.global_type_at(global_index)?.content_type;
2462+
let global = self.global_type_at(global_index)?;
2463+
if !global.mutable {
2464+
bail!(
2465+
self.offset,
2466+
"global is immutable: cannot modify it with `global.atomic.rmw.xchg`"
2467+
);
2468+
}
2469+
let ty = global.content_type;
24562470
if !(ty == ValType::I32
24572471
|| ty == ValType::I64
24582472
|| self.resources.is_subtype(ty, RefType::ANYREF.into()))
@@ -2469,7 +2483,14 @@ where
24692483
_ordering: crate::Ordering,
24702484
global_index: u32,
24712485
) -> Self::Output {
2472-
let ty = self.global_type_at(global_index)?.content_type;
2486+
let global = self.global_type_at(global_index)?;
2487+
if !global.mutable {
2488+
bail!(
2489+
self.offset,
2490+
"global is immutable: cannot modify it with `global.atomic.rmw.cmpxchg`"
2491+
);
2492+
}
2493+
let ty = global.content_type;
24732494
if !(ty == ValType::I32
24742495
|| ty == ValType::I64
24752496
|| self.resources.is_subtype(ty, RefType::EQREF.into()))
@@ -3709,7 +3730,7 @@ where
37093730
struct_type_index: u32,
37103731
field_index: u32,
37113732
) -> Self::Output {
3712-
self.visit_struct_get_s(struct_type_index, field_index)?;
3733+
self.visit_struct_get_u(struct_type_index, field_index)?;
37133734
// This instruction has the same type restrictions as the non-`atomic` version.
37143735
debug_assert!(matches!(
37153736
self.struct_field_at(struct_type_index, field_index)?

tests/cli/shared-everything-threads/globals.wast

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,78 @@
380380
)
381381
"invalid type: `global.atomic.rmw.*` only allows `i32` and `i64`")
382382

383+
;; Check global.atomic.rmw.* on immutable globals.
384+
(assert_invalid
385+
(module
386+
(global $g (shared i32) (i32.const 0))
387+
(func (result i32)
388+
i32.const 1
389+
global.atomic.rmw.add seq_cst $g
390+
)
391+
)
392+
"global is immutable")
393+
394+
(assert_invalid
395+
(module
396+
(global $g (shared i32) (i32.const 0))
397+
(func (result i32)
398+
i32.const 1
399+
global.atomic.rmw.sub seq_cst $g
400+
)
401+
)
402+
"global is immutable")
403+
404+
(assert_invalid
405+
(module
406+
(global $g (shared i32) (i32.const 0))
407+
(func (result i32)
408+
i32.const 1
409+
global.atomic.rmw.and seq_cst $g
410+
)
411+
)
412+
"global is immutable")
413+
414+
(assert_invalid
415+
(module
416+
(global $g (shared i32) (i32.const 0))
417+
(func (result i32)
418+
i32.const 1
419+
global.atomic.rmw.or seq_cst $g
420+
)
421+
)
422+
"global is immutable")
423+
424+
(assert_invalid
425+
(module
426+
(global $g (shared i32) (i32.const 0))
427+
(func (result i32)
428+
i32.const 1
429+
global.atomic.rmw.xor seq_cst $g
430+
)
431+
)
432+
"global is immutable")
433+
434+
(assert_invalid
435+
(module
436+
(global $g (shared i32) (i32.const 0))
437+
(func (result i32)
438+
i32.const 1
439+
global.atomic.rmw.xchg seq_cst $g
440+
)
441+
)
442+
"global is immutable")
443+
444+
(assert_invalid
445+
(module
446+
(global $g (shared i32) (i32.const 0))
447+
(func (result i32)
448+
i32.const 1
449+
i32.const 2
450+
global.atomic.rmw.cmpxchg seq_cst $g
451+
)
452+
)
453+
"global is immutable")
454+
383455
(assert_invalid
384456
(module
385457
(func

tests/snapshots/cli/shared-everything-threads/globals.wast.json

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,35 +181,84 @@
181181
},
182182
{
183183
"type": "assert_invalid",
184-
"line": 384,
184+
"line": 385,
185185
"filename": "globals.26.wasm",
186186
"module_type": "binary",
187-
"text": "global index out of bounds"
187+
"text": "global is immutable"
188188
},
189189
{
190190
"type": "assert_invalid",
191-
"line": 392,
191+
"line": 395,
192192
"filename": "globals.27.wasm",
193193
"module_type": "binary",
194+
"text": "global is immutable"
195+
},
196+
{
197+
"type": "assert_invalid",
198+
"line": 405,
199+
"filename": "globals.28.wasm",
200+
"module_type": "binary",
201+
"text": "global is immutable"
202+
},
203+
{
204+
"type": "assert_invalid",
205+
"line": 415,
206+
"filename": "globals.29.wasm",
207+
"module_type": "binary",
208+
"text": "global is immutable"
209+
},
210+
{
211+
"type": "assert_invalid",
212+
"line": 425,
213+
"filename": "globals.30.wasm",
214+
"module_type": "binary",
215+
"text": "global is immutable"
216+
},
217+
{
218+
"type": "assert_invalid",
219+
"line": 435,
220+
"filename": "globals.31.wasm",
221+
"module_type": "binary",
222+
"text": "global is immutable"
223+
},
224+
{
225+
"type": "assert_invalid",
226+
"line": 445,
227+
"filename": "globals.32.wasm",
228+
"module_type": "binary",
229+
"text": "global is immutable"
230+
},
231+
{
232+
"type": "assert_invalid",
233+
"line": 456,
234+
"filename": "globals.33.wasm",
235+
"module_type": "binary",
236+
"text": "global index out of bounds"
237+
},
238+
{
239+
"type": "assert_invalid",
240+
"line": 464,
241+
"filename": "globals.34.wasm",
242+
"module_type": "binary",
194243
"text": "invalid type: `global.atomic.rmw.xchg` only allows `i32`, `i64` and subtypes of `anyref`"
195244
},
196245
{
197246
"type": "module",
198-
"line": 402,
199-
"filename": "globals.28.wasm",
247+
"line": 474,
248+
"filename": "globals.35.wasm",
200249
"module_type": "binary"
201250
},
202251
{
203252
"type": "assert_invalid",
204-
"line": 412,
205-
"filename": "globals.29.wasm",
253+
"line": 484,
254+
"filename": "globals.36.wasm",
206255
"module_type": "binary",
207256
"text": "invalid type: `global.atomic.rmw.cmpxchg` only allows `i32`, `i64` and subtypes of `eqref`"
208257
},
209258
{
210259
"type": "module",
211-
"line": 423,
212-
"filename": "globals.30.wasm",
260+
"line": 495,
261+
"filename": "globals.37.wasm",
213262
"module_type": "binary"
214263
}
215264
]

tests/snapshots/cli/shared-everything-threads/globals.wast/28.print renamed to tests/snapshots/cli/shared-everything-threads/globals.wast/35.print

File renamed without changes.

tests/snapshots/cli/shared-everything-threads/globals.wast/30.print renamed to tests/snapshots/cli/shared-everything-threads/globals.wast/37.print

File renamed without changes.

0 commit comments

Comments
 (0)