diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index bb64c370d0..33c2778d1f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -11,19 +11,29 @@ using System.Diagnostics; using System.Globalization; using System.IO; +#if NET using System.Security.Authentication; +#else +using System.Runtime.CompilerServices; +#endif using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; using Interop.Common.Sni; +#if NETFRAMEWORK +using Interop.Windows.Sni; +#endif using Microsoft.Data.Common; using Microsoft.Data.ProviderBase; using Microsoft.Data.Sql; using Microsoft.Data.SqlClient.DataClassification; using Microsoft.Data.SqlClient.LocalDb; using Microsoft.Data.SqlClient.Server; +#if NETFRAMEWORK using Microsoft.Data.SqlTypes; +#endif +using Microsoft.SqlServer.Server; namespace Microsoft.Data.SqlClient { @@ -350,8 +360,7 @@ internal void ProcessPendingAck(TdsParserStateObject stateObj) } } - internal void Connect( - ServerInfo serverInfo, + internal void Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, TimeoutTimer timeout, SqlConnectionString connectionOptions, @@ -537,7 +546,8 @@ internal void Connect( _physicalStateObj.SniContext = SniContext.Snix_Connect; _physicalStateObj.CreatePhysicalSNIHandle( serverInfo.ExtendedServerName, - timeout, out instanceName, + timeout, + out instanceName, ref _serverSpn, true, true, @@ -924,7 +934,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( out bool marsCapable, out bool fedAuthRequired, bool tlsFirst, - string serverCert) + string serverCertificateFilename) { // Assign default values marsCapable = _fMARS; @@ -1007,7 +1017,8 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( ON, NOT_SUP, REQ, - LOGIN + LOGIN, + OPTIONS_MASK = 0x3f } */ // Any response other than NOT_SUP means the server supports encryption. @@ -1146,7 +1157,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( uint info = (shouldValidateServerCert ? TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE : 0) | TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE; - EnableSsl(info, encrypt, integratedSecurity, serverCert); + EnableSsl(info, encrypt, integratedSecurity, serverCertificateFilename); } return PreLoginHandshakeStatus.Successful; @@ -1499,6 +1510,7 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj) string providerName = StringsHelper.GetResourceString(providerRid); Debug.Assert(!string.IsNullOrEmpty(providerName), $"invalid providerResourceId '{providerRid}'"); uint win32ErrorCode = details.nativeError; + SqlClientEventSource.Log.TryAdvancedTraceEvent(" SNI Native Error Code = {0}", win32ErrorCode); if (details.sniErrorNumber == 0) { @@ -2000,7 +2012,9 @@ internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandle } if (TdsParserState.Broken == State || TdsParserState.Closed == State) + { break; // jump out of the loop if the state is already broken or closed. + } if (!stateObj._accumulateInfoEvents && (stateObj._pendingInfoEvents != null)) { @@ -2020,10 +2034,13 @@ internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandle } } else + { foreach (SqlError error in stateObj._pendingInfoEvents) { stateObj.AddWarning(error); } + } + } stateObj._pendingInfoEvents = null; } @@ -2230,7 +2247,7 @@ internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandle while (env != null) { - if (!this.Connection.IgnoreEnvChange) + if (!Connection.IgnoreEnvChange) { switch (env._type) { @@ -2368,7 +2385,8 @@ internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandle if (tokenLength != TdsEnums.VARNULL) { _SqlMetaDataSet metadata; - result = TryProcessMetaData(tokenLength, stateObj, out metadata, cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); + result = TryProcessMetaData(tokenLength, stateObj, out metadata, + cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); if (result != TdsOperationStatus.Done) { return result; @@ -2502,7 +2520,8 @@ internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandle case TdsEnums.SQLRETURNVALUE: { SqlReturnValue returnValue; - result = TryProcessReturnValue(tokenLength, stateObj, out returnValue, cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); + result = TryProcessReturnValue(tokenLength, stateObj, out returnValue, + cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); if (result != TdsOperationStatus.Done) { return result; @@ -4091,7 +4110,10 @@ internal TdsOperationStatus TryProcessError(byte token, TdsParserStateObject sta return TdsOperationStatus.Done; } - internal TdsOperationStatus TryProcessReturnValue(int length, TdsParserStateObject stateObj, out SqlReturnValue returnValue, SqlCommandColumnEncryptionSetting columnEncryptionSetting) + internal TdsOperationStatus TryProcessReturnValue(int length, + TdsParserStateObject stateObj, + out SqlReturnValue returnValue, + SqlCommandColumnEncryptionSetting columnEncryptionSetting) { returnValue = null; SqlReturnValue rec = new SqlReturnValue(); @@ -4499,6 +4521,7 @@ internal TdsOperationStatus TryProcessCollation(TdsParserStateObject stateObj, o collation = null; return result; } + if (SqlCollation.Equals(_cachedCollation, info, sortId)) { collation = _cachedCollation; @@ -4619,63 +4642,84 @@ internal int GetCodePage(SqlCollation collation, TdsParserStateObject stateObj) internal void DrainData(TdsParserStateObject stateObj) { +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif try { - SqlDataReader.SharedState sharedState = stateObj._readerState; - if (sharedState != null && sharedState._dataReady) + try { - _SqlMetaDataSet metadata = stateObj._cleanupMetaData; - if (stateObj._partialHeaderBytesRead > 0) + SqlDataReader.SharedState sharedState = stateObj._readerState; + if (sharedState != null && sharedState._dataReady) { - if (stateObj.TryProcessHeader() != TdsOperationStatus.Done) + _SqlMetaDataSet metadata = stateObj._cleanupMetaData; + if (stateObj._partialHeaderBytesRead > 0) { - throw SQL.SynchronousCallMayNotPend(); + if (stateObj.TryProcessHeader() != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } } - } - if (0 == sharedState._nextColumnHeaderToRead) - { - // i. user called read but didn't fetch anything - if (stateObj.Parser.TrySkipRow(stateObj._cleanupMetaData, stateObj) != TdsOperationStatus.Done) + if (0 == sharedState._nextColumnHeaderToRead) { - throw SQL.SynchronousCallMayNotPend(); + // i. user called read but didn't fetch anything + if (stateObj.Parser.TrySkipRow(stateObj._cleanupMetaData, stateObj) != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } } - } - else - { - // iia. if we still have bytes left from a partially read column, skip - if (sharedState._nextColumnDataToRead < sharedState._nextColumnHeaderToRead) + else { - if ((sharedState._nextColumnHeaderToRead > 0) && (metadata[sharedState._nextColumnHeaderToRead - 1].metaType.IsPlp)) + // iia. if we still have bytes left from a partially read column, skip + if (sharedState._nextColumnDataToRead < sharedState._nextColumnHeaderToRead) { - if (stateObj._longlen != 0) + if ((sharedState._nextColumnHeaderToRead > 0) && (metadata[sharedState._nextColumnHeaderToRead - 1].metaType.IsPlp)) { - if (TrySkipPlpValue(ulong.MaxValue, stateObj, out _) != TdsOperationStatus.Done) + if (stateObj._longlen != 0) { - throw SQL.SynchronousCallMayNotPend(); + if (TrySkipPlpValue(ulong.MaxValue, stateObj, out _) != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } } } - } - else if (0 < sharedState._columnDataBytesRemaining) - { - if (stateObj.TrySkipLongBytes(sharedState._columnDataBytesRemaining) != TdsOperationStatus.Done) + else if (0 < sharedState._columnDataBytesRemaining) { - throw SQL.SynchronousCallMayNotPend(); + if (stateObj.TrySkipLongBytes(sharedState._columnDataBytesRemaining) != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } } } - } - // Read the remaining values off the wire for this row - if (stateObj.Parser.TrySkipRow(metadata, sharedState._nextColumnHeaderToRead, stateObj) != TdsOperationStatus.Done) - { - throw SQL.SynchronousCallMayNotPend(); + // Read the remaining values off the wire for this row + if (stateObj.Parser.TrySkipRow(metadata, sharedState._nextColumnHeaderToRead, stateObj) != TdsOperationStatus.Done) + { + throw SQL.SynchronousCallMayNotPend(); + } } } + Run(RunBehavior.Clean, null, null, null, stateObj); } - Run(RunBehavior.Clean, null, null, null, stateObj); + catch + { + _connHandler.DoomThisConnection(); + throw; + } + } + catch (OutOfMemoryException) + { + _connHandler.DoomThisConnection(); + throw; + } + catch (StackOverflowException) + { + _connHandler.DoomThisConnection(); + throw; } - catch + catch (ThreadAbortException) { _connHandler.DoomThisConnection(); throw; @@ -5248,7 +5292,8 @@ private TdsOperationStatus TryCommonProcessMetaData(TdsParserStateObject stateOb return TdsOperationStatus.Done; } - private void WriteUDTMetaData(object value, string database, string schema, string type, TdsParserStateObject stateObj) + private void WriteUDTMetaData(object value, string database, string schema, string type, + TdsParserStateObject stateObj) { // database if (string.IsNullOrEmpty(database)) @@ -5635,7 +5680,9 @@ private TdsOperationStatus TryProcessRow(_SqlMetaDataSet columns, object[] buffe // We only read up to 2Gb. Throw if data is larger. Very large data // should be read in chunks in sequential read mode // For Plp columns, we may have gotten only the length of the first chunk - result = TryReadSqlValue(data, md, md.metaType.IsPlp ? (Int32.MaxValue) : (int)len, stateObj, SqlCommandColumnEncryptionSetting.Disabled /*Column Encryption Disabled for Bulk Copy*/, md.column); + result = TryReadSqlValue(data, md, md.metaType.IsPlp ? (int.MaxValue) : (int)len, stateObj, + SqlCommandColumnEncryptionSetting.Disabled /*Column Encryption Disabled for Bulk Copy*/, + md.column); if (result != TdsOperationStatus.Done) { return result; @@ -5671,11 +5718,15 @@ internal static bool ShouldHonorTceForRead(SqlCommandColumnEncryptionSetting col // Check connection level setting! Debug.Assert(SqlCommandColumnEncryptionSetting.UseConnectionSetting == columnEncryptionSetting, "Unexpected value for command level override"); - return (connection != null && connection.ConnectionOptions != null && connection.ConnectionOptions.ColumnEncryptionSetting == SqlConnectionColumnEncryptionSetting.Enabled); + return (connection != null && connection.ConnectionOptions != null + && connection.ConnectionOptions.ColumnEncryptionSetting == SqlConnectionColumnEncryptionSetting.Enabled); } } - internal static object GetNullSqlValue(SqlBuffer nullVal, SqlMetaDataPriv md, SqlCommandColumnEncryptionSetting columnEncryptionSetting, SqlInternalConnectionTds connection) + internal static object GetNullSqlValue(SqlBuffer nullVal, + SqlMetaDataPriv md, + SqlCommandColumnEncryptionSetting columnEncryptionSetting, + SqlInternalConnectionTds connection) { SqlDbType type = md.type; @@ -6271,7 +6322,13 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt return true; } - internal TdsOperationStatus TryReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, int length, TdsParserStateObject stateObj, SqlCommandColumnEncryptionSetting columnEncryptionOverride, string columnName, SqlCommand command = null) + internal TdsOperationStatus TryReadSqlValue(SqlBuffer value, + SqlMetaDataPriv md, + int length, + TdsParserStateObject stateObj, + SqlCommandColumnEncryptionSetting columnEncryptionOverride, + string columnName, + SqlCommand command = null) { bool isPlp = md.metaType.IsPlp; byte tdsType = md.tdsType; @@ -6382,7 +6439,7 @@ internal TdsOperationStatus TryReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, } else { - value.SqlBinary = SqlBinary.WrapBytes(b); + value.SqlBinary = SqlBinary.WrapBytes(b); // doesn't copy the byte array } break; @@ -6716,8 +6773,9 @@ internal TdsOperationStatus TryReadSqlValueInternal(SqlBuffer value, byte tdsTyp case TdsEnums.SQLUNIQUEID: { - Debug.Assert(length == 16, "invalid length for SqlGuid type!"); - Span b = stackalloc byte[16]; + Debug.Assert(length == GUID_SIZE, "invalid length for SqlGuid type!"); + + Span b = stackalloc byte[GUID_SIZE]; result = stateObj.TryReadByteArray(b, length); if (result != TdsOperationStatus.Done) { @@ -6741,7 +6799,7 @@ internal TdsOperationStatus TryReadSqlValueInternal(SqlBuffer value, byte tdsTyp { return result; } - value.SqlBinary = SqlBinary.WrapBytes(b); + value.SqlBinary = SqlBinary.WrapBytes(b); // doesn't copy the byte array break; } @@ -8002,7 +8060,6 @@ internal TdsOperationStatus TryGetTokenLength(byte token, TdsParserStateObject s tokenLength = -1; return TdsOperationStatus.Done; case TdsEnums.SQLSESSIONSTATE: - return stateObj.TryReadInt32(out tokenLength); case TdsEnums.SQLFEDAUTHINFO: return stateObj.TryReadInt32(out tokenLength); } @@ -8367,7 +8424,7 @@ internal int WriteFedAuthFeatureRequest(FederatedAuthenticationFeatureExtensionD internal int WriteTceFeatureRequest(bool write /* if false just calculates the length */) { - int len = 6; // (1byte = featureID, 4bytes = featureData length, 1 bytes = Version + int len = 6; // 1byte = featureID, 4bytes = featureData length, 1 bytes = Version if (write) { @@ -8679,7 +8736,7 @@ private void WriteLoginData(SqlLogin rec, // write variable length portion WriteString(rec.hostName, _physicalStateObj); - // if we are using SSPI, do not send over username/password, since we will use SSPI instead + // if we are using SSPI or fed auth MSAL, do not send over username/password, since we will use SSPI instead // same behavior as Luxor if (!rec.useSSPI && !(_connHandler._federatedAuthenticationInfoRequested || _connHandler._federatedAuthenticationRequested)) { @@ -9388,7 +9445,8 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout if ( !(cmd.ColumnEncryptionSetting == SqlCommandColumnEncryptionSetting.Enabled || - (cmd.ColumnEncryptionSetting == SqlCommandColumnEncryptionSetting.UseConnectionSetting && cmd.Connection.IsColumnEncryptionSettingEnabled))) + (cmd.ColumnEncryptionSetting == SqlCommandColumnEncryptionSetting.UseConnectionSetting && cmd.Connection.IsColumnEncryptionSettingEnabled)) + ) { throw SQL.ParamInvalidForceColumnEncryptionSetting(param.ParameterName, rpcext.GetCommandTextOrRpcName()); } @@ -9785,7 +9843,7 @@ private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParamet { int maxSupportedSize = Is2008OrNewer ? int.MaxValue : short.MaxValue; byte[] udtVal = null; - SqlServer.Server.Format format = SqlServer.Server.Format.Native; + Format format = Format.Native; if (string.IsNullOrEmpty(param.UdtTypeName)) { @@ -10054,7 +10112,28 @@ private void FinalizeExecuteRPC(TdsParserStateObject stateObj) private void TdsExecuteRPC_OnFailure(Exception exc, TdsParserStateObject stateObj) { - FailureCleanup(stateObj, exc); +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif + try + { + FailureCleanup(stateObj, exc); + } + catch (OutOfMemoryException) + { + _connHandler.DoomThisConnection(); + throw; + } + catch (StackOverflowException) + { + _connHandler.DoomThisConnection(); + throw; + } + catch (ThreadAbortException) + { + _connHandler.DoomThisConnection(); + throw; + } } private void ExecuteFlushTaskCallback(Task tsk, TdsParserStateObject stateObj, TaskCompletionSource completion, bool releaseConnectionLock) @@ -10065,10 +10144,32 @@ private void ExecuteFlushTaskCallback(Task tsk, TdsParserStateObject stateObj, T if (tsk.Exception != null) { Exception exc = tsk.Exception.InnerException; + +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif try { FailureCleanup(stateObj, tsk.Exception); } + catch (OutOfMemoryException e) + { + _connHandler.DoomThisConnection(); + completion.SetException(e); + throw; + } + catch (StackOverflowException e) + { + _connHandler.DoomThisConnection(); + completion.SetException(e); + throw; + } + catch (ThreadAbortException e) + { + _connHandler.DoomThisConnection(); + completion.SetException(e); + throw; + } catch (Exception e) { exc = e; @@ -10171,7 +10272,8 @@ private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefa else { value = param.GetCoercedValue(); - typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData.SqlDbType, metaData.IsMultiValued, value, null); + typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( + metaData.SqlDbType, metaData.IsMultiValued, value, null); } if (advancedTraceIsOn) @@ -11137,7 +11239,6 @@ private Task WriteBulkCopyValueSetupContinuation(Task internalWriteTask, Encodin // Write mars header data, not including the mars header length private void WriteMarsHeaderData(TdsParserStateObject stateObj, SqlInternalTransaction transaction) { - // Function to send over additional payload header data for 2005 and beyond only. // We may need to update the mars header length if mars header is changed in the future WriteShort(TdsEnums.HEADERTYPE_MARS, stateObj); @@ -11409,7 +11510,9 @@ private Task GetTerminationTask(Task unterminatedWriteTask, object value, MetaTy } else { - return AsyncHelper.CreateContinuationTask(unterminatedWriteTask, WriteInt, 0, stateObj); + return AsyncHelper.CreateContinuationTask(unterminatedWriteTask, + WriteInt, 0, stateObj + ); } } else @@ -11729,14 +11832,35 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati StripPreamble(buffer, ref offset, ref count); - Task task = null; - if (count > 0) +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif + try { - _parser.WriteInt(count, _stateObj); // write length of chunk - task = _stateObj.WriteByteArray(buffer, count, offset, canAccumulate: false); - } + Task task = null; + if (count > 0) + { + _parser.WriteInt(count, _stateObj); // write length of chunk + task = _stateObj.WriteByteArray(buffer, count, offset, canAccumulate: false); + } - return task ?? Task.CompletedTask; + return task ?? Task.CompletedTask; + } + catch (OutOfMemoryException) + { + _parser._connHandler.DoomThisConnection(); + throw; + } + catch (StackOverflowException) + { + _parser._connHandler.DoomThisConnection(); + throw; + } + catch (ThreadAbortException) + { + _parser._connHandler.DoomThisConnection(); + throw; + } } internal static void ValidateWriteParameters(byte[] buffer, int offset, int count) @@ -11901,7 +12025,7 @@ private async Task WriteXmlFeed(XmlDataFeed feed, TdsParserStateObject stateObj, } XmlWriterSettings writerSettings = new XmlWriterSettings(); - writerSettings.CloseOutput = false; // don't close the memory stream + writerSettings.CloseOutput = false; // don't close the memory stream writerSettings.ConformanceLevel = ConformanceLevel.Fragment; if (_asyncWrite) { @@ -13062,6 +13186,7 @@ bool writeDataSizeToSnapshot } } } + // Special case single byte if ( (stateObj._longlenleft == 1 || partialReadInProgress) @@ -13168,7 +13293,6 @@ static int IncrementSnapshotDataSize(TdsParserStateObject stateObj, bool resetti } } - internal int ReadPlpAnsiChars(ref char[] buff, int offst, int len, SqlMetaDataPriv metadata, TdsParserStateObject stateObj) { int charsRead = 0; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs index 2fbfbd6101..b8433464ca 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -11,24 +11,29 @@ using System.Diagnostics; using System.Globalization; using System.IO; +#if NET +using System.Security.Authentication; +#else using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; +#endif using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; -using System.Net; using Interop.Common.Sni; +#if NETFRAMEWORK using Interop.Windows.Sni; +#endif using Microsoft.Data.Common; +using Microsoft.Data.ProviderBase; using Microsoft.Data.Sql; using Microsoft.Data.SqlClient.DataClassification; using Microsoft.Data.SqlClient.LocalDb; using Microsoft.Data.SqlClient.Server; +#if NETFRAMEWORK using Microsoft.Data.SqlTypes; +#endif using Microsoft.SqlServer.Server; -using Microsoft.Data.ProviderBase; namespace Microsoft.Data.SqlClient { @@ -36,21 +41,13 @@ namespace Microsoft.Data.SqlClient // and surfacing objects to the user. internal sealed partial class TdsParser { - private static int _objectTypeCount; // EventSource Counter + private static int _objectTypeCount; // EventSource counter private readonly SqlClientLogger _logger = new SqlClientLogger(); private SSPIContextProvider _authenticationProvider; - internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount); - - - internal int ObjectID - { - get - { - return _objectID; - } - } + internal readonly int _objectID = Interlocked.Increment(ref _objectTypeCount); + internal int ObjectID => _objectID; /// /// Verify client encryption possibility. @@ -90,9 +87,9 @@ internal int ObjectID internal Encoding _defaultEncoding = null; // for sql character data - private static EncryptionOptions _sniSupportedEncryptionOption = SNILoadHandle.SingletonInstance.Options; + private static EncryptionOptions s_sniSupportedEncryptionOption = SNILoadHandle.SingletonInstance.Options; - private EncryptionOptions _encryptionOption = _sniSupportedEncryptionOption; + private EncryptionOptions _encryptionOption = s_sniSupportedEncryptionOption; private SqlInternalTransaction _currentTransaction; private SqlInternalTransaction _pendingTransaction; // pending transaction for 2005 and beyond. @@ -126,8 +123,6 @@ internal int ObjectID private string _serverSpn = null; - // UNDONE - need to have some for both instances - both command and default??? - // SqlStatistics private SqlStatistics _statistics = null; @@ -143,13 +138,10 @@ internal int ObjectID // textptr sequence private static readonly byte[] s_longDataHeader = { 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - // Various other statics - private const int ATTENTION_TIMEOUT = 5000; // internal attention timeout, in ticks - - // XML metadata substitue sequence + // XML metadata substitute sequence private static readonly byte[] s_xmlMetadataSubstituteSequence = { 0xe7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }; - // JSON metadata substitue sequence + // JSON metadata substitute sequence private static readonly byte[] s_jsonMetadataSubstituteSequence = { 0xa7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }; // size of Guid (e.g. _clientConnectionId, ActivityId.Id) @@ -158,7 +150,7 @@ internal int ObjectID // now data length is 1 byte // First bit is 1 indicating client support failover partner with readonly intent - private static readonly byte[] s_FeatureExtDataAzureSQLSupportFeatureRequest = { 0x01 }; + private static readonly byte[] s_featureExtDataAzureSQLSupportFeatureRequest = { 0x01 }; // NOTE: You must take the internal connection's _parserLock before modifying this internal bool _asyncWrite = false; @@ -202,6 +194,7 @@ internal int ObjectID internal TdsParser(bool MARS, bool fAsynchronous) { _fMARS = MARS; // may change during Connect to pre 2005 servers + _physicalStateObj = new TdsParserStateObject(this); DataClassificationVersion = TdsEnums.DATA_CLASSIFICATION_NOT_ENABLED; } @@ -241,8 +234,8 @@ internal SqlInternalTransaction CurrentTransaction // change it; this can occur when there is a delegated transaction // and the user attempts to do an API begin transaction; in these // cases, it's safe to ignore the set. - if ((_currentTransaction == null && value != null) || - (_currentTransaction != null && value == null)) + if ((_currentTransaction == null && value != null) + || (_currentTransaction != null && value == null)) { _currentTransaction = value; } @@ -395,7 +388,7 @@ internal void Connect(ServerInfo serverInfo, // Clean up IsSQLDNSCachingSupported flag from previous status _connHandler.IsSQLDNSCachingSupported = false; - UInt32 sniStatus = SNILoadHandle.SingletonInstance.Status; + uint sniStatus = SNILoadHandle.SingletonInstance.Status; if (sniStatus != TdsEnums.SNI_SUCCESS) { @@ -556,7 +549,7 @@ internal void Connect(ServerInfo serverInfo, serverInfo.ResolvedServerName : serverInfo.PreRoutingServerName); } _state = TdsParserState.OpenNotLoggedIn; - _physicalStateObj.SniContext = SniContext.Snix_PreLoginBeforeSuccessfulWrite; // SQL BU DT 376766 + _physicalStateObj.SniContext = SniContext.Snix_PreLoginBeforeSuccessfulWrite; _physicalStateObj.TimeoutTime = timeout.LegacyTimerExpire; bool marsCapable = false; @@ -584,12 +577,7 @@ internal void Connect(ServerInfo serverInfo, // UNDONE - send "" for instance now, need to fix later SqlClientEventSource.Log.TryTraceEvent(" Sending prelogin handshake"); - - SendPreLoginHandshake( - instanceName, - encrypt, - integratedSecurity, - serverCertificateFilename); + SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename); _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake); _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake); @@ -597,7 +585,6 @@ internal void Connect(ServerInfo serverInfo, _physicalStateObj.SniContext = SniContext.Snix_PreLogin; SqlClientEventSource.Log.TryTraceEvent(" Consuming prelogin handshake"); PreLoginHandshakeStatus status = ConsumePreLoginHandshake( - authType, encrypt, trustServerCert, integratedSecurity, @@ -643,14 +630,8 @@ internal void Connect(ServerInfo serverInfo, // for DNS Caching phase 1 AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache); - SendPreLoginHandshake( - instanceName, - encrypt, - integratedSecurity, - serverCertificateFilename); - + SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename); status = ConsumePreLoginHandshake( - authType, encrypt, trustServerCert, integratedSecurity, @@ -815,14 +796,14 @@ private void SendPreLoginHandshake( byte[] instanceName, SqlConnectionEncryptOption encrypt, bool integratedSecurity, - string serverCertificate) + string serverCertificateFilename) { if (encrypt == SqlConnectionEncryptOption.Strict) { //Always validate the certificate when in strict encryption mode uint info = TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE | TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE | TdsEnums.SNI_SSL_SEND_ALPN_EXTENSION; - EnableSsl(info, encrypt, integratedSecurity, serverCertificate); + EnableSsl(info, encrypt, integratedSecurity, serverCertificateFilename); // Since encryption has already been negotiated, we need to set encryption not supported in // prelogin so that we don't try to negotiate encryption again during ConsumePreLoginHandshake. @@ -990,7 +971,7 @@ private void SendPreLoginHandshake( _physicalStateObj.WritePacket(TdsEnums.HARDFLUSH); } - private void EnableSsl(uint info, SqlConnectionEncryptOption encrypt, bool integratedSecurity, string serverCertificate) + private void EnableSsl(uint info, SqlConnectionEncryptOption encrypt, bool integratedSecurity, string serverCertificateFilename) { uint error = 0; @@ -1010,7 +991,7 @@ private void EnableSsl(uint info, SqlConnectionEncryptOption encrypt, bool integ authInfo.certHash = false; authInfo.clientCertificateCallbackContext = IntPtr.Zero; authInfo.clientCertificateCallback = null; - authInfo.serverCertFileName = string.IsNullOrEmpty(serverCertificate) ? null : serverCertificate; + authInfo.serverCertFileName = string.IsNullOrEmpty(serverCertificateFilename) ? null : serverCertificateFilename; Debug.Assert((_encryptionOption & EncryptionOptions.CLIENT_CERT) == 0, "Client certificate authentication support has been removed"); @@ -1054,7 +1035,6 @@ private void EnableSsl(uint info, SqlConnectionEncryptOption encrypt, bool integ } private PreLoginHandshakeStatus ConsumePreLoginHandshake( - SqlAuthenticationMethod authType, SqlConnectionEncryptOption encrypt, bool trustServerCert, bool integratedSecurity, @@ -1145,9 +1125,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake( NOT_SUP, REQ, LOGIN, - OPTIONS_MASK = 0x3f, - CTAIP = 0x40, - CLIENT_CERT = 0x80, + OPTIONS_MASK = 0x3f } */ // Any response other than NOT_SUP means the server supports encryption. @@ -1571,14 +1549,14 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj) // There is an exception here for MARS as its possible that another thread has closed the connection just as we see an error Debug.Assert(SniContext.Undefined != stateObj.DebugOnlyCopyOfSniContext || ((_fMARS) && ((_state == TdsParserState.Closed) || (_state == TdsParserState.Broken))), "SniContext must not be None"); #endif - SniError sniError = new SniError(); - SniNativeWrapper.SniGetLastError(out sniError); + SniError details = new SniError(); + SniNativeWrapper.SniGetLastError(out details); - if (sniError.sniError != 0) + if (details.sniError != 0) { // handle special SNI error codes that are converted into exception which is not a SqlException. - switch (sniError.sniError) + switch (details.sniError) { case SniErrors.MultiSubnetFailoverWithMoreThan64IPs: // Connecting with the MultiSubnetFailover connection option to a SQL Server instance configured with more than 64 IP addresses is not supported. @@ -1598,7 +1576,7 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj) // error.errorMessage is null terminated with garbage beyond that, since fixed length string errorMessage; - errorMessage = string.IsNullOrEmpty(sniError.errorMessage) ? string.Empty : sniError.errorMessage; + errorMessage = string.IsNullOrEmpty(details.errorMessage) ? string.Empty : details.errorMessage; /* Format SNI errors and add Context Information * * General syntax is: @@ -1615,13 +1593,12 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj) Debug.Assert(!ADP.IsEmpty(errorMessage), "Empty error message received from SNI"); string sqlContextInfo = StringsHelper.GetString(Enum.GetName(typeof(SniContext), stateObj.SniContext)); - - string providerRid = String.Format("SNI_PN{0}", (int)sniError.provider); + string providerRid = string.Format("SNI_PN{0}", (int)details.provider); string providerName = StringsHelper.GetString(providerRid); Debug.Assert(!string.IsNullOrEmpty(providerName), $"invalid providerResourceId '{providerRid}'"); - uint win32ErrorCode = sniError.nativeError; + uint win32ErrorCode = details.nativeError; - if (sniError.sniError == 0) + if (details.sniError == 0) { // Provider error. The message from provider is preceeded with non-localizable info from SNI // strip provider info from SNI @@ -1634,7 +1611,7 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj) if (0 <= iColon) { int len = errorMessage.Length; - len -= 2; // exclude "\r\n" sequence + len -= 2; // exclude newline sequence iColon += 2; // skip over ": " sequence len -= iColon; /* @@ -1651,22 +1628,21 @@ internal SqlError ProcessSNIError(TdsParserStateObject stateObj) } else { - // SNI error. Replace the entire message - // - errorMessage = SQL.GetSNIErrorMessage(sniError.sniError); + // SNI error. Replace the entire message. + errorMessage = SQL.GetSNIErrorMessage(details.sniError); // If its a LocalDB error, then nativeError actually contains a LocalDB-specific error code, not a win32 error code - if (sniError.sniError == SniErrors.LocalDBErrorCode) + if (details.sniError == SniErrors.LocalDBErrorCode) { - errorMessage += LocalDbApi.GetLocalDbMessage((int)sniError.nativeError); + errorMessage += LocalDbApi.GetLocalDbMessage((int)details.nativeError); win32ErrorCode = 0; } } errorMessage = string.Format("{0} (provider: {1}, error: {2} - {3})", - sqlContextInfo, providerName, (int)sniError.sniError, errorMessage); + sqlContextInfo, providerName, (int)details.sniError, errorMessage); - return new SqlError((int)sniError.nativeError, 0x00, TdsEnums.FATAL_ERROR_CLASS, - _server, errorMessage, sniError.function, (int)sniError.lineNumber, win32ErrorCode); + return new SqlError((int)details.nativeError, 0x00, TdsEnums.FATAL_ERROR_CLASS, + _server, errorMessage, details.function, (int)details.lineNumber, win32ErrorCode); } internal void CheckResetConnection(TdsParserStateObject stateObj) @@ -1831,11 +1807,11 @@ internal byte[] SerializeInt(int v, TdsParserStateObject stateObj) { if (stateObj._bIntBytes == null) { - stateObj._bIntBytes = new byte[4]; + stateObj._bIntBytes = new byte[sizeof(int)]; } else { - Debug.Assert(4 == stateObj._bIntBytes.Length); + Debug.Assert(sizeof(int) == stateObj._bIntBytes.Length); } int current = 0; @@ -1997,7 +1973,7 @@ internal void WriteUnsignedLong(ulong uv, TdsParserStateObject stateObj) // internal byte[] SerializeDouble(double v) { - if (Double.IsInfinity(v) || Double.IsNaN(v)) + if (double.IsInfinity(v) || double.IsNaN(v)) { throw ADP.ParameterValueOutOfRange(v.ToString()); } @@ -2470,7 +2446,7 @@ internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandle { _SqlMetaDataSet metadata; result = TryProcessMetaData(tokenLength, stateObj, out metadata, - cmdHandler != null ? cmdHandler.ColumnEncryptionSetting : SqlCommandColumnEncryptionSetting.UseConnectionSetting); + cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); if (result != TdsOperationStatus.Done) { return result; @@ -2605,7 +2581,7 @@ internal TdsOperationStatus TryRun(RunBehavior runBehavior, SqlCommand cmdHandle { SqlReturnValue returnValue; result = TryProcessReturnValue(tokenLength, stateObj, out returnValue, - cmdHandler != null ? cmdHandler.ColumnEncryptionSetting : SqlCommandColumnEncryptionSetting.UseConnectionSetting); + cmdHandler?.ColumnEncryptionSetting ?? SqlCommandColumnEncryptionSetting.UseConnectionSetting); if (result != TdsOperationStatus.Done) { return result; @@ -2893,7 +2869,6 @@ private TdsOperationStatus TryProcessEnvChange(int tokenLength, TdsParserStateOb _defaultCollation = env._newCollation; _defaultLCID = env._newCollation.LCID; - // UTF8 collation if (env._newCollation.IsUTF8) { @@ -3022,7 +2997,6 @@ private TdsOperationStatus TryProcessEnvChange(int tokenLength, TdsParserStateOb case TdsEnums.ENV_TRANSACTIONMANAGERADDRESS: case TdsEnums.ENV_SPRESETCONNECTIONACK: - // TODO UNDONE BUGBUG - need to implement support for these env changes result = TryReadTwoBinaryFields(env, stateObj); if (result != TdsOperationStatus.Done) { @@ -4193,11 +4167,10 @@ internal TdsOperationStatus TryProcessError(byte token, TdsParserStateObject sta return TdsOperationStatus.Done; } - internal TdsOperationStatus TryProcessReturnValue(int length, - TdsParserStateObject stateObj, - out SqlReturnValue returnValue, - SqlCommandColumnEncryptionSetting columnEncryptionSetting) + TdsParserStateObject stateObj, + out SqlReturnValue returnValue, + SqlCommandColumnEncryptionSetting columnEncryptionSetting) { TdsOperationStatus result; returnValue = null; @@ -4805,17 +4778,17 @@ internal void DrainData(TdsParserStateObject stateObj) throw; } } - catch (System.OutOfMemoryException) + catch (OutOfMemoryException) { _connHandler.DoomThisConnection(); throw; } - catch (System.StackOverflowException) + catch (StackOverflowException) { _connHandler.DoomThisConnection(); throw; } - catch (System.Threading.ThreadAbortException) + catch (ThreadAbortException) { _connHandler.DoomThisConnection(); throw; @@ -5160,10 +5133,7 @@ internal TdsOperationStatus TryProcessMetaData(int cColumns, TdsParserStateObjec return TdsOperationStatus.Done; } - private bool IsVarTimeTds(byte tdsType) - { - return tdsType == TdsEnums.SQLTIME || tdsType == TdsEnums.SQLDATETIME2 || tdsType == TdsEnums.SQLDATETIMEOFFSET; - } + private bool IsVarTimeTds(byte tdsType) => tdsType == TdsEnums.SQLTIME || tdsType == TdsEnums.SQLDATETIME2 || tdsType == TdsEnums.SQLDATETIMEOFFSET; private TdsOperationStatus TryProcessTypeInfo(TdsParserStateObject stateObj, SqlMetaDataPriv col, UInt32 userType) { @@ -5198,7 +5168,7 @@ private TdsOperationStatus TryProcessTypeInfo(TdsParserStateObject stateObj, Sql if (TdsEnums.SQLUDT == tdsType) { - result = TryProcessUDTMetaData((SqlMetaDataPriv)col, stateObj); + result = TryProcessUDTMetaData(col, stateObj); if (result != TdsOperationStatus.Done) { return result; @@ -5215,7 +5185,7 @@ private TdsOperationStatus TryProcessTypeInfo(TdsParserStateObject stateObj, Sql "Invalid streaming datatype"); col.metaType = MetaType.GetMaxMetaTypeFromMetaType(col.metaType); Debug.Assert(col.metaType.IsLong, "Max datatype not IsLong"); - col.length = Int32.MaxValue; + col.length = int.MaxValue; if (tdsType == TdsEnums.SQLXMLTYPE) { byte schemapresent; @@ -5389,6 +5359,7 @@ private TdsOperationStatus TryCommonProcessMetaData(TdsParserStateObject stateOb } col.IsColumnSet = (TdsEnums.IsColumnSet == (flags & TdsEnums.IsColumnSet)); + if (fColMD && IsColumnEncryptionSupported) { col.isEncrypted = (TdsEnums.IsEncrypted == (flags & TdsEnums.IsEncrypted)); @@ -5524,7 +5495,7 @@ private TdsOperationStatus TryProcessUDTMetaData(SqlMetaDataPriv metaData, TdsPa } private void WriteUDTMetaData(object value, string database, string schema, string type, - TdsParserStateObject stateObj) + TdsParserStateObject stateObj) { // database if (string.IsNullOrEmpty(database)) @@ -5705,6 +5676,7 @@ private TdsOperationStatus TryProcessColInfo(_SqlMetaDataSet columns, SqlDataRea { return result; } + result = stateObj.TryReadByte(out col.tableNum); if (result != TdsOperationStatus.Done) { @@ -5911,9 +5883,9 @@ private TdsOperationStatus TryProcessRow(_SqlMetaDataSet columns, object[] buffe // We only read up to 2Gb. Throw if data is larger. Very large data // should be read in chunks in sequential read mode // For Plp columns, we may have gotten only the length of the first chunk - result = TryReadSqlValue(data, md, md.metaType.IsPlp ? (Int32.MaxValue) : (int)len, stateObj, - SqlCommandColumnEncryptionSetting.Disabled /*Column Encryption Disabled for Bulk Copy*/, - md.column); + result = TryReadSqlValue(data, md, md.metaType.IsPlp ? (int.MaxValue) : (int)len, stateObj, + SqlCommandColumnEncryptionSetting.Disabled /*Column Encryption Disabled for Bulk Copy*/, + md.column); if (result != TdsOperationStatus.Done) { return result; @@ -5934,10 +5906,8 @@ private TdsOperationStatus TryProcessRow(_SqlMetaDataSet columns, object[] buffe /// Determines if a column value should be transparently decrypted (based on SqlCommand and Connection String settings). /// /// true if the value should be transparently decrypted, false otherwise - internal static bool ShouldHonorTceForRead(SqlCommandColumnEncryptionSetting columnEncryptionSetting, - SqlInternalConnectionTds connection) + internal static bool ShouldHonorTceForRead(SqlCommandColumnEncryptionSetting columnEncryptionSetting, SqlInternalConnectionTds connection) { - // Command leve setting trumps all switch (columnEncryptionSetting) { @@ -5951,16 +5921,15 @@ internal static bool ShouldHonorTceForRead(SqlCommandColumnEncryptionSetting col // Check connection level setting! Debug.Assert(SqlCommandColumnEncryptionSetting.UseConnectionSetting == columnEncryptionSetting, "Unexpected value for command level override"); - return (connection != null && connection.ConnectionOptions != null && - connection.ConnectionOptions.ColumnEncryptionSetting == SqlConnectionColumnEncryptionSetting.Enabled); + return (connection != null && connection.ConnectionOptions != null + && connection.ConnectionOptions.ColumnEncryptionSetting == SqlConnectionColumnEncryptionSetting.Enabled); } } - internal static object GetNullSqlValue( - SqlBuffer nullVal, - SqlMetaDataPriv md, - SqlCommandColumnEncryptionSetting columnEncryptionSetting, - SqlInternalConnectionTds connection) + internal static object GetNullSqlValue(SqlBuffer nullVal, + SqlMetaDataPriv md, + SqlCommandColumnEncryptionSetting columnEncryptionSetting, + SqlInternalConnectionTds connection) { SqlDbType type = md.type; @@ -6556,12 +6525,12 @@ internal bool DeserializeUnencryptedValue(SqlBuffer value, byte[] unencryptedByt } internal TdsOperationStatus TryReadSqlValue(SqlBuffer value, - SqlMetaDataPriv md, - int length, - TdsParserStateObject stateObj, - SqlCommandColumnEncryptionSetting columnEncryptionOverride, - string columnName, - SqlCommand command = null) + SqlMetaDataPriv md, + int length, + TdsParserStateObject stateObj, + SqlCommandColumnEncryptionSetting columnEncryptionOverride, + string columnName, + SqlCommand command = null) { bool isPlp = md.metaType.IsPlp; byte tdsType = md.tdsType; @@ -6616,8 +6585,8 @@ internal TdsOperationStatus TryReadSqlValue(SqlBuffer value, } if (md.isEncrypted - && ((columnEncryptionOverride == SqlCommandColumnEncryptionSetting.Enabled - || columnEncryptionOverride == SqlCommandColumnEncryptionSetting.ResultSetOnly) + && (columnEncryptionOverride == SqlCommandColumnEncryptionSetting.Enabled + || columnEncryptionOverride == SqlCommandColumnEncryptionSetting.ResultSetOnly || (columnEncryptionOverride == SqlCommandColumnEncryptionSetting.UseConnectionSetting && _connHandler != null && _connHandler.ConnectionOptions != null && _connHandler.ConnectionOptions.ColumnEncryptionSetting == SqlConnectionColumnEncryptionSetting.Enabled))) @@ -6672,7 +6641,7 @@ internal TdsOperationStatus TryReadSqlValue(SqlBuffer value, } else { - value.SqlBinary = SqlTypeWorkarounds.SqlBinaryCtor(b, true); // doesn't copy the byte array + value.SqlBinary = SqlTypeWorkarounds.SqlBinaryCtor(b, true); // doesn't copy the byte array } break; @@ -7036,7 +7005,7 @@ internal TdsOperationStatus TryReadSqlValueInternal(SqlBuffer value, byte tdsTyp { return result; } - value.SqlBinary = SqlTypeWorkarounds.SqlBinaryCtor(b, true); // doesn't copy the byte array + value.SqlBinary = SqlTypeWorkarounds.SqlBinaryCtor(b, true); // doesn't copy the byte array break; } @@ -7892,7 +7861,7 @@ internal static SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale) internal static decimal AdjustDecimalScale(decimal value, int newScale) { - int oldScale = (Decimal.GetBits(value)[3] & 0x00ff0000) >> 0x10; + int oldScale = (decimal.GetBits(value)[3] & 0x00ff0000) >> 0x10; if (newScale != oldScale) { @@ -8137,12 +8106,12 @@ internal Task WriteString(string s, int length, int offset, TdsParserStateObject } - private unsafe static void CopyCharsToBytes(char[] source, int sourceOffset, byte[] dest, int destOffset, int charLength) + private static void CopyCharsToBytes(char[] source, int sourceOffset, byte[] dest, int destOffset, int charLength) { Buffer.BlockCopy(source, sourceOffset, dest, destOffset, charLength * ADP.CharSize); } - private unsafe static void CopyStringToBytes(string source, int sourceOffset, byte[] dest, int destOffset, int charLength) + private static void CopyStringToBytes(string source, int sourceOffset, byte[] dest, int destOffset, int charLength) { Encoding.Unicode.GetBytes(source, sourceOffset, charLength, dest, destOffset); } @@ -8648,7 +8617,7 @@ internal int WriteFedAuthFeatureRequest(FederatedAuthenticationFeatureExtensionD if (write) { - // Write Feature ID, legth of the version# field and Sensitivity Classification Version# + // Write Feature ID, length of the version# field and Sensitivity Classification Version# _physicalStateObj.WriteByte(TdsEnums.FEATUREEXT_DATACLASSIFICATION); WriteInt(1, _physicalStateObj); _physicalStateObj.WriteByte(TdsEnums.DATA_CLASSIFICATION_VERSION_MAX_SUPPORTED); @@ -8659,11 +8628,11 @@ internal int WriteFedAuthFeatureRequest(FederatedAuthenticationFeatureExtensionD internal int WriteTceFeatureRequest(bool write /* if false just calculates the length */) { - int len = 6; // (1byte = featureID, 4bytes = featureData length, 1 bytes = Version + int len = 6; // 1byte = featureID, 4bytes = featureData length, 1 bytes = Version if (write) { - // Write Feature ID, legth of the version# field and TCE Version# + // Write Feature ID, length of the version# field and TCE Version# _physicalStateObj.WriteByte(TdsEnums.FEATUREEXT_TCE); WriteInt(1, _physicalStateObj); _physicalStateObj.WriteByte(TdsEnums.MAX_SUPPORTED_TCE_VERSION); @@ -8696,9 +8665,9 @@ internal int WriteFedAuthFeatureRequest(FederatedAuthenticationFeatureExtensionD _physicalStateObj.WriteByte(TdsEnums.FEATUREEXT_AZURESQLSUPPORT); // Feature Data length - WriteInt(s_FeatureExtDataAzureSQLSupportFeatureRequest.Length, _physicalStateObj); + WriteInt(s_featureExtDataAzureSQLSupportFeatureRequest.Length, _physicalStateObj); - _physicalStateObj.WriteByteArray(s_FeatureExtDataAzureSQLSupportFeatureRequest, s_FeatureExtDataAzureSQLSupportFeatureRequest.Length, 0); + _physicalStateObj.WriteByteArray(s_featureExtDataAzureSQLSupportFeatureRequest, s_featureExtDataAzureSQLSupportFeatureRequest.Length, 0); } return len; @@ -9365,7 +9334,6 @@ internal SqlDataReader TdsExecuteTransactionManagerRequest( } catch (Exception e) { - // UNDONE - should not be catching all exceptions!!! if (!ADP.IsCatchableExceptionType(e)) { throw; @@ -9423,7 +9391,7 @@ internal void FailureCleanup(TdsParserStateObject stateObj, Exception e) } finally { - // Reset the ThreadHasParserLock value incase our caller expects it to be set\not set + // Reset the ThreadHasParserLock value in case our caller expects it to be set\not set _connHandler.ThreadHasParserLockForClose = originalThreadHasParserLock; } } @@ -9538,7 +9506,6 @@ internal Task TdsExecuteSQLBatch(string text, int timeout, SqlNotificationReques } catch (Exception e) { - //Debug.Assert(_state == TdsParserState.Broken, "Caught exception in TdsExecuteSQLBatch but connection was not broken!"); // UNDONE - should not be catching all exceptions!!! if (!ADP.IsCatchableExceptionType(e)) { @@ -9929,7 +9896,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout maxsize = 1; } - WriteParameterVarLen(mt, maxsize, false/*IsNull*/, stateObj); + WriteParameterVarLen(mt, maxsize, false /*IsNull*/, stateObj); } } else @@ -9947,11 +9914,10 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout } else if (mt.SqlDbType == SqlDbType.Udt) { + int maxSupportedSize = Is2008OrNewer ? int.MaxValue : short.MaxValue; byte[] udtVal = null; Format format = Format.Native; - int maxSupportedSize = Is2008OrNewer ? int.MaxValue : short.MaxValue; - if (!isNull) { // When writing UDT parameter values to the TDS stream, allow sending byte[] or SqlBytes @@ -9985,7 +9951,6 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout Debug.Assert(udtVal != null, "GetBytes returned null instance. Make sure that it always returns non-null value"); size = udtVal.Length; - //it may be legitimate, but we dont support it yet if (size < 0 || (size >= maxSupportedSize && maxsize != -1)) { throw SQL.UDTInvalidSize(maxsize, maxSupportedSize); @@ -10016,10 +9981,10 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout WriteUnsignedLong((ulong)udtVal.Length, stateObj); // PLP length if (udtVal.Length > 0) { // Only write chunk length if its value is greater than 0 - WriteInt(udtVal.Length, stateObj); // Chunk length + WriteInt(udtVal.Length, stateObj); // Chunk length stateObj.WriteByteArray(udtVal, udtVal.Length, 0); // Value } - WriteInt(0, stateObj); // Terminator + WriteInt(0, stateObj); // Terminator } else { @@ -10045,7 +10010,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, IList<_SqlRPC> rpcArray, int timeout maxsize = 1; } - WriteParameterVarLen(mt, maxsize, false/*IsNull*/, stateObj); + WriteParameterVarLen(mt, maxsize, false /*IsNull*/, stateObj); } } @@ -10300,17 +10265,17 @@ private void TdsExecuteRPC_OnFailure(Exception exc, TdsParserStateObject stateOb { FailureCleanup(stateObj, exc); } - catch (System.OutOfMemoryException) + catch (OutOfMemoryException) { _connHandler.DoomThisConnection(); throw; } - catch (System.StackOverflowException) + catch (StackOverflowException) { _connHandler.DoomThisConnection(); throw; } - catch (System.Threading.ThreadAbortException) + catch (ThreadAbortException) { _connHandler.DoomThisConnection(); throw; @@ -10325,24 +10290,25 @@ private void ExecuteFlushTaskCallback(Task tsk, TdsParserStateObject stateObj, T if (tsk.Exception != null) { Exception exc = tsk.Exception.InnerException; + RuntimeHelpers.PrepareConstrainedRegions(); try { FailureCleanup(stateObj, tsk.Exception); } - catch (System.OutOfMemoryException e) + catch (OutOfMemoryException e) { _connHandler.DoomThisConnection(); completion.SetException(e); throw; } - catch (System.StackOverflowException e) + catch (StackOverflowException e) { _connHandler.DoomThisConnection(); completion.SetException(e); throw; } - catch (System.Threading.ThreadAbortException e) + catch (ThreadAbortException e) { _connHandler.DoomThisConnection(); completion.SetException(e); @@ -10451,7 +10417,7 @@ private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefa { value = param.GetCoercedValue(); typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - metaData.SqlDbType, metaData.IsMultiValued, value, null, SmiContextFactory.Sql2008Version); + metaData.SqlDbType, metaData.IsMultiValued, value, null, SmiContextFactory.Sql2008Version); } var sendDefaultValue = sendDefault ? 1 : 0; @@ -11007,8 +10973,8 @@ internal void WriteBulkCopyMetaData(_SqlMetaDataSet metadataCollection, int coun // Write the flags ushort flags; flags = (ushort)(md.Updatability << 2); - flags |= (ushort)(md.IsNullable ? (ushort)TdsEnums.Nullable : (ushort)0); - flags |= (ushort)(md.IsIdentity ? (ushort)TdsEnums.Identity : (ushort)0); + flags |= md.IsNullable ? TdsEnums.Nullable : (ushort)0; + flags |= md.IsIdentity ? TdsEnums.Identity : (ushort)0; // Write the next byte of flags if (IsColumnEncryptionSupported) @@ -11019,7 +10985,7 @@ internal void WriteBulkCopyMetaData(_SqlMetaDataSet metadataCollection, int coun } } - WriteShort(flags, stateObj);// write the flags + WriteShort(flags, stateObj); // write the flags // todo: // for xml WriteTokenLength results in a no-op @@ -11819,6 +11785,7 @@ private Task WriteUnterminatedSqlValue(object value, MetaType type, int actualLe if (value is SqlChars) { string sch = new string(((SqlChars)value).Value); + return WriteEncodingChar(sch, actualLength, offset, _defaultEncoding, stateObj, canAccumulate: false); } else @@ -12028,17 +11995,17 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return task ?? Task.CompletedTask; } - catch (System.OutOfMemoryException) + catch (OutOfMemoryException) { _parser._connHandler.DoomThisConnection(); throw; } - catch (System.StackOverflowException) + catch (StackOverflowException) { _parser._connHandler.DoomThisConnection(); throw; } - catch (System.Threading.ThreadAbortException) + catch (ThreadAbortException) { _parser._connHandler.DoomThisConnection(); throw; @@ -12208,7 +12175,7 @@ private async Task WriteXmlFeed(XmlDataFeed feed, TdsParserStateObject stateObj, ConstrainedTextWriter writer = new ConstrainedTextWriter(new StreamWriter(new TdsOutputStream(this, stateObj, preambleToSkip), encoding), size); XmlWriterSettings writerSettings = new XmlWriterSettings(); - writerSettings.CloseOutput = false; // don't close the memory stream + writerSettings.CloseOutput = false; // don't close the memory stream writerSettings.ConformanceLevel = ConformanceLevel.Fragment; if (_asyncWrite) { @@ -13371,12 +13338,12 @@ bool writeDataSizeToSnapshot // Special case single byte if ( - (stateObj._longlenleft == 1 || partialReadInProgress ) + (stateObj._longlenleft == 1 || partialReadInProgress) && (charsLeft > 0) ) { - byte b1=0; - byte b2=0; + byte b1 = 0; + byte b2 = 0; if (partialReadInProgress) { partialReadInProgress = false;