1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
;; Passive segment syntax
(module
(memory i64 1)
(data "foo"))
;; memory.fill
(module
(memory i64 1)
(func (export "fill") (param i64 i32 i64)
(memory.fill
(local.get 0)
(local.get 1)
(local.get 2)))
(func (export "load8_u") (param i64) (result i32)
(i32.load8_u (local.get 0)))
)
;; Basic fill test.
(invoke "fill" (i64.const 1) (i32.const 0xff) (i64.const 3))
(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0))
(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xff))
(assert_return (invoke "load8_u" (i64.const 2)) (i32.const 0xff))
(assert_return (invoke "load8_u" (i64.const 3)) (i32.const 0xff))
(assert_return (invoke "load8_u" (i64.const 4)) (i32.const 0))
;; Fill value is stored as a byte.
(invoke "fill" (i64.const 0) (i32.const 0xbbaa) (i64.const 2))
(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0xaa))
(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xaa))
;; Fill all of memory
(invoke "fill" (i64.const 0) (i32.const 0) (i64.const 0x10000))
;; Succeed when writing 0 bytes at the end of the region.
(invoke "fill" (i64.const 0x10000) (i32.const 0) (i64.const 0))
;; Writing 0 bytes outside of memory limit is NOT allowed.
(assert_trap (invoke "fill" (i64.const 0x10001) (i32.const 0) (i64.const 0)) "oob")
;; Negative size
(assert_trap (invoke "fill" (i64.const 15) (i32.const 14) (i64.const -2)) "oob")
(assert_return (invoke "load8_u" (i64.const 15)) (i32.const 0))
;; memory.copy
(module
(memory i64 1 1)
(data (i64.const 0) "\aa\bb\cc\dd")
(func (export "copy") (param i64 i64 i64)
(memory.copy
(local.get 0)
(local.get 1)
(local.get 2)))
(func (export "load8_u") (param i64) (result i32)
(i32.load8_u (local.get 0)))
)
;; Non-overlapping copy.
(invoke "copy" (i64.const 10) (i64.const 0) (i64.const 4))
(assert_return (invoke "load8_u" (i64.const 9)) (i32.const 0))
(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0xaa))
(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xbb))
(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xdd))
(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0))
;; Overlap, source > dest
(invoke "copy" (i64.const 8) (i64.const 10) (i64.const 4))
(assert_return (invoke "load8_u" (i64.const 8)) (i32.const 0xaa))
(assert_return (invoke "load8_u" (i64.const 9)) (i32.const 0xbb))
(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xdd))
(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xdd))
;; Overlap, source < dest
(invoke "copy" (i64.const 10) (i64.const 7) (i64.const 6))
(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0))
(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xaa))
(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xbb))
(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0xdd))
(assert_return (invoke "load8_u" (i64.const 15)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 16)) (i32.const 0))
;; Overlap, source < dest but size is out of bounds
(assert_trap (invoke "copy" (i64.const 13) (i64.const 11) (i64.const -1)) "oob")
(assert_return (invoke "load8_u" (i64.const 10)) (i32.const 0))
(assert_return (invoke "load8_u" (i64.const 11)) (i32.const 0xaa))
(assert_return (invoke "load8_u" (i64.const 12)) (i32.const 0xbb))
(assert_return (invoke "load8_u" (i64.const 13)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 14)) (i32.const 0xdd))
(assert_return (invoke "load8_u" (i64.const 15)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 16)) (i32.const 0))
;; Copy ending at memory limit is ok.
(invoke "copy" (i64.const 0xff00) (i64.const 0) (i64.const 0x100))
(invoke "copy" (i64.const 0xfe00) (i64.const 0xff00) (i64.const 0x100))
;; Succeed when copying 0 bytes at the end of the region.
(invoke "copy" (i64.const 0x10000) (i64.const 0) (i64.const 0))
(invoke "copy" (i64.const 0) (i64.const 0x10000) (i64.const 0))
;; Copying 0 bytes outside of memory limit is NOT allowed.
(assert_trap (invoke "copy" (i64.const 0x10001) (i64.const 0) (i64.const 0)) "oob")
(assert_trap (invoke "copy" (i64.const 0) (i64.const 0x10001) (i64.const 0)) "oob")
;; memory.init
(module
(memory i64 1)
(data "\aa\bb\cc\dd")
(func (export "init") (param i64 i32 i32)
(memory.init 0
(local.get 0)
(local.get 1)
(local.get 2)))
(func (export "load8_u") (param i64) (result i32)
(i32.load8_u (local.get 0)))
)
(invoke "init" (i64.const 0) (i32.const 1) (i32.const 2))
(assert_return (invoke "load8_u" (i64.const 0)) (i32.const 0xbb))
(assert_return (invoke "load8_u" (i64.const 1)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 2)) (i32.const 0))
;; Init ending at memory limit and segment limit is ok.
(invoke "init" (i64.const 0xfffc) (i32.const 0) (i32.const 4))
;; Out-of-bounds writes trap, and no partial writes has been made.
(assert_trap (invoke "init" (i64.const 0xfffe) (i32.const 0) (i32.const 3))
"out of bounds memory access")
(assert_return (invoke "load8_u" (i64.const 0xfffe)) (i32.const 0xcc))
(assert_return (invoke "load8_u" (i64.const 0xffff)) (i32.const 0xdd))
;; Succeed when writing 0 bytes at the end of either region.
(invoke "init" (i64.const 0x10000) (i32.const 0) (i32.const 0))
(invoke "init" (i64.const 0) (i32.const 4) (i32.const 0))
;; Writing 0 bytes outside of memory / segment limit is NOT allowed.
(assert_trap (invoke "init" (i64.const 0x10001) (i32.const 0) (i32.const 0)) "oob")
(assert_trap (invoke "init" (i64.const 0) (i32.const 5) (i32.const 0)) "oob")
;; OK to access 0 bytes at offset 0 in a dropped segment.
(invoke "init" (i64.const 0) (i32.const 0) (i32.const 0))
;; data.drop
(module
(memory i64 1)
(data "")
(data (i64.const 0) "")
(func (export "drop_passive") (data.drop 0))
(func (export "init_passive")
(memory.init 0 (i64.const 0) (i32.const 0) (i32.const 0)))
(func (export "drop_active") (data.drop 1))
(func (export "init_active")
(memory.init 1 (i64.const 0) (i32.const 0) (i32.const 0)))
)
;; OK to drop the same segment multiple times or drop an active segment.
(invoke "init_passive")
(invoke "drop_passive")
(invoke "drop_passive")
(invoke "drop_active")
|