aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/reflectdata/reflect.go
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/cmd/compile/internal/reflectdata/reflect.go
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/cmd/compile/internal/reflectdata/reflect.go')
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go29
1 files changed, 16 insertions, 13 deletions
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index 01eaf26a0a..8c0e33f6df 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -5,6 +5,7 @@
package reflectdata
import (
+ "encoding/binary"
"fmt"
"internal/buildcfg"
"os"
@@ -473,21 +474,25 @@ func dnameField(lsym *obj.LSym, ot int, spkg *types.Pkg, ft *types.Field) int {
// dnameData writes the contents of a reflect.name into s at offset ot.
func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported bool) int {
- if len(name) > 1<<16-1 {
- base.Fatalf("name too long: %s", name)
+ if len(name) >= 1<<29 {
+ base.Fatalf("name too long: %d %s...", len(name), name[:1024])
}
- if len(tag) > 1<<16-1 {
- base.Fatalf("tag too long: %s", tag)
+ if len(tag) >= 1<<29 {
+ base.Fatalf("tag too long: %d %s...", len(tag), tag[:1024])
}
+ var nameLen [binary.MaxVarintLen64]byte
+ nameLenLen := binary.PutUvarint(nameLen[:], uint64(len(name)))
+ var tagLen [binary.MaxVarintLen64]byte
+ tagLenLen := binary.PutUvarint(tagLen[:], uint64(len(tag)))
// Encode name and tag. See reflect/type.go for details.
var bits byte
- l := 1 + 2 + len(name)
+ l := 1 + nameLenLen + len(name)
if exported {
bits |= 1 << 0
}
if len(tag) > 0 {
- l += 2 + len(tag)
+ l += tagLenLen + len(tag)
bits |= 1 << 1
}
if pkg != nil {
@@ -495,14 +500,12 @@ func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported b
}
b := make([]byte, l)
b[0] = bits
- b[1] = uint8(len(name) >> 8)
- b[2] = uint8(len(name))
- copy(b[3:], name)
+ copy(b[1:], nameLen[:nameLenLen])
+ copy(b[1+nameLenLen:], name)
if len(tag) > 0 {
- tb := b[3+len(name):]
- tb[0] = uint8(len(tag) >> 8)
- tb[1] = uint8(len(tag))
- copy(tb[2:], tag)
+ tb := b[1+nameLenLen+len(name):]
+ copy(tb, tagLen[:tagLenLen])
+ copy(tb[tagLenLen:], tag)
}
ot = int(s.WriteBytes(base.Ctxt, int64(ot), b))