Skip to content

Commit 8300978

Browse files
committed
Statically disallow casts over continuations
1 parent ad92b39 commit 8300978

File tree

3 files changed

+125
-2
lines changed

3 files changed

+125
-2
lines changed

interpreter/valid/valid.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ let func_type_of_tag_type (c : context) (TagT dt) at : func_type =
114114
| DefFuncT ft -> ft
115115
| _ -> error at "non-function type"
116116

117+
117118
(* Types *)
118119

119120
let check_limits {min; max} range at msg =
@@ -413,6 +414,10 @@ let check_memop (c : context) (memop : ('t, 's) memop) ty_size get_sz at =
413414
"offset out of range";
414415
memop.ty
415416

417+
let check_cast (c : context) rt at =
418+
require (not (match_ref_type c.types rt (Null, ContHT))) at
419+
"invalid cast to continuation types"
420+
416421

417422
(*
418423
* Conventions:
@@ -540,6 +545,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : infer_in
540545
| BrOnCast (x, rt1, rt2) ->
541546
check_ref_type c rt1 e.at;
542547
check_ref_type c rt2 e.at;
548+
check_cast c rt2 e.at;
543549
require
544550
(match_ref_type c.types rt2 rt1) e.at
545551
("type mismatch on cast: type " ^ string_of_ref_type rt2 ^
@@ -556,6 +562,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : infer_in
556562
| BrOnCastFail (x, rt1, rt2) ->
557563
check_ref_type c rt1 e.at;
558564
check_ref_type c rt2 e.at;
565+
check_cast c rt2 e.at;
559566
let rt1' = diff_ref_type rt1 rt2 in
560567
require
561568
(match_ref_type c.types rt2 rt1) e.at
@@ -835,11 +842,13 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : infer_in
835842
| RefTest rt ->
836843
let (_nul, ht) = rt in
837844
check_ref_type c rt e.at;
845+
check_cast c rt e.at;
838846
[RefT (Null, top_of_heap_type c.types ht)] --> [NumT I32T], []
839847

840848
| RefCast rt ->
841849
let (nul, ht) = rt in
842850
check_ref_type c rt e.at;
851+
check_cast c rt e.at;
843852
[RefT (Null, top_of_heap_type c.types ht)] --> [RefT (nul, ht)], []
844853

845854
| RefEq ->

proposals/stack-switching/Explainer.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -900,8 +900,8 @@ critical use-cases requires multi-shot continuations.
900900

901901
## Specification changes
902902

903-
This proposal is based on the [function references proposal](https://github.com/WebAssembly/function-references)
904-
and [exception handling proposal](https://github.com/WebAssembly/exception-handling).
903+
This proposal is based on Wasm 3.0, specifically [function references](https://github.com/WebAssembly/function-references)
904+
and [exception handling](https://github.com/WebAssembly/exception-handling).
905905

906906
### Types
907907

@@ -998,6 +998,15 @@ This abbreviation will be formalised with an auxiliary function or other means i
998998
- and `C.types[$ct2] ~~ cont [t2*] -> [te2*]`
999999
- and `t* <: te2*`
10001000

1001+
In addition to these new rules, the existing rules for cast instructions `ref.test`, `ref.cast`, `br_on_cast`, and `br_on_cast_fail` are amended with an additional side condition to rule out casting of continuation types:
1002+
1003+
- iff `rt castable`
1004+
1005+
where `rt` is the respective target type of the cast instruction, and the `castable` predicate is defined as follows:
1006+
1007+
- `rt castable`
1008+
- iff not (rt <: (ref null cont))
1009+
10011010
### Execution
10021011

10031012
The same control tag may be used simultaneously by `throw`, `suspend`,

test/core/stack-switching/validation.wast

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,3 +796,108 @@
796796
)
797797
"unknown tag"
798798
)
799+
800+
801+
;; Illegal casts
802+
803+
(assert_invalid
804+
(module
805+
(func (drop (ref.test contref (unreachable))))
806+
)
807+
"invalid cast"
808+
)
809+
(assert_invalid
810+
(module
811+
(func (drop (ref.test nullcontref (unreachable))))
812+
)
813+
"invalid cast"
814+
)
815+
(assert_invalid
816+
(module
817+
(type $f (func))
818+
(type $c (cont $f))
819+
(func (drop (ref.test (ref $c) (unreachable))))
820+
)
821+
"invalid cast"
822+
)
823+
824+
(assert_invalid
825+
(module
826+
(func (drop (ref.cast contref (unreachable))))
827+
)
828+
"invalid cast"
829+
)
830+
(assert_invalid
831+
(module
832+
(func (drop (ref.cast nullcontref (unreachable))))
833+
)
834+
"invalid cast"
835+
)
836+
(assert_invalid
837+
(module
838+
(type $f (func))
839+
(type $c (cont $f))
840+
(func (drop (ref.cast (ref $c) (unreachable))))
841+
)
842+
"invalid cast"
843+
)
844+
845+
(assert_invalid
846+
(module
847+
(func
848+
(block (result contref) (br_on_cast 0 contref contref (unreachable)))
849+
(drop)
850+
)
851+
)
852+
"invalid cast"
853+
)
854+
(assert_invalid
855+
(module
856+
(func
857+
(block (result contref) (br_on_cast 0 nullcontref nullcontref (unreachable)))
858+
(drop)
859+
)
860+
)
861+
"invalid cast"
862+
)
863+
(assert_invalid
864+
(module
865+
(type $f (func))
866+
(type $c (cont $f))
867+
(func
868+
(block (result contref) (br_on_cast 0 (ref $c) (ref $c) (unreachable)))
869+
(drop)
870+
)
871+
)
872+
"invalid cast"
873+
)
874+
875+
(assert_invalid
876+
(module
877+
(func
878+
(block (result contref) (br_on_cast_fail 0 contref contref (unreachable)))
879+
(drop)
880+
)
881+
)
882+
"invalid cast"
883+
)
884+
(assert_invalid
885+
(module
886+
(func
887+
(block (result contref) (br_on_cast_fail 0 nullcontref nullcontref (unreachable)))
888+
(drop)
889+
)
890+
)
891+
"invalid cast"
892+
)
893+
(assert_invalid
894+
(module
895+
(type $f (func))
896+
(type $c (cont $f))
897+
(func
898+
(block (result contref) (br_on_cast_fail 0 (ref $c) (ref $c) (unreachable)))
899+
(drop)
900+
)
901+
)
902+
"invalid cast"
903+
)

0 commit comments

Comments
 (0)