Skip to content

Commit 89a8e71

Browse files
committed
fix(bson): correct deserialization of primitive arrays using BinaryPrimitives for Big Endian support
Signed-off-by: Medha Tiwari <[email protected]>
1 parent d6840c3 commit 89a8e71

File tree

1 file changed

+16
-20
lines changed

1 file changed

+16
-20
lines changed

src/MongoDB.Bson/Serialization/Serializers/PrimitivesArrayReader.cs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Buffers.Binary;
23
using System.Collections.Generic;
34
using System.Runtime.CompilerServices;
45
using MongoDB.Bson.IO;
@@ -77,6 +78,7 @@ private static T[] ReadBsonArray<T>(
7778

7879
var result = new List<T>();
7980

81+
8082
var index = 4; // 4 first bytes are array object size in bytes
8183
var maxIndex = array.Length - 1;
8284

@@ -85,7 +87,7 @@ private static T[] ReadBsonArray<T>(
8587
ValidateBsonType(bsonDataType);
8688

8789
// Skip name
88-
while (bytes[index] != 0) { index++; };
90+
while (bytes[index] != 0) { index++; }
8991
index++; // Skip string terminating 0
9092

9193
T value = default;
@@ -95,85 +97,81 @@ private static T[] ReadBsonArray<T>(
9597
{
9698
case ConversionType.DoubleToSingle:
9799
{
98-
var v = (float)BitConverter.ToDouble(bytes, index);
99-
100+
var v = (float)BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(bytes.AsSpan(index)));
100101
value = Unsafe.As<float, T>(ref v);
101102
break;
102103
}
103104
case ConversionType.DoubleToDouble:
104105
{
105-
var v = BitConverter.ToDouble(bytes, index);
106+
var v = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(bytes.AsSpan(index)));
106107
value = Unsafe.As<double, T>(ref v);
107108
break;
108109
}
109110
case ConversionType.Decimal128ToDecimal128:
110111
{
111-
var lowBits = (ulong)BitConverter.ToInt64(bytes, index);
112-
var highBits = (ulong)BitConverter.ToInt64(bytes, index + 8);
112+
var lowBits = BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(index));
113+
var highBits = BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(index + 8));
113114
var v = Decimal128.ToDecimal(Decimal128.FromIEEEBits(highBits, lowBits));
114-
115115
value = Unsafe.As<decimal, T>(ref v);
116116
break;
117117
}
118118
case ConversionType.BoolToBool:
119119
{
120120
var v = bytes[index] != 0;
121-
122121
value = Unsafe.As<bool, T>(ref v);
123122
break;
124123
}
125124
case ConversionType.Int32ToInt8:
126125
{
127-
var v = (sbyte)BitConverter.ToInt32(bytes, index);
126+
var v = (sbyte)BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(index));
128127
value = Unsafe.As<sbyte, T>(ref v);
129-
130128
break;
131129
}
132130
case ConversionType.Int32ToUInt8:
133131
{
134-
var v = (byte)BitConverter.ToInt32(bytes, index);
132+
var v = (byte)BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(index));
135133
value = Unsafe.As<byte, T>(ref v);
136134
break;
137135
}
138136
case ConversionType.Int32ToInt16:
139137
{
140-
var v = (short)BitConverter.ToInt32(bytes, index);
138+
var v = (short)BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(index));
141139
value = Unsafe.As<short, T>(ref v);
142140
break;
143141
}
144142
case ConversionType.Int32ToUInt16:
145143
{
146-
var v = (ushort)BitConverter.ToInt32(bytes, index);
144+
var v = (ushort)BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(index));
147145
value = Unsafe.As<ushort, T>(ref v);
148146
break;
149147
}
150148
case ConversionType.Int32ToChar:
151149
{
152-
var v = BitConverter.ToChar(bytes, index);
150+
var v = (char)(ushort)BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(index));
153151
value = Unsafe.As<char, T>(ref v);
154152
break;
155153
}
156154
case ConversionType.Int32ToInt32:
157155
{
158-
var v = BitConverter.ToInt32(bytes, index);
156+
var v = BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(index));
159157
value = Unsafe.As<int, T>(ref v);
160158
break;
161159
}
162160
case ConversionType.Int32ToUInt32:
163161
{
164-
var v = BitConverter.ToUInt32(bytes, index);
162+
var v = BinaryPrimitives.ReadUInt32LittleEndian(bytes.AsSpan(index));
165163
value = Unsafe.As<uint, T>(ref v);
166164
break;
167165
}
168166
case ConversionType.Int64ToInt64:
169167
{
170-
var v = BitConverter.ToInt64(bytes, index);
168+
var v = BinaryPrimitives.ReadInt64LittleEndian(bytes.AsSpan(index));
171169
value = Unsafe.As<long, T>(ref v);
172170
break;
173171
}
174172
case ConversionType.Int64ToUInt64:
175173
{
176-
var v = BitConverter.ToUInt64(bytes, index);
174+
var v = BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(index));
177175
value = Unsafe.As<ulong, T>(ref v);
178176
break;
179177
}
@@ -182,12 +180,10 @@ private static T[] ReadBsonArray<T>(
182180
}
183181

184182
result.Add(value);
185-
186183
index += bsonDataSize;
187184
}
188185

189186
ValidateBsonType(BsonType.EndOfDocument);
190-
191187
return result.ToArray();
192188

193189
void ValidateBsonType(BsonType bsonType)

0 commit comments

Comments
 (0)