aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2021-05-09 11:06:17 -0700
committerKeith Randall <khr@golang.org>2021-05-10 13:16:56 +0000
commit287025925f66f90ad9b30aea2e533928026a8376 (patch)
treed1d08af3e2dbb39ee461a3d9bc821b406e6a384b /src/internal
parentc14ecaca8182314efd2ef7280feffc2242644887 (diff)
downloadgo-287025925f66f90ad9b30aea2e533928026a8376.tar.gz
go-287025925f66f90ad9b30aea2e533928026a8376.zip
cmd/compile,reflect: allow longer type names
Encode the length of type names and tags in a varint encoding instead of a fixed 2-byte encoding. This allows lengths longer than 65535 (which can happen for large unnamed structs). Removed the alignment check for #14962, it isn't relevant any more since we're no longer reading pointers directly out of this data (it is encoded as an offset which is copied out bytewise). Fixes #44155 Update #14962 Change-Id: I6084f6027e5955dc16777c87b0dd5ea2baa49629 Reviewed-on: https://go-review.googlesource.com/c/go/+/318249 Trust: Keith Randall <khr@golang.org> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/reflectlite/all_test.go13
-rw-r--r--src/internal/reflectlite/type.go52
2 files changed, 29 insertions, 36 deletions
diff --git a/src/internal/reflectlite/all_test.go b/src/internal/reflectlite/all_test.go
index e2c4f30487..e15f364fcd 100644
--- a/src/internal/reflectlite/all_test.go
+++ b/src/internal/reflectlite/all_test.go
@@ -982,19 +982,6 @@ func TestNames(t *testing.T) {
}
}
-type embed struct {
- EmbedWithUnexpMeth
-}
-
-func TestNameBytesAreAligned(t *testing.T) {
- typ := TypeOf(embed{})
- b := FirstMethodNameBytes(typ)
- v := uintptr(unsafe.Pointer(b))
- if v%unsafe.Alignof((*byte)(nil)) != 0 {
- t.Errorf("reflect.name.bytes pointer is not aligned: %x", v)
- }
-}
-
// TestUnaddressableField tests that the reflect package will not allow
// a type from another package to be used as a named type with an
// unexported field.
diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go
index 15ba30da36..f529f7c5fc 100644
--- a/src/internal/reflectlite/type.go
+++ b/src/internal/reflectlite/type.go
@@ -321,49 +321,55 @@ func (n name) isExported() bool {
return (*n.bytes)&(1<<0) != 0
}
-func (n name) nameLen() int {
- return int(uint16(*n.data(1, "name len field"))<<8 | uint16(*n.data(2, "name len field")))
-}
-
-func (n name) tagLen() int {
- if *n.data(0, "name flag field")&(1<<1) == 0 {
- return 0
+func (n name) hasTag() bool {
+ return (*n.bytes)&(1<<1) != 0
+}
+
+// readVarint parses a varint as encoded by encoding/binary.
+// It returns the number of encoded bytes and the encoded value.
+func (n name) readVarint(off int) (int, int) {
+ v := 0
+ for i := 0; ; i++ {
+ x := *n.data(off+i, "read varint")
+ v += int(x&0x7f) << (7 * i)
+ if x&0x80 == 0 {
+ return i + 1, v
+ }
}
- off := 3 + n.nameLen()
- return int(uint16(*n.data(off, "name taglen field"))<<8 | uint16(*n.data(off+1, "name taglen field")))
}
func (n name) name() (s string) {
if n.bytes == nil {
return
}
- b := (*[4]byte)(unsafe.Pointer(n.bytes))
-
+ i, l := n.readVarint(1)
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
- hdr.Data = unsafe.Pointer(&b[3])
- hdr.Len = int(b[1])<<8 | int(b[2])
- return s
+ hdr.Data = unsafe.Pointer(n.data(1+i, "non-empty string"))
+ hdr.Len = l
+ return
}
func (n name) tag() (s string) {
- tl := n.tagLen()
- if tl == 0 {
+ if !n.hasTag() {
return ""
}
- nl := n.nameLen()
+ i, l := n.readVarint(1)
+ i2, l2 := n.readVarint(1 + i + l)
hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
- hdr.Data = unsafe.Pointer(n.data(3+nl+2, "non-empty string"))
- hdr.Len = tl
- return s
+ hdr.Data = unsafe.Pointer(n.data(1+i+l+i2, "non-empty string"))
+ hdr.Len = l2
+ return
}
func (n name) pkgPath() string {
if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
return ""
}
- off := 3 + n.nameLen()
- if tl := n.tagLen(); tl > 0 {
- off += 2 + tl
+ i, l := n.readVarint(1)
+ off := 1 + i + l
+ if n.hasTag() {
+ i2, l2 := n.readVarint(off)
+ off += i2 + l2
}
var nameOff int32
// Note that this field may not be aligned in memory,