mirror of
https://github.com/golang/go
synced 2024-11-18 18:34:40 -07:00
go.tools/go/pointer: eliminate TODOs regarding sound treatment of unsafe.Pointer.
Ain't gonna happen. Also, don't emit a warning when this happens. LGTM=crawshaw R=crawshaw CC=golang-codereviews https://golang.org/cl/110030044
This commit is contained in:
parent
f563a1f0f5
commit
79e0c7b71e
@ -8,15 +8,6 @@ CONSTRAINT GENERATION:
|
||||
- a couple of operators are missing
|
||||
- reflect.Values may contain lvalues (CanAddr)
|
||||
- implement native intrinsics. These vary by platform.
|
||||
- unsafe.Pointer conversions. Three options:
|
||||
1) unsoundly (but type-safely) treat p=unsafe.Pointer(x) conversions as
|
||||
allocations, losing aliases. This is what's currently implemented.
|
||||
2) unsoundly (but type-safely) treat p=unsafe.Pointer(x) and T(p)
|
||||
conversions as interface boxing and unboxing operations.
|
||||
This may preserve some aliasing relations at little cost.
|
||||
3) soundly track physical field offsets. (Summarise dannyb's email here.)
|
||||
A downside is that we can't keep the identity field of struct
|
||||
allocations that identifies the object.
|
||||
- add to pts(a.panic) a label representing all runtime panics, e.g.
|
||||
runtime.{TypeAssertionError,errorString,errorCString}.
|
||||
|
||||
|
@ -435,29 +435,15 @@ func (a *analysis) genConv(conv *ssa.Convert, cgn *cgnode) {
|
||||
case *types.Pointer:
|
||||
// *T -> unsafe.Pointer?
|
||||
if tDst.Underlying() == tUnsafePtr {
|
||||
// ignore for now
|
||||
// a.copy(res, a.valueNode(conv.X), 1)
|
||||
return
|
||||
return // we don't model unsafe aliasing (unsound)
|
||||
}
|
||||
|
||||
case *types.Basic:
|
||||
switch utDst := tDst.Underlying().(type) {
|
||||
switch tDst.Underlying().(type) {
|
||||
case *types.Pointer:
|
||||
// unsafe.Pointer -> *T? (currently unsound)
|
||||
// Treat unsafe.Pointer->*T conversions like
|
||||
// new(T) and create an unaliased object.
|
||||
if utSrc == tUnsafePtr {
|
||||
// For now, suppress unsafe.Pointer conversion
|
||||
// warnings on "syscall" package.
|
||||
// TODO(adonovan): audit for soundness.
|
||||
if conv.Parent().Pkg.Object.Path() != "syscall" {
|
||||
a.warnf(conv.Pos(),
|
||||
"unsound: %s contains an unsafe.Pointer conversion (to %s)",
|
||||
conv.Parent(), tDst)
|
||||
}
|
||||
|
||||
// For now, we treat unsafe.Pointer->*T
|
||||
// conversion like new(T) and create an
|
||||
// unaliased object. In future we may handle
|
||||
// unsafe conversions soundly; see TODO file.
|
||||
obj := a.addNodes(mustDeref(tDst), "unsafe.Pointer conversion")
|
||||
a.endObject(obj, cgn, conv)
|
||||
a.addressOf(tDst, res, obj)
|
||||
@ -474,25 +460,10 @@ func (a *analysis) genConv(conv *ssa.Convert, cgn *cgnode) {
|
||||
}
|
||||
|
||||
case *types.Basic:
|
||||
// TODO(adonovan):
|
||||
// unsafe.Pointer -> uintptr?
|
||||
// uintptr -> unsafe.Pointer
|
||||
//
|
||||
// The language doesn't adequately specify the
|
||||
// behaviour of these operations, but almost
|
||||
// all uses of these conversions (even in the
|
||||
// spec) seem to imply a non-moving garbage
|
||||
// collection strategy, or implicit "pinning"
|
||||
// semantics for unsafe.Pointer conversions.
|
||||
|
||||
// TODO(adonovan): we need more work before we can handle
|
||||
// cryptopointers well.
|
||||
if utSrc == tUnsafePtr || utDst == tUnsafePtr {
|
||||
// Ignore for now. See TODO file for ideas.
|
||||
return
|
||||
}
|
||||
|
||||
return // ignore all other basic type conversions
|
||||
// All basic-to-basic type conversions are no-ops.
|
||||
// This includes uintptr<->unsafe.Pointer conversions,
|
||||
// which we (unsoundly) ignore.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,12 +152,12 @@ func init() {
|
||||
"sync/atomic.CompareAndSwapUintptr": ext۰NoEffect,
|
||||
"sync/atomic.LoadInt32": ext۰NoEffect,
|
||||
"sync/atomic.LoadInt64": ext۰NoEffect,
|
||||
"sync/atomic.LoadPointer": ext۰NoEffect, // ignore unsafe.Pointer for now
|
||||
"sync/atomic.LoadPointer": ext۰NoEffect, // ignore unsafe.Pointers
|
||||
"sync/atomic.LoadUint32": ext۰NoEffect,
|
||||
"sync/atomic.LoadUint64": ext۰NoEffect,
|
||||
"sync/atomic.LoadUintptr": ext۰NoEffect,
|
||||
"sync/atomic.StoreInt32": ext۰NoEffect,
|
||||
"sync/atomic.StorePointer": ext۰NoEffect, // ignore unsafe.Pointer for now
|
||||
"sync/atomic.StorePointer": ext۰NoEffect, // ignore unsafe.Pointers
|
||||
"sync/atomic.StoreUint32": ext۰NoEffect,
|
||||
"sync/atomic.StoreUintptr": ext۰NoEffect,
|
||||
"syscall.Close": ext۰NoEffect,
|
||||
|
2
go/pointer/testdata/conv.go
vendored
2
go/pointer/testdata/conv.go
vendored
@ -40,11 +40,9 @@ func conv3() {
|
||||
print(*y) // @pointsto main.a
|
||||
}
|
||||
|
||||
// @warning "main.conv4 contains an unsafe.Pointer conversion"
|
||||
func conv4() {
|
||||
// Handling of unsafe.Pointer conversion is unsound:
|
||||
// we lose the alias to main.a and get something like new(int) instead.
|
||||
// We require users to provide aliasing summaries.
|
||||
p := (*int)(unsafe.Pointer(&a)) // @line c2p
|
||||
print(p) // @pointsto convert@c2p:13
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user