From 93453233bd00cc641d2f959f1faf236e0094c2bf Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 22 Sep 2021 15:56:58 -0700 Subject: [PATCH] cmd/compile: fix unsafe.Add with small-size offsets operands 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 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le --- src/cmd/compile/internal/ssagen/ssa.go | 5 +++++ test/fixedbugs/issue48536.go | 29 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 test/fixedbugs/issue48536.go diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 82d232f940..9746fbd316 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -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 index 0000000000..68c7d1c261 --- /dev/null +++ b/test/fixedbugs/issue48536.go @@ -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) + } +} -- 2.50.0