From: Keith Randall Date: Tue, 30 Oct 2018 20:30:09 +0000 (-0700) Subject: cmd/compile: assume unsafe pointer arithmetic generates non-nil results X-Git-Tag: go1.12beta1~354 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0c7762cd184649552309c82671bf81f89d215ff7;p=gostls13.git cmd/compile: assume unsafe pointer arithmetic generates non-nil results 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 --- diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go index f2e17c606b..fca4f0bfc4 100644 --- a/src/cmd/compile/internal/ssa/nilcheck.go +++ b/src/cmd/compile/internal/ssa/nilcheck.go @@ -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 } } diff --git a/src/unsafe/unsafe.go b/src/unsafe/unsafe.go index e16c4aeacb..272761d936 100644 --- a/src/unsafe/unsafe.go +++ b/src/unsafe/unsafe.go @@ -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