Skip to content

Commit 225ac8b

Browse files
authored
CSHARP-4853: "Thread static buffer is already in use." error after bad utf8 string write. (#1219)
1 parent dd1f1bf commit 225ac8b

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

src/MongoDB.Bson/IO/EncodingHelper.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,17 @@ public static DisposableSegment GetBytesUsingThreadStaticBuffer(this Encoding en
6363
var maxSize = encoding.GetMaxByteCount(length);
6464
var rentedBuffer = ThreadStaticBuffer.RentBuffer(maxSize);
6565

66-
var size = encoding.GetBytes(value, 0, length, rentedBuffer.Bytes, 0);
67-
var segment = new ArraySegment<byte>(rentedBuffer.Bytes, 0, size);
68-
69-
return new DisposableSegment(rentedBuffer, segment);
66+
try
67+
{
68+
var size = encoding.GetBytes(value, 0, length, rentedBuffer.Bytes, 0);
69+
var segment = new ArraySegment<byte>(rentedBuffer.Bytes, 0, size);
70+
return new DisposableSegment(rentedBuffer, segment);
71+
}
72+
catch
73+
{
74+
rentedBuffer.Dispose();
75+
throw;
76+
}
7077
}
7178
}
7279
}

tests/MongoDB.Bson.Tests/IO/EncodingHelperTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ public void GetBytesUsingThreadStaticBuffer_should_throw_when_encoding_is_null()
3333

3434
var e = exception.Should().BeOfType<ArgumentNullException>().Subject;
3535
e.ParamName.Should().Be("encoding");
36+
37+
AssertGetBytesUsingThreadStaticBufferWorks();
38+
}
39+
40+
[Fact]
41+
public void GetBytesUsingThreadStaticBuffer_should_throw_when_string_is_invalid()
42+
{
43+
const string invalidUtf8String = "\uD801";
44+
45+
var exception = Record.Exception(() => EncodingHelper.GetBytesUsingThreadStaticBuffer(Utf8Encodings.Strict, invalidUtf8String));
46+
exception.Should().BeOfType<EncoderFallbackException>();
47+
48+
AssertGetBytesUsingThreadStaticBufferWorks();
3649
}
3750

3851
[Fact]
@@ -42,6 +55,8 @@ public void GetBytesUsingThreadStaticBuffer_should_throw_when_value_is_null()
4255

4356
var e = exception.Should().BeOfType<ArgumentNullException>().Subject;
4457
e.ParamName.Should().Be("value");
58+
59+
AssertGetBytesUsingThreadStaticBufferWorks();
4560
}
4661

4762
[Fact]
@@ -111,6 +126,12 @@ public void GetBytesUsingThreadStaticBuffer_should_return_expected_result_when_m
111126
}
112127

113128
// private methods
129+
private void AssertGetBytesUsingThreadStaticBufferWorks()
130+
{
131+
using var segment = EncodingHelper.GetBytesUsingThreadStaticBuffer(Utf8Encodings.Strict, "Apples");
132+
segment.Segment.Array.Length.Should().BeGreaterThan(0);
133+
}
134+
114135
private string GetString(int length) =>
115136
new string(Enumerable.Range(0, length).Select(i => (char)('a' + i % 26)).ToArray());
116137
}

0 commit comments

Comments
 (0)