Skip to content

Commit db4fb62

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

File tree

7 files changed

+178
-10
lines changed

7 files changed

+178
-10
lines changed

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

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

55
using System;
6+
#if NETCOREAPP
7+
using System.Buffers.Binary;
8+
#endif
69
using System.Diagnostics;
710
using System.Net;
811
using System.Net.Security;
@@ -59,10 +62,17 @@ public void Read(byte[] bytes)
5962
{
6063
SMID = bytes[0];
6164
flags = bytes[1];
65+
#if NETCOREAPP
66+
sessionId = BinaryPrimitives.ReadUInt16LittleEndian(new ReadOnlySpan<byte>(bytes, 2, 2));
67+
length = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 4, 4)) - SNISMUXHeader.HEADER_LENGTH;
68+
sequenceNumber = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 8, 4));
69+
highwater = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 12, 4));
70+
#else
6271
sessionId = BitConverter.ToUInt16(bytes, 2);
6372
length = BitConverter.ToUInt32(bytes, 4) - SNISMUXHeader.HEADER_LENGTH;
6473
sequenceNumber = BitConverter.ToUInt32(bytes, 8);
6574
highwater = BitConverter.ToUInt32(bytes, 12);
75+
#endif
6676
}
6777

6878
public void Write(Span<byte> bytes)

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

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

55
using System;
66
using System.Diagnostics;
7+
#if NETCOREAPP
8+
using System.Buffers.Binary;
9+
#endif
710

811
namespace Microsoft.Data.SqlClient
912
{
1013
internal sealed partial class TdsParser
1114
{
1215
internal static void FillGuidBytes(Guid guid, Span<byte> buffer) => guid.TryWriteBytes(buffer);
1316

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

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

1831
internal static Guid ConstructGuid(ReadOnlySpan<byte> bytes)
1932
{

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

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

55
using System;
66
using System.Buffers;
7+
#if NETCOREAPP
8+
using System.Buffers.Binary;
9+
#endif
710
using System.Collections.Generic;
811
using System.Data;
912
using System.Data.SqlTypes;
@@ -1743,14 +1746,10 @@ internal void WriteInt(int v, TdsParserStateObject stateObj)
17431746

17441747
internal static void WriteInt(Span<byte> buffer, int value)
17451748
{
1746-
#if NETCOREAPP
1747-
BitConverter.TryWriteBytes(buffer, value);
1748-
#else
17491749
buffer[0] = (byte)(value & 0xff);
17501750
buffer[1] = (byte)((value >> 8) & 0xff);
17511751
buffer[2] = (byte)((value >> 16) & 0xff);
17521752
buffer[3] = (byte)((value >> 24) & 0xff);
1753-
#endif
17541753
}
17551754

17561755
//
@@ -1763,7 +1762,13 @@ internal byte[] SerializeFloat(float v)
17631762
throw ADP.ParameterValueOutOfRange(v.ToString());
17641763
}
17651764

1765+
#if NETCOREAPP
1766+
Span<byte> bytes = stackalloc byte[4];
1767+
BinaryPrimitives.WriteInt32LittleEndian(bytes, BitConverter.SingleToInt32Bits(v));
1768+
return bytes;
1769+
#else
17661770
return BitConverter.GetBytes(v);
1771+
#endif
17671772
}
17681773

17691774
internal void WriteFloat(float v, TdsParserStateObject stateObj)
@@ -1886,7 +1891,13 @@ internal byte[] SerializeDouble(double v)
18861891
throw ADP.ParameterValueOutOfRange(v.ToString());
18871892
}
18881893

1894+
#if NETCOREAPP
1895+
Span<byte> bytes = stackalloc byte[8];
1896+
BinaryPrimitives.WriteInt64LittleEndian(bytes, BitConverter.DoubleToInt64Bits(v));
1897+
return bytes;
1898+
#else
18891899
return BitConverter.GetBytes(v);
1900+
#endif
18901901
}
18911902

18921903
internal void WriteDouble(double v, TdsParserStateObject stateObj)
@@ -3808,8 +3819,13 @@ private bool TryProcessFedAuthInfo(TdsParserStateObject stateObj, int tokenLen,
38083819
uint currentOptionOffset = checked(i * optionSize);
38093820

38103821
byte id = tokenData[currentOptionOffset];
3822+
#if NETCOREAPP
3823+
uint dataLen = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(tokenData, checked((int)(currentOptionOffset + 1)), 4));
3824+
uint dataOffset = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(tokenData, checked((int)(currentOptionOffset + 5)), 4));
3825+
#else
38113826
uint dataLen = BitConverter.ToUInt32(tokenData, checked((int)(currentOptionOffset + 1)));
38123827
uint dataOffset = BitConverter.ToUInt32(tokenData, checked((int)(currentOptionOffset + 5)));
3828+
#endif
38133829
if (SqlClientEventSource.Log.IsAdvancedTraceOn())
38143830
{
38153831
SqlClientEventSource.Log.AdvancedTraceEvent("<sc.TdsParser.TryProcessFedAuthInfo> FedAuthInfoOpt: ID={0}, DataLen={1}, Offset={2}", id, dataLen.ToString(CultureInfo.InvariantCulture), dataOffset.ToString(CultureInfo.InvariantCulture));
@@ -5771,7 +5787,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
57715787
return false;
57725788
}
57735789

5790+
#if NETCOREAPP
5791+
longValue = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 8));
5792+
#else
57745793
longValue = BitConverter.ToInt64(unencryptedBytes, 0);
5794+
#endif
57755795

57765796
if (tdsType == TdsEnums.SQLBIT ||
57775797
tdsType == TdsEnums.SQLBITN)
@@ -5809,7 +5829,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58095829
return false;
58105830
}
58115831

5832+
#if NETCOREAPP
5833+
singleValue = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(unencryptedBytes));
5834+
#else
58125835
singleValue = BitConverter.ToSingle(unencryptedBytes, 0);
5836+
#endif
58135837
value.Single = singleValue;
58145838
break;
58155839

@@ -5820,7 +5844,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58205844
return false;
58215845
}
58225846

5847+
#if NETCOREAPP
5848+
doubleValue = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(unencryptedBytes));
5849+
#else
58235850
doubleValue = BitConverter.ToDouble(unencryptedBytes, 0);
5851+
#endif
58245852
value.Double = doubleValue;
58255853
break;
58265854

@@ -5837,8 +5865,13 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58375865
return false;
58385866
}
58395867

5868+
#if NETCOREAPP
5869+
mid = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 4));
5870+
lo = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 4, 4));
5871+
#else
58405872
mid = BitConverter.ToInt32(unencryptedBytes, 0);
58415873
lo = BitConverter.ToUInt32(unencryptedBytes, 4);
5874+
#endif
58425875

58435876
long l = (((long)mid) << 0x20) + ((long)lo);
58445877
value.SetToMoney(l);
@@ -5875,8 +5908,13 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
58755908
return false;
58765909
}
58775910

5911+
#if NETCOREAPP
5912+
daypart = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 4));
5913+
timepart = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 4, 4));
5914+
#else
58785915
daypart = BitConverter.ToInt32(unencryptedBytes, 0);
58795916
timepart = BitConverter.ToUInt32(unencryptedBytes, 4);
5917+
#endif
58805918
value.SetToDateTime(daypart, (int)timepart);
58815919
break;
58825920

@@ -5922,7 +5960,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
59225960
for (int i = 0; i < decLength; i++)
59235961
{
59245962
// up to 16 bytes of data following the sign byte
5963+
#if NETCOREAPP
5964+
bits[i] = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, index, 4));
5965+
#else
59255966
bits[i] = BitConverter.ToInt32(unencryptedBytes, index);
5967+
#endif
59265968
index += 4;
59275969
}
59285970
value.SetToDecimal(md.baseTI.precision, md.baseTI.scale, fPositive, bits);
@@ -7490,7 +7532,20 @@ internal Task WriteString(string s, int length, int offset, TdsParserStateObject
74907532

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

74967551
private static void CopyStringToBytes(string source, int sourceOffset, byte[] dest, int destOffset, int charLength)
@@ -12571,7 +12626,6 @@ private bool TryReadPlpUnicodeCharsChunk(char[] buff, int offst, int len, TdsPar
1257112626
{
1257212627
charsToRead = (int)(stateObj._longlenleft >> 1);
1257312628
}
12574-
1257512629
if (!stateObj.TryReadChars(buff, offst, charsToRead, out charsRead))
1257612630
{
1257712631
charsRead = 0;

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

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

55
using System;
66
using System.Diagnostics;
7+
#if NETCOREAPP
8+
using System.Buffers.Binary;
9+
#endif
710
using System.Runtime.InteropServices;
811
using System.Security;
912
using System.Threading;
@@ -527,7 +530,11 @@ internal bool TryReadInt64(out long value)
527530
Debug.Assert(_bTmpRead + bytesRead == 8, "TryReadByteArray returned true without reading all data required");
528531
_bTmpRead = 0;
529532
AssertValidState();
533+
#if NETCOREAPP
534+
value = BinaryPrimitives.ReadInt64LittleEndian(_bTmp);
535+
#else
530536
value = BitConverter.ToInt64(_bTmp, 0);
537+
#endif
531538
return true;
532539
}
533540
}
@@ -536,8 +543,12 @@ internal bool TryReadInt64(out long value)
536543
// The entire long is in the packet and in the buffer, so just return it
537544
// and take care of the counters.
538545

546+
#if NETCOREAPP
547+
value = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 8));
548+
#else
539549
value = BitConverter.ToInt64(_inBuff, _inBytesUsed);
540550

551+
#endif
541552
_inBytesUsed += 8;
542553
_inBytesPacket -= 8;
543554

@@ -605,7 +616,11 @@ internal bool TryReadUInt32(out uint value)
605616
Debug.Assert(_bTmpRead + bytesRead == 4, "TryReadByteArray returned true without reading all data required");
606617
_bTmpRead = 0;
607618
AssertValidState();
619+
#if NETCOREAPP
620+
value = BinaryPrimitives.ReadUInt32LittleEndian(_bTmp);
621+
#else
608622
value = BitConverter.ToUInt32(_bTmp, 0);
623+
#endif
609624
return true;
610625
}
611626
}
@@ -614,7 +629,11 @@ internal bool TryReadUInt32(out uint value)
614629
// The entire int is in the packet and in the buffer, so just return it
615630
// and take care of the counters.
616631

632+
#if NETCOREAPP
633+
value = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 4));
634+
#else
617635
value = BitConverter.ToUInt32(_inBuff, _inBytesUsed);
636+
#endif
618637

619638
_inBytesUsed += 4;
620639
_inBytesPacket -= 4;
@@ -639,16 +658,24 @@ internal bool TryReadSingle(out float value)
639658
}
640659

641660
AssertValidState();
661+
#if NETCOREAPP
662+
value = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(_bTmp));
663+
#else
642664
value = BitConverter.ToSingle(_bTmp, 0);
665+
#endif
643666
return true;
644667
}
645668
else
646669
{
647670
// The entire float is in the packet and in the buffer, so just return it
648671
// and take care of the counters.
649672

673+
#if NETCOREAPP
674+
value = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 4)));
675+
#else
650676
value = BitConverter.ToSingle(_inBuff, _inBytesUsed);
651677

678+
#endif
652679
_inBytesUsed += 4;
653680
_inBytesPacket -= 4;
654681

@@ -672,16 +699,24 @@ internal bool TryReadDouble(out double value)
672699
}
673700

674701
AssertValidState();
702+
#if NETCOREAPP
703+
value = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(_bTmp));
704+
#else
675705
value = BitConverter.ToDouble(_bTmp, 0);
706+
#endif
676707
return true;
677708
}
678709
else
679710
{
680711
// The entire double is in the packet and in the buffer, so just return it
681712
// and take care of the counters.
682713

714+
#if NETCOREAPP
715+
value = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 8)));
716+
#else
683717
value = BitConverter.ToDouble(_inBuff, _inBytesUsed);
684718

719+
#endif
685720
_inBytesUsed += 8;
686721
_inBytesPacket -= 8;
687722

@@ -1793,6 +1828,16 @@ private void SetBufferSecureStrings()
17931828
str = Marshal.SecureStringToBSTR(_securePasswords[i]);
17941829
byte[] data = new byte[_securePasswords[i].Length * 2];
17951830
Marshal.Copy(str, data, 0, _securePasswords[i].Length * 2);
1831+
if (!BitConverter.IsLittleEndian)
1832+
{
1833+
byte temp;
1834+
for (int ii = 0; ii < _securePasswords[i].Length * 2; ii += 2)
1835+
{
1836+
temp = (byte)data[ii];
1837+
data[ii] = (byte)data[ii + 1];
1838+
data[ii + 1] = (byte)temp;
1839+
}
1840+
}
17961841
TdsParserStaticMethods.ObfuscatePassword(data);
17971842
data.CopyTo(_outBuff, _securePasswordOffsetsInBuffer[i]);
17981843
}
@@ -2059,7 +2104,6 @@ internal void WriteSecureString(SecureString secureString)
20592104
Debug.Assert(_securePasswords[0] == null || _securePasswords[1] == null, "There are more than two secure passwords");
20602105

20612106
int index = _securePasswords[0] != null ? 1 : 0;
2062-
20632107
_securePasswords[index] = secureString;
20642108
_securePasswordOffsetsInBuffer[index] = _outBytesUsed;
20652109

@@ -2294,7 +2338,12 @@ internal Task WritePacket(byte flushMode, bool canAccumulate = false)
22942338
// So we need to avoid this check prior to login completing
22952339
state == TdsParserState.OpenLoggedIn
22962340
&& !_bulkCopyOpperationInProgress // ignore the condition checking for bulk copy
2297-
&& _outBytesUsed == (_outputHeaderLen + BitConverter.ToInt32(_outBuff, _outputHeaderLen))
2341+
&& _outBytesUsed == (_outputHeaderLen +
2342+
#if NETCOREAPP
2343+
BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(_outBuff, _outputHeaderLen, 4)))
2344+
#else
2345+
BitConverter.ToInt32(_outBuff, _outputHeaderLen))
2346+
#endif
22982347
&& _outputPacketCount == 0
22992348
|| _outBytesUsed == _outputHeaderLen
23002349
&& _outputPacketCount == 0)

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,16 @@ 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+
byte temp;
520+
for (int ii = 0; ii < byteCount; ii += 2)
521+
{
522+
temp = bytes[ii];
523+
bytes[ii] = bytes[ii + 1];
524+
bytes[ii + 1] = temp;
525+
}
526+
}
517527
Buffer.BlockCopy(bytes, byteIndex, chars, charIndex * 2, bytesUsed);
518528
}
519529
}

0 commit comments

Comments
 (0)