]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix checkptr false positive for (*[Big]T)(ptr)[:n:n] pattern
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Fri, 20 Aug 2021 04:38:54 +0000 (11:38 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Wed, 25 Aug 2021 01:57:42 +0000 (01:57 +0000)
The checkptr instrumentation is currently inserted before slice
operation has validated that n <= Big. So instead of panic, checkptr
have false positive throws.

To fix this, just insert the checkptr instrumentation after the bound
checking during SSA generation.

Fixes #46938

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

index f526d987a7b20e6318655445319c30a7a1cda058..41de6bd61b29a3694b6fe9c2ea722156daced7b0 100644 (file)
@@ -570,10 +570,11 @@ func (*SelectorExpr) CanBeNtype() {}
 // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
 type SliceExpr struct {
        miniExpr
-       X    Node
-       Low  Node
-       High Node
-       Max  Node
+       X            Node
+       Low          Node
+       High         Node
+       Max          Node
+       CheckPtrCall *CallExpr
 }
 
 func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
index 39d3b206ac6e1b5f259acd4dd72c5dbd376f0814..0a48f6b70422372419c606060625a0a1ce10e25d 100644 (file)
@@ -3090,6 +3090,9 @@ func (s *state) expr(n ir.Node) *ssa.Value {
                        k = s.expr(n.Max)
                }
                p, l, c := s.slice(v, i, j, k, n.Bounded())
+               if n.CheckPtrCall != nil {
+                       s.stmt(n.CheckPtrCall)
+               }
                return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c)
 
        case ir.OSLICESTR:
index 27a07ce4b6085031262d6e8590703fcceaa0114b..f724ca7cae95bb1077c44bb69e10c78bd8d97033 100644 (file)
@@ -413,11 +413,15 @@ func byteindex(n ir.Node) ir.Node {
        return n
 }
 
-func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, count ir.Node) ir.Node {
+func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, se *ir.SliceExpr) ir.Node {
        if !n.Type().IsPtr() {
                base.Fatalf("expected pointer type: %v", n.Type())
        }
        elem := n.Type().Elem()
+       var count ir.Node
+       if se != nil {
+               count = se.Max
+       }
        if count != nil {
                if !elem.IsArray() {
                        base.Fatalf("expected array type: %v", elem)
@@ -435,7 +439,12 @@ func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, count ir.Node) ir.Nod
        }
 
        n.X = cheapExpr(n.X, init)
-       init.Append(mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR])))
+       checkPtrCall := mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR]))
+       if se != nil {
+               se.CheckPtrCall = checkPtrCall
+       } else {
+               init.Append(checkPtrCall)
+       }
        return n
 }
 
index 26e225440a73d5ed2d35c282d4d879222e828944..c04998137b453802ae98520757687409016243e2 100644 (file)
@@ -824,7 +824,7 @@ func walkSlice(n *ir.SliceExpr, init *ir.Nodes) ir.Node {
        n.High = walkExpr(n.High, init)
        n.Max = walkExpr(n.Max, init)
        if checkSlice {
-               n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n.Max)
+               n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n)
        }
 
        if n.Op().IsSlice3() {
diff --git a/test/fixedbugs/issue46938.go b/test/fixedbugs/issue46938.go
new file mode 100644 (file)
index 0000000..87532d4
--- /dev/null
@@ -0,0 +1,29 @@
+// run -gcflags="-d=checkptr"
+
+// 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 (
+       "strings"
+       "unsafe"
+)
+
+func main() {
+       defer func() {
+               err := recover()
+               if err == nil {
+                       panic("expected panic")
+               }
+               if got := err.(error).Error(); !strings.Contains(got, "slice bounds out of range") {
+                       panic("expected panic slice out of bound, got " + got)
+               }
+       }()
+       s := make([]int64, 100)
+       p := unsafe.Pointer(&s[0])
+       n := 1000
+
+       _ = (*[10]int64)(p)[:n:n]
+}