]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix unsafe.Add with small-size offsets operands
authorMatthew Dempsky <mdempsky@google.com>
Wed, 22 Sep 2021 22:56:58 +0000 (15:56 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 23 Sep 2021 00:14:22 +0000 (00:14 +0000)
Like other builtin functions, unsafe.Add's len operand is allowed to
be variable sized. However, unlike other builtins, it doesn't get
lowered to a runtime function call, so we never end up coercing it to
a specific type. As a result, we could end up constructing an OpAddPtr
value but with a less-than-ptr-sized addend operand.

This CL fixes this by always coercing the second operand to uintptr
during SSA construction.

Theoretically, we could do this during walk instead, but the frontend
doesn't allow converting negative constants to uintptr.

Fixes #48536.

Change-Id: Ib0619ea79df58b256b250fec967a6d3c8afea631
Reviewed-on: https://go-review.googlesource.com/c/go/+/351592
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/ssagen/ssa.go
test/fixedbugs/issue48536.go [new file with mode: 0644]

index 82d232f940501a8c2afa4b111048135097a04b6d..9746fbd3165c27958e44cebb75bb9c9123307c80 100644 (file)
@@ -3206,6 +3206,11 @@ func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value {
                n := n.(*ir.BinaryExpr)
                ptr := s.expr(n.X)
                len := s.expr(n.Y)
+
+               // Force len to uintptr to prevent misuse of garbage bits in the
+               // upper part of the register (#48536).
+               len = s.conv(n, len, len.Type, types.Types[types.TUINTPTR])
+
                return s.newValue2(ssa.OpAddPtr, n.Type(), ptr, len)
 
        default:
diff --git a/test/fixedbugs/issue48536.go b/test/fixedbugs/issue48536.go
new file mode 100644 (file)
index 0000000..68c7d1c
--- /dev/null
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+var i = 257
+
+func main() {
+       var buf [10]byte
+       p0 := unsafe.Pointer(&buf[0])
+       p1 := unsafe.Pointer(&buf[1])
+
+       if p := unsafe.Add(p0, uint8(i)); p != p1 {
+               println("FAIL:", p, "!=", p1)
+       }
+
+       var x uint8
+       if i != 0 {
+               x = 1
+       }
+       if p := unsafe.Add(p0, x); p != p1 {
+               println("FAIL:", p, "!=", p1)
+       }
+}