1*39e910beSAlex Crichton;;! multi_memory = true
2*39e910beSAlex Crichton
3*39e910beSAlex Crichton;; Transcode a utf16 string to latin1+utf16, but the original string is
4*39e910beSAlex Crichton;; out-of-bounds. Should report a first-class error.
5*39e910beSAlex Crichton(component
6*39e910beSAlex Crichton  (component $dst
7*39e910beSAlex Crichton    (core module $m
8*39e910beSAlex Crichton      (func (export "recv") (param i32 i32))
9*39e910beSAlex Crichton      (func (export "realloc") (param i32 i32 i32 i32) (result i32) i32.const 0)
10*39e910beSAlex Crichton      (memory (export "memory") 1)
11*39e910beSAlex Crichton    )
12*39e910beSAlex Crichton    (core instance $i (instantiate $m))
13*39e910beSAlex Crichton    (func (export "recv") (param "a" string)
14*39e910beSAlex Crichton      (canon lift (core func $i "recv") (realloc (func $i "realloc")) (memory $i "memory")
15*39e910beSAlex Crichton        string-encoding=latin1+utf16)
16*39e910beSAlex Crichton    )
17*39e910beSAlex Crichton  )
18*39e910beSAlex Crichton
19*39e910beSAlex Crichton  ;; Source component: uses utf16 encoding.
20*39e910beSAlex Crichton  ;; Passes a string placed near the END of linear memory to $dst.
21*39e910beSAlex Crichton  (component $src
22*39e910beSAlex Crichton    (import "recv" (func $recv (param "a" string)))
23*39e910beSAlex Crichton    (core module $libc
24*39e910beSAlex Crichton      (memory (export "memory") 1)  ;; 1 page = 65536 bytes
25*39e910beSAlex Crichton      (func (export "realloc") (param i32 i32 i32 i32) (result i32) i32.const 0)
26*39e910beSAlex Crichton    )
27*39e910beSAlex Crichton    (core instance $libc (instantiate $libc))
28*39e910beSAlex Crichton    ;; canon lower with utf16 — the source side of the mismatch.
29*39e910beSAlex Crichton    (core func $recv_lowered (canon lower (func $recv) string-encoding=utf16 (memory $libc "memory")))
30*39e910beSAlex Crichton    (core module $m
31*39e910beSAlex Crichton      (import "" "" (func $recv (param i32 i32)))
32*39e910beSAlex Crichton      (import "libc" "memory" (memory 0))
33*39e910beSAlex Crichton      (func (export "run")
34*39e910beSAlex Crichton        ;; Write 8 UTF-16 code units (16 bytes) of 'A' (U+0041) at the end of memory.
35*39e910beSAlex Crichton        ;; Offsets 65520–65535: exactly fills to the last byte of the page.
36*39e910beSAlex Crichton        (i32.store (i32.const 65520) (i32.const 0x00410041))
37*39e910beSAlex Crichton        (i32.store (i32.const 65524) (i32.const 0x00410041))
38*39e910beSAlex Crichton        (i32.store (i32.const 65528) (i32.const 0x00410041))
39*39e910beSAlex Crichton        (i32.store (i32.const 65532) (i32.const 0x00410041))
40*39e910beSAlex Crichton
41*39e910beSAlex Crichton        ;; Pass ptr=65520, len=10 CODE UNITS (not bytes).
42*39e910beSAlex Crichton        ;; We wrote 8 code units but claim 10 — the extra 2 are past end of memory.
43*39e910beSAlex Crichton        (call $recv (i32.const 65520) (i32.const 10))
44*39e910beSAlex Crichton      )
45*39e910beSAlex Crichton    )
46*39e910beSAlex Crichton    (core instance $i (instantiate $m
47*39e910beSAlex Crichton      (with "" (instance (export "" (func $recv_lowered))))
48*39e910beSAlex Crichton      (with "libc" (instance $libc))
49*39e910beSAlex Crichton    ))
50*39e910beSAlex Crichton    (func (export "run")
51*39e910beSAlex Crichton      (canon lift (core func $i "run"))
52*39e910beSAlex Crichton    )
53*39e910beSAlex Crichton  )
54*39e910beSAlex Crichton
55*39e910beSAlex Crichton  ;; Wire the components together and run.
56*39e910beSAlex Crichton  (instance $dst_inst (instantiate $dst))
57*39e910beSAlex Crichton  (instance $i (instantiate $src (with "recv" (func $dst_inst "recv"))))
58*39e910beSAlex Crichton
59*39e910beSAlex Crichton  (export "run" (func $i "run"))
60*39e910beSAlex Crichton)
61*39e910beSAlex Crichton
62*39e910beSAlex Crichton(assert_trap (invoke "run") "string content out-of-bounds")
63