]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/wasm: avoid invalid offsets for Load/Store
authorRichard Musiol <mail@richard-musiol.de>
Mon, 7 May 2018 14:18:19 +0000 (16:18 +0200)
committerCherry Zhang <cherryyz@google.com>
Thu, 10 May 2018 12:05:17 +0000 (12:05 +0000)
Offsets for Load and Store instructions have type i32. Bad index
expression offsets can cause an offset to be larger than MaxUint32,
which is not allowed. One example for this is the test test/index0.go.

Generate valid code by adding a guard to the responsible rewrite rule.
Also emit a proper error when using such a bad index in assembly code.

Change-Id: Ie90adcbf3ae3861c26680eb81790f28692913ccf
Reviewed-on: https://go-review.googlesource.com/111955
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/ssa/gen/Wasm.rules
src/cmd/compile/internal/ssa/rewriteWasm.go
src/cmd/internal/obj/wasm/wasmobj.go

index cede359c538073222451f45640717f8e97644ce1..7994fb7f5baa104b2f562d99f95f628b5917dcb2 100644 (file)
 (I64Add x (I64Const [y])) -> (I64AddConst [y] x)
 (I64Eqz (I64Eqz (I64Eqz x))) -> (I64Eqz x)
 
-(I64Store8 [off] (I64AddConst [off2] ptr) val mem) && off+off2 >= 0 -> (I64Store8 [off+off2] ptr val mem)
-(I64Store16 [off] (I64AddConst [off2] ptr) val mem) && off+off2 >= 0 -> (I64Store16 [off+off2] ptr val mem)
-(I64Store32 [off] (I64AddConst [off2] ptr) val mem) && off+off2 >= 0 -> (I64Store32 [off+off2] ptr val mem)
-(I64Store [off] (I64AddConst [off2] ptr) val mem) && off+off2 >= 0 -> (I64Store [off+off2] ptr val mem)
-
-(I64Load8U [off] (I64AddConst [off2] ptr) mem) && off+off2 >= 0 -> (I64Load8U [off+off2] ptr mem)
-(I64Load8S [off] (I64AddConst [off2] ptr) mem) && off+off2 >= 0 -> (I64Load8S [off+off2] ptr mem)
-(I64Load16U [off] (I64AddConst [off2] ptr) mem) && off+off2 >= 0 -> (I64Load16U [off+off2] ptr mem)
-(I64Load16S [off] (I64AddConst [off2] ptr) mem) && off+off2 >= 0 -> (I64Load16S [off+off2] ptr mem)
-(I64Load32U [off] (I64AddConst [off2] ptr) mem) && off+off2 >= 0 -> (I64Load32U [off+off2] ptr mem)
-(I64Load32S [off] (I64AddConst [off2] ptr) mem) && off+off2 >= 0 -> (I64Load32S [off+off2] ptr mem)
-(I64Load [off] (I64AddConst [off2] ptr) mem) && off+off2 >= 0 -> (I64Load [off+off2] ptr mem)
+((I64Load|I64Load32U|I64Load32S|I64Load16U|I64Load16S|I64Load8U|I64Load8S) [off] (I64AddConst [off2] ptr) mem)
+       && isU32Bit(off+off2) ->
+       ((I64Load|I64Load32U|I64Load32S|I64Load16U|I64Load16S|I64Load8U|I64Load8S) [off+off2] ptr mem)
+
+((I64Store|I64Store32|I64Store16|I64Store8) [off] (I64AddConst [off2] ptr) val mem)
+       && isU32Bit(off+off2) ->
+       ((I64Store|I64Store32|I64Store16|I64Store8) [off+off2] ptr val mem)
index f488a935224ca063d8a6ffb3b5292e6608d2b478..22555610514ca1821fd9c62e2144549c0b29d4b3 100644 (file)
@@ -5256,7 +5256,7 @@ func rewriteValueWasm_OpWasmI64Eqz_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Load_0(v *Value) bool {
        // match: (I64Load [off] (I64AddConst [off2] ptr) mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Load [off+off2] ptr mem)
        for {
                off := v.AuxInt
@@ -5268,7 +5268,7 @@ func rewriteValueWasm_OpWasmI64Load_0(v *Value) bool {
                off2 := v_0.AuxInt
                ptr := v_0.Args[0]
                mem := v.Args[1]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Load)
@@ -5281,7 +5281,7 @@ func rewriteValueWasm_OpWasmI64Load_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Load16S_0(v *Value) bool {
        // match: (I64Load16S [off] (I64AddConst [off2] ptr) mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Load16S [off+off2] ptr mem)
        for {
                off := v.AuxInt
@@ -5293,7 +5293,7 @@ func rewriteValueWasm_OpWasmI64Load16S_0(v *Value) bool {
                off2 := v_0.AuxInt
                ptr := v_0.Args[0]
                mem := v.Args[1]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Load16S)
@@ -5306,7 +5306,7 @@ func rewriteValueWasm_OpWasmI64Load16S_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Load16U_0(v *Value) bool {
        // match: (I64Load16U [off] (I64AddConst [off2] ptr) mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Load16U [off+off2] ptr mem)
        for {
                off := v.AuxInt
@@ -5318,7 +5318,7 @@ func rewriteValueWasm_OpWasmI64Load16U_0(v *Value) bool {
                off2 := v_0.AuxInt
                ptr := v_0.Args[0]
                mem := v.Args[1]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Load16U)
@@ -5331,7 +5331,7 @@ func rewriteValueWasm_OpWasmI64Load16U_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Load32S_0(v *Value) bool {
        // match: (I64Load32S [off] (I64AddConst [off2] ptr) mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Load32S [off+off2] ptr mem)
        for {
                off := v.AuxInt
@@ -5343,7 +5343,7 @@ func rewriteValueWasm_OpWasmI64Load32S_0(v *Value) bool {
                off2 := v_0.AuxInt
                ptr := v_0.Args[0]
                mem := v.Args[1]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Load32S)
@@ -5356,7 +5356,7 @@ func rewriteValueWasm_OpWasmI64Load32S_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Load32U_0(v *Value) bool {
        // match: (I64Load32U [off] (I64AddConst [off2] ptr) mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Load32U [off+off2] ptr mem)
        for {
                off := v.AuxInt
@@ -5368,7 +5368,7 @@ func rewriteValueWasm_OpWasmI64Load32U_0(v *Value) bool {
                off2 := v_0.AuxInt
                ptr := v_0.Args[0]
                mem := v.Args[1]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Load32U)
@@ -5381,7 +5381,7 @@ func rewriteValueWasm_OpWasmI64Load32U_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Load8S_0(v *Value) bool {
        // match: (I64Load8S [off] (I64AddConst [off2] ptr) mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Load8S [off+off2] ptr mem)
        for {
                off := v.AuxInt
@@ -5393,7 +5393,7 @@ func rewriteValueWasm_OpWasmI64Load8S_0(v *Value) bool {
                off2 := v_0.AuxInt
                ptr := v_0.Args[0]
                mem := v.Args[1]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Load8S)
@@ -5406,7 +5406,7 @@ func rewriteValueWasm_OpWasmI64Load8S_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Load8U_0(v *Value) bool {
        // match: (I64Load8U [off] (I64AddConst [off2] ptr) mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Load8U [off+off2] ptr mem)
        for {
                off := v.AuxInt
@@ -5418,7 +5418,7 @@ func rewriteValueWasm_OpWasmI64Load8U_0(v *Value) bool {
                off2 := v_0.AuxInt
                ptr := v_0.Args[0]
                mem := v.Args[1]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Load8U)
@@ -5588,7 +5588,7 @@ func rewriteValueWasm_OpWasmI64Or_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Store_0(v *Value) bool {
        // match: (I64Store [off] (I64AddConst [off2] ptr) val mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Store [off+off2] ptr val mem)
        for {
                off := v.AuxInt
@@ -5601,7 +5601,7 @@ func rewriteValueWasm_OpWasmI64Store_0(v *Value) bool {
                ptr := v_0.Args[0]
                val := v.Args[1]
                mem := v.Args[2]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Store)
@@ -5615,7 +5615,7 @@ func rewriteValueWasm_OpWasmI64Store_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Store16_0(v *Value) bool {
        // match: (I64Store16 [off] (I64AddConst [off2] ptr) val mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Store16 [off+off2] ptr val mem)
        for {
                off := v.AuxInt
@@ -5628,7 +5628,7 @@ func rewriteValueWasm_OpWasmI64Store16_0(v *Value) bool {
                ptr := v_0.Args[0]
                val := v.Args[1]
                mem := v.Args[2]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Store16)
@@ -5642,7 +5642,7 @@ func rewriteValueWasm_OpWasmI64Store16_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Store32_0(v *Value) bool {
        // match: (I64Store32 [off] (I64AddConst [off2] ptr) val mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Store32 [off+off2] ptr val mem)
        for {
                off := v.AuxInt
@@ -5655,7 +5655,7 @@ func rewriteValueWasm_OpWasmI64Store32_0(v *Value) bool {
                ptr := v_0.Args[0]
                val := v.Args[1]
                mem := v.Args[2]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Store32)
@@ -5669,7 +5669,7 @@ func rewriteValueWasm_OpWasmI64Store32_0(v *Value) bool {
 }
 func rewriteValueWasm_OpWasmI64Store8_0(v *Value) bool {
        // match: (I64Store8 [off] (I64AddConst [off2] ptr) val mem)
-       // cond: off+off2 >= 0
+       // cond: isU32Bit(off+off2)
        // result: (I64Store8 [off+off2] ptr val mem)
        for {
                off := v.AuxInt
@@ -5682,7 +5682,7 @@ func rewriteValueWasm_OpWasmI64Store8_0(v *Value) bool {
                ptr := v_0.Args[0]
                val := v.Args[1]
                mem := v.Args[2]
-               if !(off+off2 >= 0) {
+               if !(isU32Bit(off + off2)) {
                        break
                }
                v.reset(OpWasmI64Store8)
index 2b7e12a93f10af3e91c991e34bd6f160b10f9ec2..ca09b3fa0b23e5fde6e4a2311d9e779eb470553e 100644 (file)
@@ -870,6 +870,9 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
                        if p.From.Type != obj.TYPE_CONST {
                                panic("bad type for *Load")
                        }
+                       if p.From.Offset > math.MaxUint32 {
+                               ctxt.Diag("bad offset in %v", p)
+                       }
                        writeUleb128(w, align(p.As))
                        writeUleb128(w, uint64(p.From.Offset))
 
@@ -877,6 +880,9 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
                        if p.To.Offset < 0 {
                                panic("negative offset")
                        }
+                       if p.From.Offset > math.MaxUint32 {
+                               ctxt.Diag("bad offset in %v", p)
+                       }
                        writeUleb128(w, align(p.As))
                        writeUleb128(w, uint64(p.To.Offset))