From d38d554e7ad3135dc985cddb672078befe2eb825 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 5 Dec 2019 23:43:47 +0000 Subject: [PATCH] Fix | Allow large UDT buffers (#340) --- .../src/Microsoft/Data/SqlClient/SqlUtil.cs | 6 ++ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 25 ++--- .../netcore/src/Resources/SR.Designer.cs | 91 ++++++++++--------- .../netcore/src/Resources/SR.resx | 7 +- 4 files changed, 74 insertions(+), 55 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs index 8454dc3c78..47a1401562 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs @@ -739,6 +739,12 @@ internal static Exception UDTInvalidSqlType(string typeName) { return ADP.Argument(System.SRHelper.GetString(SR.SQLUDT_InvalidSqlType, typeName)); } + + internal static Exception UDTInvalidSize(int maxSize, int maxSupportedSize) + { + throw ADP.ArgumentOutOfRange(System.SRHelper.GetString(SR.SQLUDT_InvalidSize, maxSize, maxSupportedSize)); + } + internal static Exception InvalidSqlDbTypeForConstructor(SqlDbType type) { return ADP.Argument(System.SRHelper.GetString(SR.SqlMetaData_InvalidSqlDbTypeForConstructorFormat, type.ToString())); 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 e530dacc6a..c331e19a95 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 @@ -8986,15 +8986,21 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo } else if (mt.SqlDbType == SqlDbType.Udt) { + Debug.Assert(_isYukon, "Invalid DataType UDT for non-Yukon or later server!"); + + int maxSupportedSize = IsKatmaiOrNewer ? int.MaxValue : short.MaxValue; byte[] udtVal = null; Format format = Format.Native; - Debug.Assert(_isYukon, "Invalid DataType UDT for non-Yukon or later server!"); + if (string.IsNullOrEmpty(param.UdtTypeName)) + { + throw SQL.MustSetUdtTypeNameForUdtParams(); + } if (!isNull) { // When writing UDT parameter values to the TDS stream, allow sending byte[] or SqlBytes - // directly to the server and not rejected as invalid. This allows users to handle + // directly to the server and not reject them as invalid. This allows users to handle // serialization and deserialization logic without having to have SqlClient be aware of // the types and without using inefficient text representations. if (value is byte[] rawBytes) @@ -9024,20 +9030,15 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo Debug.Assert(null != udtVal, "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 >= ushort.MaxValue && maxsize != -1)) - throw new IndexOutOfRangeException(); + if (size >= maxSupportedSize && maxsize != -1) + { + throw SQL.UDTInvalidSize(maxsize, maxSupportedSize); + } } - //if this is NULL value, write special null value - byte[] lenBytes = BitConverter.GetBytes((long)size); - - if (string.IsNullOrEmpty(param.UdtTypeName)) - throw SQL.MustSetUdtTypeNameForUdtParams(); - // Split the input name. TypeName is returned as single 3 part name during DeriveParameters. // NOTE: ParseUdtTypeName throws if format is incorrect - string[] names = SqlParameter.ParseTypeName(param.UdtTypeName, true /* is UdtTypeName */); + string[] names = SqlParameter.ParseTypeName(param.UdtTypeName, isUdtTypeName: true); if (!string.IsNullOrEmpty(names[0]) && TdsEnums.MAX_SERVERNAME < names[0].Length) { throw ADP.ArgumentOutOfRange(nameof(names)); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.Designer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.Designer.cs index f7a9088e44..f7d8a6286b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.Designer.cs @@ -10,8 +10,8 @@ namespace System { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -889,7 +889,7 @@ internal static string ArgumentOutOfRange_NeedNonNegNum { } /// - /// Looks up a localized string similar to The validation of an attestation token failed. The token signature does not match the signature omputed using a public key retrieved from the attestation public key endpoint at '{0}'. Verify the DNS apping for the endpoint. If correct, contact Customer Support Services.. + /// Looks up a localized string similar to The validation of an attestation token failed. The token signature does not match the signature computed using a public key retrieved from the attestation public key endpoint at '{0}'. Verify the DNS mapping for the endpoint. If correct, contact Customer Support Services.. /// internal static string AttestationTokenSignatureValidationFailed { get { @@ -3993,6 +3993,15 @@ internal static string SQLROR_UnexpectedRoutingInfo { } } + /// + /// Looks up a localized string similar to UDT size must be less than {1}, size: {0}. + /// + internal static string SQLUDT_InvalidSize { + get { + return ResourceManager.GetString("SQLUDT_InvalidSize", resourceCulture); + } + } + /// /// Looks up a localized string similar to Specified type is not registered on the target server. {0}.. /// @@ -4074,6 +4083,24 @@ internal static string TCE_AttestationInfoNotReturnedFromSQLServer { } } + /// + /// Looks up a localized string similar to Error occured when generating enclave package. Attestation Protocol has not been specified in the connection string, but the query requires enclave computations.. + /// + internal static string TCE_AttestationProtocolNotSpecifiedForGeneratingEnclavePackage { + get { + return ResourceManager.GetString("TCE_AttestationProtocolNotSpecifiedForGeneratingEnclavePackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to initialize connection. The attestation protocol '{0}' does not support the enclave type '{1}'.. + /// + internal static string TCE_AttestationProtocolNotSupportEnclaveType { + get { + return ResourceManager.GetString("TCE_AttestationProtocolNotSupportEnclaveType", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0} should be identical on all commands ({1}, {2}, {3}, {4}) when doing batch updates.. /// @@ -4182,6 +4209,15 @@ internal static string TCE_ColumnMasterKeySignatureVerificationFailed { } } + /// + /// Looks up a localized string similar to Specifies an attestation protocol for its corresponding enclave attestation service.. + /// + internal static string TCE_DbConnectionString_AttestationProtocol { + get { + return ResourceManager.GetString("TCE_DbConnectionString_AttestationProtocol", resourceCulture); + } + } + /// /// Looks up a localized string similar to Decryption failed. The last 10 bytes of the encrypted column encryption key are: '{0}'. The first 10 bytes of ciphertext are: '{1}'.. /// @@ -4336,50 +4372,14 @@ internal static string TCE_EnclaveComputationsNotSupported { } /// - /// Looks up a localized string similar to No enclave provider found for enclave type '{0}'. Please specify the provider in the application configuration.. + /// Looks up a localized string similar to No enclave provider found for enclave type '{0}' and attestation protocol '{1}'. Please specify the correct attestation protocol in the connection string.. /// internal static string TCE_EnclaveProviderNotFound { get { return ResourceManager.GetString("TCE_EnclaveProviderNotFound", resourceCulture); } } - - /// - /// Looks up a localized string similar to Specifies an attestation protocol for its corresponding enclave attestation service. - /// - internal static string TCE_DbConnectionString_AttestationProtocol { - get { - return ResourceManager.GetString("TCE_DbConnectionString_AttestationProtocol", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The enclave type '{0}' returned from the server is not supported. - /// - internal static string TCE_EnclaveTypeNotSupported { - get { - return ResourceManager.GetString("TCE_EnclaveTypeNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to initialize connection. The attestation protocol '{0}' does not support the enclave type '{1}'. - /// - internal static string TCE_AttestationProtocolNotSupportEnclaveType { - get { - return ResourceManager.GetString("TCE_AttestationProtocolNotSupportEnclaveType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Error occured when generating enclave package. Attestation Protocol has not been specified in the connection string, but the query requires enclave computations. - /// - internal static string TCE_AttestationProtocolNotSpecifiedForGeneratingEnclavePackage { - get { - return ResourceManager.GetString("TCE_AttestationProtocolNotSpecifiedForGeneratingEnclavePackage", resourceCulture); - } - } - + /// /// Looks up a localized string similar to Executing a query requires enclave computations, but the application configuration is missing the enclave provider section.. /// @@ -4398,6 +4398,15 @@ internal static string TCE_EnclaveTypeNotReturned { } } + /// + /// Looks up a localized string similar to The enclave type '{0}' returned from the server is not supported.. + /// + internal static string TCE_EnclaveTypeNotSupported { + get { + return ResourceManager.GetString("TCE_EnclaveTypeNotSupported", resourceCulture); + } + } + /// /// Looks up a localized string similar to Internal Error. Enclave type received from SQL Server is null or empty when executing a query requiring enclave computations.. /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.resx b/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.resx index f41b408e6a..78dd164819 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.resx +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/SR.resx @@ -167,7 +167,7 @@ The DataDirectory substitute is not a string. - + The {0} enumeration value, {1}, is invalid. @@ -1851,4 +1851,7 @@ Error occured when generating enclave package. Attestation Protocol has not been specified in the connection string, but the query requires enclave computations. - + + UDT size must be less than {1}, size: {0} + + \ No newline at end of file