Skip to content

Commit adbaaed

Browse files
authored
GODRIVER-150 Raise error for read message length too large (#545)
1 parent 7841aba commit adbaaed

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

x/mongo/driver/topology/connection.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ import (
3030

3131
var globalConnectionID uint64 = 1
3232

33+
var (
34+
defaultMaxMessageSize uint32 = 48000000
35+
errResponseTooLarge error = errors.New("length of read message too large")
36+
)
37+
3338
func nextConnectionID() uint64 { return atomic.AddUint64(&globalConnectionID, 1) }
3439

3540
type connection struct {
@@ -406,6 +411,16 @@ func (c *connection) read(ctx context.Context, dst []byte) (bytesRead []byte, er
406411
// read the length as an int32
407412
size := (int32(sizeBuf[0])) | (int32(sizeBuf[1]) << 8) | (int32(sizeBuf[2]) << 16) | (int32(sizeBuf[3]) << 24)
408413

414+
// In the case of an isMaster response where MaxMessageSize has not yet been set, use the hard-coded
415+
// defaultMaxMessageSize instead.
416+
maxMessageSize := c.desc.MaxMessageSize
417+
if maxMessageSize == 0 {
418+
maxMessageSize = defaultMaxMessageSize
419+
}
420+
if uint32(size) > maxMessageSize {
421+
return nil, errResponseTooLarge.Error(), errResponseTooLarge
422+
}
423+
409424
if int(size) > cap(dst) {
410425
// Since we can't grow this slice without allocating, just allocate an entirely new slice.
411426
dst = make([]byte, 0, size)

x/mongo/driver/topology/connection_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,41 @@ func TestConnection(t *testing.T) {
485485
}
486486
listener.assertMethodsCalled(t, 1, 1)
487487
})
488+
t.Run("message too large errors", func(t *testing.T) {
489+
testCases := []struct {
490+
name string
491+
buffer []byte
492+
desc description.Server
493+
}{
494+
{
495+
"message too large errors with small max message size",
496+
[]byte{0x0A, 0x00, 0x00, 0x00}, // defines a message size of 10 in hex with the first four bytes.
497+
description.Server{MaxMessageSize: 9},
498+
},
499+
{
500+
"message too large errors with default max message size",
501+
[]byte{0x01, 0x6C, 0xDC, 0x02}, // defines a message size of 48000001 in hex with the first four bytes.
502+
description.Server{},
503+
},
504+
}
505+
for _, tc := range testCases {
506+
t.Run(tc.name, func(t *testing.T) {
507+
err := errors.New("length of read message too large")
508+
tnc := &testNetConn{buf: make([]byte, len(tc.buffer))}
509+
copy(tnc.buf, tc.buffer)
510+
conn := &connection{id: "foobar", nc: tnc, connected: connected, desc: tc.desc}
511+
listener := newTestCancellationListener(false)
512+
conn.cancellationListener = listener
513+
514+
want := ConnectionError{ConnectionID: "foobar", Wrapped: err, message: err.Error()}
515+
_, got := conn.readWireMessage(context.Background(), nil)
516+
if !cmp.Equal(got, want, cmp.Comparer(compareErrors)) {
517+
t.Errorf("errors do not match. got %v; want %v", got, want)
518+
}
519+
listener.assertMethodsCalled(t, 1, 1)
520+
})
521+
}
522+
})
488523
t.Run("success", func(t *testing.T) {
489524
want := []byte{0x0A, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}
490525
tnc := &testNetConn{buf: make([]byte, len(want))}

0 commit comments

Comments
 (0)