aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/gob/type.go
diff options
context:
space:
mode:
authorAndy Pan <panjf2000@gmail.com>2023-08-18 13:39:57 +0800
committerGopher Robot <gobot@golang.org>2023-08-19 23:03:14 +0000
commitba626ac327f45a6d9d211fddd5b48e321fa0702a (patch)
treee19a50997936bcf46f8d85de099a39a40a8e48b3 /src/encoding/gob/type.go
parent7b2f81eb3b19232c1d3a60241cb92c1c50d0e4ab (diff)
downloadgo-ba626ac327f45a6d9d211fddd5b48e321fa0702a.tar.xz
encoding/gob: prevent panic from index out of range in Decoder.typeString
I believe this bug is introduced by CL 460543 which optimizes the allocations by changing the type of `idToType` from map to slice, but didn't update the access code in `Decoder.typeString` that is safe for map but not for slice. Fixes #62117 Change-Id: I0f2e4cc2f34c54dada1f83458ba512a6fde6dcbe Reviewed-on: https://go-review.googlesource.com/c/go/+/520757 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Run-TryBot: Andy Pan <panjf2000@gmail.com> Auto-Submit: Ian Lance Taylor <iant@golang.org> Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'src/encoding/gob/type.go')
-rw-r--r--src/encoding/gob/type.go29
1 files changed, 19 insertions, 10 deletions
diff --git a/src/encoding/gob/type.go b/src/encoding/gob/type.go
index acc36425bd..24105c5e11 100644
--- a/src/encoding/gob/type.go
+++ b/src/encoding/gob/type.go
@@ -173,9 +173,18 @@ type gobType interface {
safeString(seen map[typeId]bool) string
}
-var types = make(map[reflect.Type]gobType, 32)
-var idToType = make([]gobType, 1, firstUserId)
-var builtinIdToTypeSlice [firstUserId]gobType // set in init() after builtins are established
+var (
+ types = make(map[reflect.Type]gobType, 32)
+ idToTypeSlice = make([]gobType, 1, firstUserId)
+ builtinIdToTypeSlice [firstUserId]gobType // set in init() after builtins are established
+)
+
+func idToType(id typeId) gobType {
+ if id < 0 || int(id) >= len(idToTypeSlice) {
+ return nil
+ }
+ return idToTypeSlice[id]
+}
func builtinIdToType(id typeId) gobType {
if id < 0 || int(id) >= len(builtinIdToTypeSlice) {
@@ -189,16 +198,16 @@ func setTypeId(typ gobType) {
if typ.id() != 0 {
return
}
- nextId := typeId(len(idToType))
+ nextId := typeId(len(idToTypeSlice))
typ.setId(nextId)
- idToType = append(idToType, typ)
+ idToTypeSlice = append(idToTypeSlice, typ)
}
func (t typeId) gobType() gobType {
if t == 0 {
return nil
}
- return idToType[t]
+ return idToType(t)
}
// string returns the string representation of the type associated with the typeId.
@@ -277,14 +286,14 @@ func init() {
checkId(21, mustGetTypeInfo(reflect.TypeFor[fieldType]()).id)
checkId(23, mustGetTypeInfo(reflect.TypeFor[mapType]()).id)
- copy(builtinIdToTypeSlice[:], idToType)
+ copy(builtinIdToTypeSlice[:], idToTypeSlice)
// Move the id space upwards to allow for growth in the predefined world
// without breaking existing files.
- if nextId := len(idToType); nextId > firstUserId {
+ if nextId := len(idToTypeSlice); nextId > firstUserId {
panic(fmt.Sprintln("nextId too large:", nextId))
}
- idToType = idToType[:firstUserId]
+ idToTypeSlice = idToTypeSlice[:firstUserId]
registerBasics()
wireTypeUserInfo = userType(wireTypeType)
}
@@ -526,7 +535,7 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, err
case reflect.Struct:
st := newStructType(name)
types[rt] = st
- idToType[st.id()] = st
+ idToTypeSlice[st.id()] = st
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if !isSent(&f) {