Skip to content

Commit 385bb3b

Browse files
committed
CSHARP-1501: Drivers must raise an error if response messageLength > ismaster.maxMessageSizeBytes
1 parent 7008c17 commit 385bb3b

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

src/MongoDB.Driver.Core/Core/Connections/BinaryConnection.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,16 @@ private void Dispose(bool disposing)
220220
}
221221
}
222222

223+
private void EnsureMessageSizeIsValid(int messageSize)
224+
{
225+
var maxMessageSize = _description?.MaxMessageSize ?? 48000000;
226+
227+
if (messageSize < 0 || messageSize > maxMessageSize)
228+
{
229+
throw new FormatException("The size of the message is invalid.");
230+
}
231+
}
232+
223233
public void Open(CancellationToken cancellationToken)
224234
{
225235
ThrowIfDisposed();
@@ -321,6 +331,7 @@ private IByteBuffer ReceiveBuffer()
321331
var messageSizeBytes = new byte[4];
322332
_stream.ReadBytes(messageSizeBytes, 0, 4, _backgroundTaskCancellationToken);
323333
var messageSize = BitConverter.ToInt32(messageSizeBytes, 0);
334+
EnsureMessageSizeIsValid(messageSize);
324335
var inputBufferChunkSource = new InputBufferChunkSource(BsonChunkPool.Default);
325336
var buffer = ByteBufferFactory.Create(inputBufferChunkSource, messageSize);
326337
buffer.Length = messageSize;
@@ -382,6 +393,7 @@ private async Task<IByteBuffer> ReceiveBufferAsync()
382393
var messageSizeBytes = new byte[4];
383394
await _stream.ReadBytesAsync(messageSizeBytes, 0, 4, _backgroundTaskCancellationToken).ConfigureAwait(false);
384395
var messageSize = BitConverter.ToInt32(messageSizeBytes, 0);
396+
EnsureMessageSizeIsValid(messageSize);
385397
var inputBufferChunkSource = new InputBufferChunkSource(BsonChunkPool.Default);
386398
var buffer = ByteBufferFactory.Create(inputBufferChunkSource, messageSize);
387399
buffer.Length = messageSize;

tests/MongoDB.Driver.Core.Tests/Core/Connections/BinaryConnectionTests.cs

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,18 @@ public BinaryConnectionTests()
5353

5454
_endPoint = new DnsEndPoint("localhost", 27017);
5555
var serverId = new ServerId(new ClusterId(), _endPoint);
56+
var connectionId = new ConnectionId(serverId);
57+
var isMasterResult = new IsMasterResult(new BsonDocument { { "ok", 1 }, { "maxMessageSizeBytes", 48000000 } });
58+
var buildInfoResult = new BuildInfoResult(new BsonDocument { { "ok", 1 }, { "version", "2.6.3" } });
59+
var connectionDescription = new ConnectionDescription(connectionId, isMasterResult, buildInfoResult);
5660

5761
_mockConnectionInitializer = new Mock<IConnectionInitializer>();
58-
_mockConnectionInitializer.Setup(i => i.InitializeConnection(It.IsAny<IConnection>(), CancellationToken.None))
59-
.Returns(() => new ConnectionDescription(
60-
new ConnectionId(serverId),
61-
new IsMasterResult(new BsonDocument()),
62-
new BuildInfoResult(new BsonDocument("version", "2.6.3"))));
63-
_mockConnectionInitializer.Setup(i => i.InitializeConnectionAsync(It.IsAny<IConnection>(), CancellationToken.None))
64-
.Returns(() => Task.FromResult(new ConnectionDescription(
65-
new ConnectionId(serverId),
66-
new IsMasterResult(new BsonDocument()),
67-
new BuildInfoResult(new BsonDocument("version", "2.6.3")))));
62+
_mockConnectionInitializer
63+
.Setup(i => i.InitializeConnection(It.IsAny<IConnection>(), CancellationToken.None))
64+
.Returns(connectionDescription);
65+
_mockConnectionInitializer
66+
.Setup(i => i.InitializeConnectionAsync(It.IsAny<IConnection>(), CancellationToken.None))
67+
.ReturnsAsync(connectionDescription);
6868

6969
_subject = new BinaryConnection(
7070
serverId: serverId,
@@ -212,6 +212,47 @@ public void Open_should_not_complete_the_second_call_until_the_first_is_complete
212212
_capturedEvents.Any().Should().BeFalse();
213213
}
214214

215+
[Theory]
216+
[ParameterAttributeData]
217+
public void ReceiveMessage_should_throw_a_FormatException_when_message_is_an_invalid_size(
218+
[Values(-1, 48000001)]
219+
int length,
220+
[Values(false, true)]
221+
bool async)
222+
{
223+
using (var stream = new BlockingMemoryStream())
224+
{
225+
var bytes = BitConverter.GetBytes(length);
226+
stream.Write(bytes, 0, bytes.Length);
227+
stream.Seek(0, SeekOrigin.Begin);
228+
var encoderSelector = new ReplyMessageEncoderSelector<BsonDocument>(BsonDocumentSerializer.Instance);
229+
230+
Exception exception;
231+
if (async)
232+
{
233+
_mockStreamFactory
234+
.Setup(f => f.CreateStreamAsync(_endPoint, CancellationToken.None))
235+
.ReturnsAsync(stream);
236+
_subject.OpenAsync(CancellationToken.None).GetAwaiter().GetResult();
237+
exception = Record
238+
.Exception(() => _subject.ReceiveMessageAsync(10, encoderSelector, _messageEncoderSettings, CancellationToken.None)
239+
.GetAwaiter()
240+
.GetResult());
241+
}
242+
else
243+
{
244+
_mockStreamFactory.Setup(f => f.CreateStream(_endPoint, CancellationToken.None))
245+
.Returns(stream);
246+
_subject.Open(CancellationToken.None);
247+
exception = Record.Exception( () => _subject.ReceiveMessage(10, encoderSelector, _messageEncoderSettings, CancellationToken.None));
248+
}
249+
250+
exception.Should().BeOfType<MongoConnectionException>();
251+
var e = exception.InnerException.Should().BeOfType<FormatException>().Subject;
252+
e.Message.Should().Be("The size of the message is invalid.");
253+
}
254+
}
255+
215256
[Theory]
216257
[ParameterAttributeData]
217258
public void ReceiveMessage_should_throw_an_ArgumentNullException_when_the_encoderSelector_is_null(

0 commit comments

Comments
 (0)