Skip to content

Commit

Permalink
big endian fix
Browse files Browse the repository at this point in the history
  • Loading branch information
saitama951 committed Sep 28, 2023
1 parent 111033e commit 4114d8a
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 10 deletions.
Expand Up @@ -3,6 +3,9 @@
// See the LICENSE file in the project root for more information.

using System;
#if NETCOREAPP
using System.Buffers.Binary;
#endif
using System.Diagnostics;
using System.Net;
using System.Net.Security;
Expand Down Expand Up @@ -59,10 +62,17 @@ public void Read(byte[] bytes)
{
SMID = bytes[0];
flags = bytes[1];
#if NETCOREAPP
sessionId = BinaryPrimitives.ReadUInt16LittleEndian(new ReadOnlySpan<byte>(bytes, 2, 2));
length = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 4, 4)) - SNISMUXHeader.HEADER_LENGTH;
sequenceNumber = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 8, 4));
highwater = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(bytes, 12, 4));
#else
sessionId = BitConverter.ToUInt16(bytes, 2);
length = BitConverter.ToUInt32(bytes, 4) - SNISMUXHeader.HEADER_LENGTH;
sequenceNumber = BitConverter.ToUInt32(bytes, 8);
highwater = BitConverter.ToUInt32(bytes, 12);
#endif
}

public void Write(Span<byte> bytes)
Expand Down
Expand Up @@ -4,16 +4,29 @@

using System;
using System.Diagnostics;
#if NETCOREAPP
using System.Buffers.Binary;
#endif

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

internal static void FillDoubleBytes(double value, Span<byte> buffer) => BitConverter.TryWriteBytes(buffer, value);
internal static void FillDoubleBytes(double value, Span<byte> buffer) =>
#if NETCOREAPP
BinaryPrimitives.WriteDoubleLittleEndian(buffer, value);
#else
BitConverter.TryWriteBytes(buffer, value);
#endif

internal static void FillFloatBytes(float v, Span<byte> buffer) => BitConverter.TryWriteBytes(buffer, v);
internal static void FillFloatBytes(float v, Span<byte> buffer) =>
#if NETCOREAPP
BinaryPrimitives.WriteSingleLittleEndian(buffer, v);
#else
BitConverter.TryWriteBytes(buffer, v);
#endif

internal static Guid ConstructGuid(ReadOnlySpan<byte> bytes)
{
Expand Down
Expand Up @@ -4,6 +4,9 @@

using System;
using System.Buffers;
#if NETCOREAPP
using System.Buffers.Binary;
#endif
using System.Collections.Generic;
using System.Data;
using System.Data.SqlTypes;
Expand Down Expand Up @@ -1743,14 +1746,10 @@ internal void WriteInt(int v, TdsParserStateObject stateObj)

internal static void WriteInt(Span<byte> buffer, int value)
{
#if NETCOREAPP
BitConverter.TryWriteBytes(buffer, value);
#else
buffer[0] = (byte)(value & 0xff);
buffer[1] = (byte)((value >> 8) & 0xff);
buffer[2] = (byte)((value >> 16) & 0xff);
buffer[3] = (byte)((value >> 24) & 0xff);
#endif
}

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

#if NETCOREAPP
var bytes = new byte[4];
BinaryPrimitives.WriteInt32LittleEndian(bytes, BitConverter.SingleToInt32Bits(v));
return bytes;
#else
return BitConverter.GetBytes(v);
#endif
}

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

#if NETCOREAPP
var bytes = new byte[8];
BinaryPrimitives.WriteInt64LittleEndian(bytes, BitConverter.DoubleToInt64Bits(v));
return bytes;
#else
return BitConverter.GetBytes(v);
#endif
}

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

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

#if NETCOREAPP
longValue = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 8));
#else
longValue = BitConverter.ToInt64(unencryptedBytes, 0);
#endif

if (tdsType == TdsEnums.SQLBIT ||
tdsType == TdsEnums.SQLBITN)
Expand Down Expand Up @@ -5809,7 +5829,11 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt
return false;
}

#if NETCOREAPP
singleValue = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(unencryptedBytes));
#else
singleValue = BitConverter.ToSingle(unencryptedBytes, 0);
#endif
value.Single = singleValue;
break;

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

#if NETCOREAPP
doubleValue = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(unencryptedBytes));
#else
doubleValue = BitConverter.ToDouble(unencryptedBytes, 0);
#endif
value.Double = doubleValue;
break;

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

#if NETCOREAPP
mid = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 4));
lo = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 4, 4));
#else
mid = BitConverter.ToInt32(unencryptedBytes, 0);
lo = BitConverter.ToUInt32(unencryptedBytes, 4);
#endif

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

#if NETCOREAPP
daypart = BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 0, 4));
timepart = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(unencryptedBytes, 4, 4));
#else
daypart = BitConverter.ToInt32(unencryptedBytes, 0);
timepart = BitConverter.ToUInt32(unencryptedBytes, 4);
#endif
value.SetToDateTime(daypart, (int)timepart);
break;

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

private static void CopyCharsToBytes(char[] source, int sourceOffset, byte[] dest, int destOffset, int charLength)
{
Buffer.BlockCopy(source, sourceOffset, dest, destOffset, charLength * ADP.CharSize);
if (!BitConverter.IsLittleEndian)
{
int desti = 0;
for(int srci = 0; srci < charLength; srci++)
{
dest[desti + destOffset] = (byte)(source[srci + sourceOffset]);
dest[desti + destOffset+1] = (byte)(source[srci + sourceOffset] >> 8);
desti += 2;
}
}
else
{
Buffer.BlockCopy(source, sourceOffset, dest, destOffset, charLength * ADP.CharSize);
}
}

private static void CopyStringToBytes(string source, int sourceOffset, byte[] dest, int destOffset, int charLength)
Expand Down Expand Up @@ -12571,7 +12626,6 @@ private bool TryReadPlpUnicodeCharsChunk(char[] buff, int offst, int len, TdsPar
{
charsToRead = (int)(stateObj._longlenleft >> 1);
}

if (!stateObj.TryReadChars(buff, offst, charsToRead, out charsRead))
{
charsRead = 0;
Expand Down
Expand Up @@ -4,6 +4,9 @@

using System;
using System.Diagnostics;
#if NETCOREAPP
using System.Buffers.Binary;
#endif
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
Expand Down Expand Up @@ -527,7 +530,11 @@ internal bool TryReadInt64(out long value)
Debug.Assert(_bTmpRead + bytesRead == 8, "TryReadByteArray returned true without reading all data required");
_bTmpRead = 0;
AssertValidState();
#if NETCOREAPP
value = BinaryPrimitives.ReadInt64LittleEndian(_bTmp);
#else
value = BitConverter.ToInt64(_bTmp, 0);
#endif
return true;
}
}
Expand All @@ -536,8 +543,12 @@ internal bool TryReadInt64(out long value)
// The entire long is in the packet and in the buffer, so just return it
// and take care of the counters.

#if NETCOREAPP
value = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 8));
#else
value = BitConverter.ToInt64(_inBuff, _inBytesUsed);

#endif
_inBytesUsed += 8;
_inBytesPacket -= 8;

Expand Down Expand Up @@ -605,7 +616,11 @@ internal bool TryReadUInt32(out uint value)
Debug.Assert(_bTmpRead + bytesRead == 4, "TryReadByteArray returned true without reading all data required");
_bTmpRead = 0;
AssertValidState();
#if NETCOREAPP
value = BinaryPrimitives.ReadUInt32LittleEndian(_bTmp);
#else
value = BitConverter.ToUInt32(_bTmp, 0);
#endif
return true;
}
}
Expand All @@ -614,7 +629,11 @@ internal bool TryReadUInt32(out uint value)
// The entire int is in the packet and in the buffer, so just return it
// and take care of the counters.

#if NETCOREAPP
value = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(_inBuff, _inBytesUsed, 4));
#else
value = BitConverter.ToUInt32(_inBuff, _inBytesUsed);
#endif

_inBytesUsed += 4;
_inBytesPacket -= 4;
Expand All @@ -639,16 +658,24 @@ internal bool TryReadSingle(out float value)
}

AssertValidState();
#if NETCOREAPP
value = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(_bTmp));
#else
value = BitConverter.ToSingle(_bTmp, 0);
#endif
return true;
}
else
{
// The entire float is in the packet and in the buffer, so just return it
// and take care of the counters.

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

#endif
_inBytesUsed += 4;
_inBytesPacket -= 4;

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

AssertValidState();
#if NETCOREAPP
value = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(_bTmp));
#else
value = BitConverter.ToDouble(_bTmp, 0);
#endif
return true;
}
else
{
// The entire double is in the packet and in the buffer, so just return it
// and take care of the counters.

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

#endif
_inBytesUsed += 8;
_inBytesPacket -= 8;

Expand Down Expand Up @@ -1793,6 +1828,16 @@ private void SetBufferSecureStrings()
str = Marshal.SecureStringToBSTR(_securePasswords[i]);
byte[] data = new byte[_securePasswords[i].Length * 2];
Marshal.Copy(str, data, 0, _securePasswords[i].Length * 2);
if (!BitConverter.IsLittleEndian)
{
byte temp;
for (int ii = 0; ii < _securePasswords[i].Length * 2; ii += 2)
{
temp = (byte)data[ii];
data[ii] = (byte)data[ii + 1];
data[ii + 1] = (byte)temp;
}
}
TdsParserStaticMethods.ObfuscatePassword(data);
data.CopyTo(_outBuff, _securePasswordOffsetsInBuffer[i]);
}
Expand Down Expand Up @@ -2059,7 +2104,6 @@ internal void WriteSecureString(SecureString secureString)
Debug.Assert(_securePasswords[0] == null || _securePasswords[1] == null, "There are more than two secure passwords");

int index = _securePasswords[0] != null ? 1 : 0;

_securePasswords[index] = secureString;
_securePasswordOffsetsInBuffer[index] = _outBytesUsed;

Expand Down Expand Up @@ -2294,7 +2338,12 @@ internal Task WritePacket(byte flushMode, bool canAccumulate = false)
// So we need to avoid this check prior to login completing
state == TdsParserState.OpenLoggedIn
&& !_bulkCopyOpperationInProgress // ignore the condition checking for bulk copy
&& _outBytesUsed == (_outputHeaderLen + BitConverter.ToInt32(_outBuff, _outputHeaderLen))
&& _outBytesUsed == (_outputHeaderLen +
#if NETCOREAPP
BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan<byte>(_outBuff, _outputHeaderLen, 4)))
#else
BitConverter.ToInt32(_outBuff, _outputHeaderLen))
#endif
&& _outputPacketCount == 0
|| _outBytesUsed == _outputHeaderLen
&& _outputPacketCount == 0)
Expand Down
Expand Up @@ -514,6 +514,16 @@ public override void Convert(byte[] bytes, int byteIndex, int byteCount, char[]
completed = (bytesUsed == byteCount);

// BlockCopy uses offsets\length measured in bytes, not the actual array index
if (!BitConverter.IsLittleEndian)
{
byte temp;
for (int ii = 0; ii < byteCount; ii += 2)
{
temp = bytes[ii];
bytes[ii] = bytes[ii + 1];
bytes[ii + 1] = temp;
}
}
Buffer.BlockCopy(bytes, byteIndex, chars, charIndex * 2, bytesUsed);
}
}
Expand Down

0 comments on commit 4114d8a

Please sign in to comment.