Skip to content

Commit 6e0c262

Browse files
Fix out-of-bounds panics in buffered frame metadata parsing
Add bounds checks in trySeekMetadataLen, trySliceMetadata, and trySliceData so malformed frames with a bogus metadata length return nil instead of panicking on the slice expression.
1 parent 2a2c1cf commit 6e0c262

1 file changed

Lines changed: 26 additions & 6 deletions

File tree

core/framing/buffered.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
uberatomic "go.uber.org/atomic"
1313
)
1414

15+
const metadataLengthFieldSize = 3 // Size of u24 metadata length field in bytes
16+
1517
// bufferedFrame is basic frame implementation.
1618
type bufferedFrame struct {
1719
innerPtr unsafe.Pointer
@@ -115,14 +117,16 @@ func (f *bufferedFrame) WriteTo(w io.Writer) (n int64, err error) {
115117

116118
func (f *bufferedFrame) trySeekMetadataLen(offset int) (n int, hasMetadata bool) {
117119
raw := f.Body()
118-
if offset > 0 {
119-
raw = raw[offset:]
120+
// Validate offset before accessing frame to avoid panic on released frames
121+
if offset < 0 || offset >= len(raw) {
122+
return -1, false
120123
}
124+
raw = raw[offset:]
121125
hasMetadata = f.HasFlag(core.FlagMetadata)
122126
if !hasMetadata {
123127
return
124128
}
125-
if len(raw) < 3 {
129+
if len(raw) < metadataLengthFieldSize {
126130
n = -1
127131
} else {
128132
n = u24.NewUint24Bytes(raw).AsInt()
@@ -135,18 +139,34 @@ func (f *bufferedFrame) trySliceMetadata(offset int) ([]byte, bool) {
135139
if !ok || n < 0 {
136140
return nil, false
137141
}
138-
return f.Body()[offset+3 : offset+3+n], true
142+
body := f.Body()
143+
// Overflow-safe bounds check
144+
metadataOffset := offset + metadataLengthFieldSize
145+
if n > len(body)-metadataOffset {
146+
return nil, false
147+
}
148+
return body[metadataOffset : metadataOffset+n], true
139149
}
140150

141151
func (f *bufferedFrame) trySliceData(offset int) []byte {
152+
body := f.Body()
142153
n, ok := f.trySeekMetadataLen(offset)
143154
if !ok {
144-
return f.Body()[offset:]
155+
if offset < 0 || offset > len(body) {
156+
return nil
157+
}
158+
return body[offset:]
145159
}
146160
if n < 0 {
147161
return nil
148162
}
149-
return f.Body()[offset+n+3:]
163+
// Overflow-safe bounds check
164+
metadataOffset := offset + metadataLengthFieldSize
165+
if n > len(body)-metadataOffset {
166+
return nil
167+
}
168+
dataOffset := metadataOffset + n
169+
return body[dataOffset:]
150170
}
151171

152172
func (f *bufferedFrame) bodyLen() int {

0 commit comments

Comments
 (0)