Skip to content

Commit ab3e871

Browse files
committed
big endian fix
1 parent 111033e commit ab3e871

File tree

7 files changed

+164
-10
lines changed

7 files changed

+164
-10
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNICommon.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Buffers.Binary;
67
using System.Diagnostics;
78
using System.Net;
89
using System.Net.Security;
@@ -59,10 +60,17 @@ public void Read(byte[] bytes)
5960
{
6061
SMID = bytes[0];
6162
flags = bytes[1];
63+
#if NETCOREAPP
64+
sessionId = BinaryPrimitives.ReadUInt16LittleEndian(new ReadOnlySpan<byte>(bytes, 2, 2));
65+
length = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 4, 4)) - SNISMUXHeader.HEADER_LENGTH;
66+
sequenceNumber = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 8, 4));
67+
highwater = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 12, 4));
68+
#else
6269
sessionId = BitConverter.ToUInt16(bytes, 2);
6370
length = BitConverter.ToUInt32(bytes, 4) - SNISMUXHeader.HEADER_LENGTH;
6471
sequenceNumber = BitConverter.ToUInt32(bytes, 8);
6572
highwater = BitConverter.ToUInt32(bytes, 12);
73+
#endif
6674
}
6775

6876
public void Write(Span<byte> bytes)

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.NetCoreApp.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,27 @@
44

55
using System;
66
using System.Diagnostics;
7+
using System.Buffers.Binary;
78

89
namespace Microsoft.Data.SqlClient
910
{
1011
internal sealed partial class TdsParser
1112
{
1213
internal static void FillGuidBytes(Guid guid, Span<byte> buffer) => guid.TryWriteBytes(buffer);
1314

14-
internal static void FillDoubleBytes(double value, Span<byte> buffer) => BitConverter.TryWriteBytes(buffer, value);
15+
internal static void FillDoubleBytes(double value, Span<byte> buffer) =>
16+
#if NETCOREAPP
17+
BinaryPrimitives.WriteDoubleLittleEndian(buffer, value);
18+
#else
19+
BitConverter.TryWriteBytes(buffer, value);
20+
#endif
1521

16-
internal static void FillFloatBytes(float v, Span<byte> buffer) => BitConverter.TryWriteBytes(buffer, v);
22+
internal static void FillFloatBytes(float v, Span<byte> buffer) =>
23+
#if NETCOREAPP
24+
BinaryPrimitives.WriteSingleLittleEndian(buffer, v);
25+
#else
26+
BitConverter.TryWriteBytes(buffer, v);
27+
#endif
1728

1829
internal static Guid ConstructGuid(ReadOnlySpan<byte> bytes)
1930
{

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Buffers;
7+
using System.Buffers.Binary;
78
using System.Collections.Generic;
89
using System.Data;
910
using System.Data.SqlTypes;
@@ -1743,14 +1744,10 @@ internal void WriteInt(int v, TdsParserStateObject stateObj)
17431744

17441745
internal static void WriteInt(Span<byte> buffer, int value)
17451746
{
1746-
#if NETCOREAPP
1747-
BitConverter.TryWriteBytes(buffer, value);
1748-
#else
17491747
buffer[0] = (byte)(value & 0xff);
17501748
buffer[1] = (byte)((value >> 8) & 0xff);
17511749
buffer[2] = (byte)((value >> 16) & 0xff);
17521750
buffer[3] = (byte)((value >> 24) & 0xff);
1753-
#endif
17541751
}
17551752

17561753
//
@@ -1763,7 +1760,13 @@ internal byte[] SerializeFloat(float v)
17631760
throw ADP.ParameterValueOutOfRange(v.ToString());
17641761
}
17651762

1763+
#if NETCOREAPP
1764+
var bytes = new byte[4];
1765+
BinaryPrimitives.WriteInt32LittleEndian(bytes, BitConverter.SingleToInt32Bits(v));
1766+
return bytes;
1767+
#else
17661768
return BitConverter.GetBytes(v);
1769+
#endif
17671770
}
17681771

17691772
internal void WriteFloat(float v, TdsParserStateObject stateObj)
@@ -1886,7 +1889,13 @@ internal byte[] SerializeDouble(double v)
18861889
throw ADP.ParameterValueOutOfRange(v.ToString());
18871890
}
18881891

1892+
#if NETCOREAPP
1893+
byte[] bytes = new byte[8];
1894+
BinaryPrimitives.WriteInt64LittleEndian(bytes, BitConverter.DoubleToInt64Bits(v));
1895+
return bytes;
1896+
#else
18891897
return BitConverter.GetBytes(v);
1898+
#endif
18901899
}
18911900

18921901
internal void WriteDouble(double v, TdsParserStateObject stateObj)
@@ -3808,8 +3817,13 @@ private bool TryProcessFedAuthInfo(TdsParserStateObject stateObj, int tokenLen,
38083817
uint currentOptionOffset = checked(i * optionSize);
38093818

38103819
byte id = tokenData[currentOptionOffset];
3820+
#if NETCOREAPP
3821+
uint dataLen = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(tokenData, checked((int)(currentOptionOffset + 1)), 4));
3822+
uint dataOffset = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(tokenData, checked((int)(currentOptionOffset + 5)), 4));
3823+
#else
38113824
uint dataLen = BitConverter.ToUInt32(tokenData, checked((int)(currentOptionOffset + 1)));
38123825
uint dataOffset = BitConverter.ToUInt32(tokenData, checked((int)(currentOptionOffset + 5)));
3826+
#endif
38133827
if (SqlClientEventSource.Log.IsAdvancedTraceOn())
38143828
{
38153829
SqlClientEventSource.Log.AdvancedTraceEvent("<sc.TdsParser.TryProcessFedAuthInfo> FedAuthInfoOpt: ID={0}, DataLen={1}, Offset={2}", id, dataLen.ToString(CultureInfo.InvariantCulture), dataOffset.ToString(CultureInfo.InvariantCulture));
@@ -5771,7 +5785,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
57715785
return false;
57725786
}
57735787

5788+
#if NETCOREAPP
5789+
longValue = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 8));
5790+
#else
57745791
longValue = BitConverter.ToInt64(unencryptedBytes, 0);
5792+
#endif
57755793

57765794
if (tdsType == TdsEnums.SQLBIT ||
57775795
tdsType == TdsEnums.SQLBITN)
@@ -5809,7 +5827,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58095827
return false;
58105828
}
58115829

5830+
#if NETCOREAPP
5831+
singleValue = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(unencryptedBytes));
5832+
#else
58125833
singleValue = BitConverter.ToSingle(unencryptedBytes, 0);
5834+
#endif
58135835
value.Single = singleValue;
58145836
break;
58155837

@@ -5820,7 +5842,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58205842
return false;
58215843
}
58225844

5845+
#if NETCOREAPP
5846+
doubleValue = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(unencryptedBytes));
5847+
#else
58235848
doubleValue = BitConverter.ToDouble(unencryptedBytes, 0);
5849+
#endif
58245850
value.Double = doubleValue;
58255851
break;
58265852

@@ -5837,8 +5863,13 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58375863
return false;
58385864
}
58395865

5866+
#if NETCOREAPP
5867+
mid = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 4));
5868+
lo = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 4, 4));
5869+
#else
58405870
mid = BitConverter.ToInt32(unencryptedBytes, 0);
58415871
lo = BitConverter.ToUInt32(unencryptedBytes, 4);
5872+
#endif
58425873

58435874
long l = (((long)mid) << 0x20) + ((long)lo);
58445875
value.SetToMoney(l);
@@ -5875,8 +5906,13 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58755906
return false;
58765907
}
58775908

5909+
#if NETCOREAPP
5910+
daypart = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 4));
5911+
timepart = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 4, 4));
5912+
#else
58785913
daypart = BitConverter.ToInt32(unencryptedBytes, 0);
58795914
timepart = BitConverter.ToUInt32(unencryptedBytes, 4);
5915+
#endif
58805916
value.SetToDateTime(daypart, (int)timepart);
58815917
break;
58825918

@@ -5922,7 +5958,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
59225958
for (int i = 0; i < decLength; i++)
59235959
{
59245960
// up to 16 bytes of data following the sign byte
5961+
#if NETCOREAPP
5962+
bits[i] = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, index, 4));
5963+
#else
59255964
bits[i] = BitConverter.ToInt32(unencryptedBytes, index);
5965+
#endif
59265966
index += 4;
59275967
}
59285968
value.SetToDecimal(md.baseTI.precision, md.baseTI.scale, fPositive, bits);
@@ -7490,7 +7530,20 @@ internal Task WriteString(string s, int length, int offset, TdsParserStateObject
74907530

74917531
private static void CopyCharsToBytes(char[] source, int sourceOffset, byte[] dest, int destOffset, int charLength)
74927532
{
7493-
Buffer.BlockCopy(source, sourceOffset, dest, destOffset, charLength * ADP.CharSize);
7533+
if (!BitConverter.IsLittleEndian)
7534+
{
7535+
int desti = 0;
7536+
for(int srci = 0; srci < charLength; srci++)
7537+
{
7538+
dest[desti + destOffset] = (byte)(source[srci + sourceOffset]);
7539+
dest[desti + destOffset+1] = (byte)(source[srci + sourceOffset] >> 8);
7540+
desti += 2;
7541+
}
7542+
}
7543+
else
7544+
{
7545+
Buffer.BlockCopy(source, sourceOffset, dest, destOffset, charLength * ADP.CharSize);
7546+
}
74947547
}
74957548

74967549
private static void CopyStringToBytes(string source, int sourceOffset, byte[] dest, int destOffset, int charLength)
@@ -12571,7 +12624,6 @@ private bool TryReadPlpUnicodeCharsChunk(char[] buff, int offst, int len, TdsPar
1257112624
{
1257212625
charsToRead = (int)(stateObj._longlenleft >> 1);
1257312626
}
12574-
1257512627
if (!stateObj.TryReadChars(buff, offst, charsToRead, out charsRead))
1257612628
{
1257712629
charsRead = 0;

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Diagnostics;
7+
using System.Buffers.Binary;
78
using System.Runtime.InteropServices;
89
using System.Security;
910
using System.Threading;
@@ -527,7 +528,11 @@ internal bool TryReadInt64(out long value)
527528
Debug.Assert(_bTmpRead + bytesRead == 8, "TryReadByteArray returned true without reading all data required");
528529
_bTmpRead = 0;
529530
AssertValidState();
531+
#if NETCOREAPP
532+
value = BinaryPrimitives.ReadInt64LittleEndian(_bTmp);
533+
#else
530534
value = BitConverter.ToInt64(_bTmp, 0);
535+
#endif
531536
return true;
532537
}
533538
}
@@ -536,8 +541,12 @@ internal bool TryReadInt64(out long value)
536541
// The entire long is in the packet and in the buffer, so just return it
537542
// and take care of the counters.
538543

544+
#if NETCOREAPP
545+
value = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 8));
546+
#else
539547
value = BitConverter.ToInt64(_inBuff, _inBytesUsed);
540548

549+
#endif
541550
_inBytesUsed += 8;
542551
_inBytesPacket -= 8;
543552

@@ -605,7 +614,11 @@ internal bool TryReadUInt32(out uint value)
605614
Debug.Assert(_bTmpRead + bytesRead == 4, "TryReadByteArray returned true without reading all data required");
606615
_bTmpRead = 0;
607616
AssertValidState();
617+
#if NETCOREAPP
618+
value = BinaryPrimitives.ReadUInt32LittleEndian(_bTmp);
619+
#else
608620
value = BitConverter.ToUInt32(_bTmp, 0);
621+
#endif
609622
return true;
610623
}
611624
}
@@ -614,7 +627,11 @@ internal bool TryReadUInt32(out uint value)
614627
// The entire int is in the packet and in the buffer, so just return it
615628
// and take care of the counters.
616629

630+
#if NETCOREAPP
631+
value = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 4));
632+
#else
617633
value = BitConverter.ToUInt32(_inBuff, _inBytesUsed);
634+
#endif
618635

619636
_inBytesUsed += 4;
620637
_inBytesPacket -= 4;
@@ -639,16 +656,24 @@ internal bool TryReadSingle(out float value)
639656
}
640657

641658
AssertValidState();
659+
#if NETCOREAPP
660+
value = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(_bTmp));
661+
#else
642662
value = BitConverter.ToSingle(_bTmp, 0);
663+
#endif
643664
return true;
644665
}
645666
else
646667
{
647668
// The entire float is in the packet and in the buffer, so just return it
648669
// and take care of the counters.
649670

671+
#if NETCOREAPP
672+
value = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 4)));
673+
#else
650674
value = BitConverter.ToSingle(_inBuff, _inBytesUsed);
651675

676+
#endif
652677
_inBytesUsed += 4;
653678
_inBytesPacket -= 4;
654679

@@ -672,16 +697,24 @@ internal bool TryReadDouble(out double value)
672697
}
673698

674699
AssertValidState();
700+
#if NETCOREAPP
701+
value = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(_bTmp));
702+
#else
675703
value = BitConverter.ToDouble(_bTmp, 0);
704+
#endif
676705
return true;
677706
}
678707
else
679708
{
680709
// The entire double is in the packet and in the buffer, so just return it
681710
// and take care of the counters.
682711

712+
#if NETCOREAPP
713+
value = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 8)));
714+
#else
683715
value = BitConverter.ToDouble(_inBuff, _inBytesUsed);
684716

717+
#endif
685718
_inBytesUsed += 8;
686719
_inBytesPacket -= 8;
687720

@@ -1793,6 +1826,16 @@ private void SetBufferSecureStrings()
17931826
str = Marshal.SecureStringToBSTR(_securePasswords[i]);
17941827
byte[] data = new byte[_securePasswords[i].Length * 2];
17951828
Marshal.Copy(str, data, 0, _securePasswords[i].Length * 2);
1829+
if (!BitConverter.IsLittleEndian)
1830+
{
1831+
byte temp;
1832+
for (int ii = 0; ii < _securePasswords[i].Length * 2; ii += 2)
1833+
{
1834+
temp = (byte)data[ii];
1835+
data[ii] = (byte)data[ii + 1];
1836+
data[ii + 1] = (byte)temp;
1837+
}
1838+
}
17961839
TdsParserStaticMethods.ObfuscatePassword(data);
17971840
data.CopyTo(_outBuff, _securePasswordOffsetsInBuffer[i]);
17981841
}
@@ -2059,7 +2102,6 @@ internal void WriteSecureString(SecureString secureString)
20592102
Debug.Assert(_securePasswords[0] == null || _securePasswords[1] == null, "There are more than two secure passwords");
20602103

20612104
int index = _securePasswords[0] != null ? 1 : 0;
2062-
20632105
_securePasswords[index] = secureString;
20642106
_securePasswordOffsetsInBuffer[index] = _outBytesUsed;
20652107

@@ -2294,7 +2336,12 @@ internal Task WritePacket(byte flushMode, bool canAccumulate = false)
22942336
// So we need to avoid this check prior to login completing
22952337
state == TdsParserState.OpenLoggedIn
22962338
&& !_bulkCopyOpperationInProgress // ignore the condition checking for bulk copy
2297-
&& _outBytesUsed == (_outputHeaderLen + BitConverter.ToInt32(_outBuff, _outputHeaderLen))
2339+
&& _outBytesUsed == (_outputHeaderLen +
2340+
#if NETCOREAPP
2341+
BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(_outBuff, _outputHeaderLen, 4)))
2342+
#else
2343+
BitConverter.ToInt32(_outBuff, _outputHeaderLen))
2344+
#endif
22982345
&& _outputPacketCount == 0
22992346
|| _outBytesUsed == _outputHeaderLen
23002347
&& _outputPacketCount == 0)

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSequentialTextReader.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,10 @@ public override void Convert(byte[] bytes, int byteIndex, int byteCount, char[]
514514
completed = (bytesUsed == byteCount);
515515

516516
// BlockCopy uses offsets\length measured in bytes, not the actual array index
517+
if (!BitConverter.IsLittleEndian)
518+
{
519+
bytes = Encoding.Unicode.GetBytes(Encoding.BigEndianUnicode.GetString(bytes));
520+
}
517521
Buffer.BlockCopy(bytes, byteIndex, chars, charIndex * 2, bytesUsed);
518522
}
519523
}

0 commit comments

Comments
 (0)