// 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 {
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:
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)
}
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
}
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() {
--- /dev/null
+// 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]
+}