aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2020-08-19 21:39:12 -0700
committerDmitri Shuralyov <dmitshur@golang.org>2020-08-21 23:45:28 +0000
commit24dbf3e136da73770300ef8f639e89bd372ed9c9 (patch)
tree4cf7e5047af2975330ed12880fd3100ecbd661cc
parent1112871bf24cd4bd1144e1ee51e8a4cd538bdb9b (diff)
downloadgo-24dbf3e136da73770300ef8f639e89bd372ed9c9.tar.gz
go-24dbf3e136da73770300ef8f639e89bd372ed9c9.zip
[release-branch.go1.14] cmd/compile: fix checkptr handling of &^
checkptr has code to recognize &^ expressions, but it didn't take into account that "p &^ x" gets rewritten to "p & ^x" during walk, which resulted in false positive diagnostics. This CL changes walkexpr to mark OANDNOT expressions with Implicit when they're rewritten to OAND, so that walkCheckPtrArithmetic can still recognize them later. It would be slightly more idiomatic to instead mark the OBITNOT expression as Implicit (as it's a compiler-generated Node), but the OBITNOT expression might get constant folded. It's not worth the extra complexity/subtlety of relying on n.Right.Orig, so we set Implicit on the OAND node instead. To atone for this transgression, I add documentation for nodeImplicit. Updates #40917. Fixes #40968. Change-Id: I386304171ad299c530e151e5924f179e9a5fd5b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/249477 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/249838 Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/syntax.go4
-rw-r--r--src/cmd/compile/internal/gc/walk.go7
-rw-r--r--src/runtime/checkptr_test.go1
-rw-r--r--src/runtime/testdata/testprog/checkptr.go8
-rw-r--r--test/fixedbugs/issue40917.go23
5 files changed, 40 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index de187959fd..8bad47d62b 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -141,8 +141,8 @@ const (
nodeInitorder, _ // tracks state during init1; two bits
_, _ // second nodeInitorder bit
_, nodeHasBreak
- _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
- _, nodeImplicit
+ _, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
+ _, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP; or ANDNOT lowered to OAND
_, nodeIsDDD // is the argument variadic
_, nodeDiag // already printed error about this
_, nodeColas // OAS resulting from :=
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index b8b954c4fc..483f338f0e 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -984,6 +984,7 @@ opswitch:
case OANDNOT:
n.Left = walkexpr(n.Left, init)
n.Op = OAND
+ n.SetImplicit(true) // for walkCheckPtrArithmetic
n.Right = nod(OBITNOT, n.Right, nil)
n.Right = typecheck(n.Right, ctxExpr)
n.Right = walkexpr(n.Right, init)
@@ -4056,8 +4057,12 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node {
case OADD:
walk(n.Left)
walk(n.Right)
- case OSUB, OANDNOT:
+ case OSUB:
walk(n.Left)
+ case OAND:
+ if n.Implicit() { // was OANDNOT
+ walk(n.Left)
+ }
case OCONVNOP:
if n.Left.Type.Etype == TUNSAFEPTR {
n.Left = cheapexpr(n.Left, init)
diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go
index 624f1b62d2..8887254e93 100644
--- a/src/runtime/checkptr_test.go
+++ b/src/runtime/checkptr_test.go
@@ -27,6 +27,7 @@ func TestCheckPtr(t *testing.T) {
{"CheckPtrAlignmentPtr", "fatal error: checkptr: unsafe pointer conversion\n"},
{"CheckPtrAlignmentNoPtr", ""},
{"CheckPtrArithmetic", "fatal error: checkptr: unsafe pointer arithmetic\n"},
+ {"CheckPtrArithmetic2", "fatal error: checkptr: unsafe pointer arithmetic\n"},
{"CheckPtrSize", "fatal error: checkptr: unsafe pointer conversion\n"},
{"CheckPtrSmall", "fatal error: checkptr: unsafe pointer arithmetic\n"},
}
diff --git a/src/runtime/testdata/testprog/checkptr.go b/src/runtime/testdata/testprog/checkptr.go
index 45e6fb1aa5..e0a2794f4c 100644
--- a/src/runtime/testdata/testprog/checkptr.go
+++ b/src/runtime/testdata/testprog/checkptr.go
@@ -10,6 +10,7 @@ func init() {
register("CheckPtrAlignmentNoPtr", CheckPtrAlignmentNoPtr)
register("CheckPtrAlignmentPtr", CheckPtrAlignmentPtr)
register("CheckPtrArithmetic", CheckPtrArithmetic)
+ register("CheckPtrArithmetic2", CheckPtrArithmetic2)
register("CheckPtrSize", CheckPtrSize)
register("CheckPtrSmall", CheckPtrSmall)
}
@@ -32,6 +33,13 @@ func CheckPtrArithmetic() {
sink2 = (*int)(unsafe.Pointer(i))
}
+func CheckPtrArithmetic2() {
+ var x [2]int64
+ p := unsafe.Pointer(&x[1])
+ var one uintptr = 1
+ sink2 = unsafe.Pointer(uintptr(p) & ^one)
+}
+
func CheckPtrSize() {
p := new(int64)
sink2 = p
diff --git a/test/fixedbugs/issue40917.go b/test/fixedbugs/issue40917.go
new file mode 100644
index 0000000000..2128be5eca
--- /dev/null
+++ b/test/fixedbugs/issue40917.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=checkptr
+
+// Copyright 2020 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"
+
+func main() {
+ var x [2]uint64
+ a := unsafe.Pointer(&x[1])
+
+ b := a
+ b = unsafe.Pointer(uintptr(b) + 2)
+ b = unsafe.Pointer(uintptr(b) - 1)
+ b = unsafe.Pointer(uintptr(b) &^ 1)
+
+ if a != b {
+ panic("pointer arithmetic failed")
+ }
+}