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: reflect: remove Value.Bytes and Value.Runes #27727

Open
bcmills opened this Issue Sep 18, 2018 · 1 comment

Comments

Projects
None yet
3 participants
@bcmills
Copy link
Member

bcmills commented Sep 18, 2018

Background

As noted in #24746 (comment), (reflect.Value).Bytes and (reflect.Value).Runes are the only reflect.Value methods that return mutable values without enforcing CanSet or CanInterface.

That makes dangerous mutations through []byte and []rune (and slices of defined types with byte or rune as the underlying type) more difficult to detect, since they do not involve unsafe or syscall in the way that other dangerous mutations must.

This is a proposal to close that mutability loophole and make the handling of byte and rune slice types more consistent with other slices.

Proposal

This proposal consists of two parts:

  1. Remove Value.Bytes and Value.Runes, making them accessible only to Go 1 code.
  2. Relax reflect.Copy, reflect.Append, and reflect.AppendSlice to allow the source argument (but not the destination) to be obtained through unexported fields, provided that the element type of the slice does not contain any pointers or interfaces.
    • Today, those functions panic if any argument was obtained through unexported fields.

Users could replace a call to Bytes or Runes on an exported field of known element type with a call to Interface and a type-assertion (https://play.golang.org/p/9LJIDW7ftZx).

To examine slices obtained via unexported fields (and slices of defined types with byte or rune as their underlying type), users could employ any of four strategies:

Note that the latter three are already possible today: part (2) of this proposal only affects the clarity of the code, not what is possible to express.

Alternatives

We could keep the Bytes and Runes methods, but make them panic if CanInterface returns false.

  • That would allow more existing code to continue to compile, but at the risk of introducing a run-time error. I prefer to make it a complie-time error in order to prompt the user to consider whether to introduce a run-time check, make a copy, or use an unsafe operation.

We could go even further and remove SetBytes and SetRunes, since they are redundant with Copy.

  • That would make the treatment of []byte and []rune more like every other slice type.
  • Since those methods don't introduce any loopholes in the usual mutability rules, removing them does not seem worth the code churn.

If we had read-only slices (#22876 and associated issues), we could make Bytes and Runes return read-only slices.

  • In contrast, this proposal does not rely on any new language features.
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

ianlancetaylor commented Oct 16, 2018

The current Bytes and Runes method are a general type safety hole, since they permit changing the value of an unexported field. We should do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment