]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: assume unsafe pointer arithmetic generates non-nil results
authorKeith Randall <khr@google.com>
Tue, 30 Oct 2018 20:30:09 +0000 (13:30 -0700)
committerKeith Randall <khr@golang.org>
Wed, 14 Nov 2018 21:01:36 +0000 (21:01 +0000)
I've never seen a case where unsafe arithmetic is used to generate a nil.
(Something like var x uintptr; unsafe.Pointer(x - x).)
We can assume that if someone is doing arithmetic with pointers, the
result will be non-nil. Our unsafe rules already forbid this, although
we should be more explicit.

RELNOTE=It is invalid to convert a nil unsafe.Pointer to uintptr and back, with arithmetic.
(This was already invalid, but this statement has been added for clarification.)

Fixes #27180

Change-Id: I1880b7725a9fd99e4613799930fdad9aaa99e8f0
Reviewed-on: https://go-review.googlesource.com/c/146058
Reviewed-by: Austin Clements <austin@google.com>
src/cmd/compile/internal/ssa/nilcheck.go
src/unsafe/unsafe.go

index f2e17c606b50e718a8e30fd83f76836ff88997e2..fca4f0bfc4076d3a4446b03ad9466bd7ce045e6a 100644 (file)
@@ -47,7 +47,8 @@ func nilcheckelim(f *Func) {
                        // a value resulting from taking the address of a
                        // value, or a value constructed from an offset of a
                        // non-nil ptr (OpAddPtr) implies it is non-nil
-                       if v.Op == OpAddr || v.Op == OpLocalAddr || v.Op == OpAddPtr || v.Op == OpOffPtr {
+                       // We also assume unsafe pointer arithmetic generates non-nil pointers. See #27180.
+                       if v.Op == OpAddr || v.Op == OpLocalAddr || v.Op == OpAddPtr || v.Op == OpOffPtr || v.Op == OpAdd32 || v.Op == OpAdd64 || v.Op == OpSub32 || v.Op == OpSub64 {
                                nonNilValues[v.ID] = true
                        }
                }
index e16c4aeacbe6fee00c59f2f29f9a456b19f4ff7c..272761d9363a4256c0254f247177234ee94ad6a7 100644 (file)
@@ -99,6 +99,12 @@ type ArbitraryType int
 //     u := uintptr(p)
 //     p = unsafe.Pointer(u + offset)
 //
+// Note that the pointer must point into an allocated object, so it may not be nil.
+//
+//     // INVALID: conversion of nil pointer
+//     u := unsafe.Pointer(nil)
+//     p := unsafe.Pointer(uintptr(u) + offset)
+//
 // (4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.
 //
 // The Syscall functions in package syscall pass their uintptr arguments directly