]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile,go/types: restrict use of unsafe.{Add,Slice} to go1.17 or newer
authorMatthew Dempsky <mdempsky@google.com>
Wed, 2 Jun 2021 19:22:50 +0000 (12:22 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 4 Jun 2021 01:31:23 +0000 (01:31 +0000)
This CL updates cmd/compile (including types2) and go/types to report
errors about using unsafe.Add and unsafe.Slice when language
compatibility is set to Go 1.16 or older.

Fixes #46525.

Change-Id: I1bfe025a672d9f4b929f443064ad1effd38d0363
Reviewed-on: https://go-review.googlesource.com/c/go/+/324369
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/typecheck/func.go
src/cmd/compile/internal/types2/builtins.go
src/go/types/builtins.go
test/fixedbugs/issue46525.go [new file with mode: 0644]

index f381e1dbdc49db47c600280f4e376e24af10cc94..a6dfbbf569ac256b86c3bf6bc39dea6b7fd31c7a 100644 (file)
@@ -981,6 +981,12 @@ func tcRecover(n *ir.CallExpr) ir.Node {
 
 // tcUnsafeAdd typechecks an OUNSAFEADD node.
 func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
+       if !types.AllowsGoVersion(curpkg(), 1, 17) {
+               base.ErrorfVers("go1.17", "unsafe.Add")
+               n.SetType(nil)
+               return n
+       }
+
        n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
        n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
        if n.X.Type() == nil || n.Y.Type() == nil {
@@ -997,6 +1003,12 @@ func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
 
 // tcUnsafeSlice typechecks an OUNSAFESLICE node.
 func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
+       if !types.AllowsGoVersion(curpkg(), 1, 17) {
+               base.ErrorfVers("go1.17", "unsafe.Slice")
+               n.SetType(nil)
+               return n
+       }
+
        n.X = Expr(n.X)
        n.Y = Expr(n.Y)
        if n.X.Type() == nil || n.Y.Type() == nil {
index b9e178dd576c708980bdfe1dc59f56e695aea262..f90e06f226791ddb7630c8b5c6d79788378bf486 100644 (file)
@@ -579,6 +579,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
        case _Add:
                // unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
+               if !check.allowVersion(check.pkg, 1, 17) {
+                       check.error(call.Fun, "unsafe.Add requires go1.17 or later")
+                       return
+               }
+
                check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
                if x.mode == invalid {
                        return
@@ -675,6 +680,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
        case _Slice:
                // unsafe.Slice(ptr *T, len IntegerType) []T
+               if !check.allowVersion(check.pkg, 1, 17) {
+                       check.error(call.Fun, "unsafe.Slice requires go1.17 or later")
+                       return
+               }
+
                typ := asPointer(x.typ)
                if typ == nil {
                        check.errorf(x, invalidArg+"%s is not a pointer", x)
index 739051cc611b3c68488f1c6f8f55bbc4d307a217..2a2d54da88227a60bcb6f5c3dfbf019db61faed4 100644 (file)
@@ -588,6 +588,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
        case _Add:
                // unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
+               if !check.allowVersion(check.pkg, 1, 17) {
+                       check.errorf(call.Fun, _InvalidUnsafeAdd, "unsafe.Add requires go1.17 or later")
+                       return
+               }
+
                check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
                if x.mode == invalid {
                        return
@@ -684,6 +689,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
        case _Slice:
                // unsafe.Slice(ptr *T, len IntegerType) []T
+               if !check.allowVersion(check.pkg, 1, 17) {
+                       check.errorf(call.Fun, _InvalidUnsafeSlice, "unsafe.Slice requires go1.17 or later")
+                       return
+               }
+
                typ := asPointer(x.typ)
                if typ == nil {
                        check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x)
diff --git a/test/fixedbugs/issue46525.go b/test/fixedbugs/issue46525.go
new file mode 100644 (file)
index 0000000..164e147
--- /dev/null
@@ -0,0 +1,14 @@
+// errorcheck -lang=go1.16
+
+// 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 p
+
+import "unsafe"
+
+func main() {
+       _ = unsafe.Add(unsafe.Pointer(nil), 0) // ERROR "unsafe.Add requires go1.17 or later"
+       _ = unsafe.Slice(new(byte), 1)         // ERROR "unsafe.Slice requires go1.17 or later"
+}