Skip to content

Commit 8234134

Browse files
committed
gopls/internal/lsp/frob: add defensive header
I can't explain the crash in the bug report: the frob logic looks sound, which leaves these possibilities: (a) the provided data is garbage or is being trampled (but the caller logic looks sound); (b) the file contents are corrupted (but the filecache SHA256 checksum was fine); (c) there's a RAM problem (but that always feels like a cop-out explanation). I've added a magic number to the file header so that there's a chance we'll detect some variants of a and b. Updates golang/go#62383 Change-Id: Icd32a2dc6ab019f3deee1b332428e0313c93a6ff Reviewed-on: https://go-review.googlesource.com/c/tools/+/524655 Run-TryBot: Alan Donovan <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent e3671fc commit 8234134

File tree

3 files changed

+16
-7
lines changed

3 files changed

+16
-7
lines changed

gopls/internal/lsp/filecache/filecache.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ type memKey struct {
6060
key [32]byte
6161
}
6262

63-
// Get retrieves from the cache and returns a newly allocated
64-
// copy of the value most recently supplied to Set(kind, key),
65-
// possibly by another process.
63+
// Get retrieves from the cache and returns the value most recently
64+
// supplied to Set(kind, key), possibly by another process.
6665
// Get returns ErrNotFound if the value was not found.
66+
//
67+
// Callers should not modify the returned array.
6768
func Get(kind string, key [32]byte) ([]byte, error) {
6869
// First consult the read-through memory cache.
6970
// Note that memory cache hits do not update the times

gopls/internal/lsp/frob/frob.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
// Package frob is a fast restricted object encoder/decoder in the
66
// spirit of encoding/gob.
77
//
8-
// As with gob, types that recursively contain functions,
9-
// channels, and unsafe.Pointers cannot encoded, but frob has these
8+
// As with gob, types that recursively contain functions, channels,
9+
// and unsafe.Pointers cannot be encoded, but frob has these
1010
// additional restrictions:
1111
//
1212
// - Interface values are not supported; this avoids the need for
@@ -24,8 +24,6 @@
2424
//
2525
// - There is no error handling. All errors are reported by panicking.
2626
//
27-
// - Types that (recursively) contain private struct fields are not permitted.
28-
//
2927
// - Values are serialized as trees, not graphs, so shared subgraphs
3028
// are encoded repeatedly.
3129
//
@@ -123,12 +121,15 @@ func (fr *frob) addElem(t reflect.Type) {
123121
fr.elems = append(fr.elems, frobFor(t))
124122
}
125123

124+
const magic = "frob"
125+
126126
func (fr *frob) Encode(v any) []byte {
127127
rv := reflect.ValueOf(v)
128128
if rv.Type() != fr.t {
129129
panic(fmt.Sprintf("got %v, want %v", rv.Type(), fr.t))
130130
}
131131
w := &writer{}
132+
w.bytes([]byte(magic))
132133
fr.encode(w, rv)
133134
if uint64(len(w.data))>>32 != 0 {
134135
panic("too large") // includes all cases where len doesn't fit in 32 bits
@@ -244,6 +245,9 @@ func (fr *frob) Decode(data []byte, ptr any) {
244245
panic(fmt.Sprintf("got %v, want %v", rv.Type(), fr.t))
245246
}
246247
rd := &reader{data}
248+
if string(rd.bytes(4)) != magic {
249+
panic("not a frob-encoded message")
250+
}
247251
fr.decode(rd, rv)
248252
if len(rd.data) > 0 {
249253
panic("surplus bytes")

gopls/internal/lsp/frob/frob_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ func TestBasics(t *testing.T) {
1818
B [2]int
1919
C *Basics
2020
D map[string]int
21+
E []byte
22+
F []string
2123
}
2224
codec := frob.CodecFor[Basics]()
2325

@@ -29,6 +31,8 @@ func TestBasics(t *testing.T) {
2931
B: [...]int{3, 4},
3032
D: map[string]int{"one": 1},
3133
},
34+
E: []byte("hello"),
35+
F: []string{s1, s2},
3236
}
3337
var y Basics
3438
codec.Decode(codec.Encode(x), &y)

0 commit comments

Comments
 (0)