Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: only give special properties to unsafe.Pointer if package imports unsafe #26070

Closed
ianlancetaylor opened this issue Jun 26, 2018 · 7 comments
Labels
FrozenDueToAge LanguageChange NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. Proposal v2 A language change or incompatible library change
Milestone

Comments

@ianlancetaylor
Copy link
Contributor

One of the difficulties of unsafe.Pointer is that if a package gets a value of type unsafe.Pointer then it can convert that pointer to other pointer types, or uintptr. This is true even if the package does not itself import "unsafe", but gets the unsafe.Pointer value by calling some other package. This is the reason that reflect.Value.Pointer returns uintptr rather than unsafe.Pointer.

For Go 2 I propose that we change the language to say that values of type unsafe.Pointer only have their special properties in packages that explicitly import "unsafe". If a package does not import "unsafe", then a value of type unsafe.Pointer may not be converted to other type.

If we make that change, then, Go 1 compatibility rules aside, we can safely permit reflect.Value.Pointer to return unsafe.Pointer.

@ianlancetaylor ianlancetaylor added LanguageChange v2 A language change or incompatible library change Proposal labels Jun 26, 2018
@ianlancetaylor ianlancetaylor added this to the Proposal milestone Jun 26, 2018
@ianlancetaylor ianlancetaylor added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Jun 26, 2018
@randall77
Copy link
Contributor

Presumably this will also let us redefine reflect.StringHeader and reflect.SliceHeader to use unsafe.Pointer instead of uintptr.

@robpike
Copy link
Contributor

robpike commented Jun 26, 2018

I like this one.

@bcmills
Copy link
Contributor

bcmills commented Jun 26, 2018

Under this proposal, in order to determine whether a conversion expression T(x) may be an unsafe.Pointer conversion, the reader still needs to know three things that may not be locally obvious:

  1. whether the operand is a pointer or uintptr type,
  2. whether T is an alias for unsafe.Pointer, and
  3. whether the current source file has imported package unsafe.

(1) and (2) may be arbitrarily distant in the code (even across package boundaries); (3) is fairly easy to find within the source file, but still requires the reader to jump from the current context to the import block and back.

In contrast, with a function-based unsafe API (such as the one @griesemer and I discussed in #20171), I believe all of that information could be present within the conversion expression itself.

(I do agree that this proposal is a strict improvement over the status quo, but in the space of “fixes for unsafe.Pointer” it seems like the low-cost/low-benefit solution. I wonder whether we could get a much larger benefit for an only marginally higher cost.)

@gopherbot gopherbot removed the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Aug 16, 2019
@gopherbot gopherbot added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Sep 3, 2019
@mdempsky
Copy link
Member

mdempsky commented Oct 24, 2019

If we make that change, then, Go 1 compatibility rules aside, we can safely permit reflect.Value.Pointer to return unsafe.Pointer.

I don't find this argument compelling. I think we can safely permit reflect.Value.Pointer to return unsafe.Pointer today anyway (again, Go 1 compatibility rules aside).

The Go toolchain no longer supports "safe" mode, so there's no builtin functionality that restricts access to package unsafe. So this argument is implicitly assuming some external safety-validation tool that restricts access to package unsafe.

But then I don't see any reason such an external tool can't just look for unsafe.Pointer->*T conversions in addition to disallowing import "unsafe". That's really no different than what cmd/compile, gccgo, and go/types would all be required to do anyway.

I think a security-oriented subset of Go a la Joe-E or Caja would be fun to work on, but I don't think trying to one-off tackle individual issues is going to get us there. (I also suspect compiling to wasm is a more pragmatic solution to this problem.)

That said, we already tie other unsafe features like //go:linkname to import "unsafe", so it's not like this is without precedent.

So overall I'd say I'm weakly opposed.

@mdempsky
Copy link
Member

mdempsky commented Aug 5, 2020

Note that reflect.NewAt allows converting unsafe.Pointer values to any pointer type even without compiler magic: https://play.golang.org/p/w-6sabmpnz9

@rsc
Copy link
Contributor

rsc commented Aug 12, 2020

@mdempsky's comment does seem like a show-stopper: there's not much point in taking away tp := (*T)(u) if you can still write tp := reflect.NewAt(reflect.TypeOf((*T)(nil)), u).Interface().(*T) instead.

So probably this proposal should be declined.

Now that there are no longer any environments penalizing unsafe (in particular, App Engine does not reject unsafe anymore), we could add reflect.Value.UnsafePointer returning unsafe.Pointer.

@ianlancetaylor
Copy link
Contributor Author

Retracting.

@golang golang locked and limited conversation to collaborators Aug 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. Proposal v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

7 participants