Describe the bug
Suppose you are using IEnumerable<SqlDataRecord> as the value of a table-valued SqlParameter and re-using the same SqlDataRecord instance for each item. One of the fields is type VARBINARY(MAX), and you use the SetBytes method to copy data into the field. After the first call to SetBytes, a subsequent call that copies fewer bytes will write to the existing buffer without setting the field's length, causing the remaining stale buffered bytes from the first call to get copied to the server, too.
To reproduce
#!/usr/bin/env dotnet run
#:package Microsoft.Data.SqlClient@6.*
using Microsoft.Data.SqlClient.Server;
using System.Data;
using System.Data.SqlTypes;
using System.Text;
var columns = new SqlMetaData[]
{
new("Data", SqlDbType.VarBinary, SqlMetaData.Max),
};
var rec = new SqlDataRecord(columns);
var buffer = new byte[4096];
// write first record value
SetBytes(rec, 0, buffer, "Two Words");
ReadBytesToConsole(rec, 0, buffer); // writes "Two Words"
// write second record value
SetBytes(rec, 0, buffer, "One");
ReadBytesToConsole(rec, 0, buffer); // writes "One Words"
// write third record value using SqlBytes, which avoids the bug
var sqlBytes = new SqlBytes(Encoding.UTF8.GetBytes("Three"));
rec.SetSqlBytes(0, sqlBytes);
ReadBytesToConsole(rec, 0, buffer); // writes "Three"
static void SetBytes(SqlDataRecord rec, int ordinal, byte[] buffer, string value)
{
int length = Encoding.UTF8.GetBytes(value, buffer);
rec.SetBytes(ordinal, 0, buffer, 0, length);
}
static void ReadBytesToConsole(SqlDataRecord rec, int ordinal, byte[] buffer)
{
var length = rec.GetBytes(ordinal, 0, buffer, 0, buffer.Length);
var s = Encoding.UTF8.GetString(buffer, 0, int.CreateChecked(length));
Console.WriteLine(s);
}
Expected behavior
The program should output:
Further technical details
Microsoft.Data.SqlClient version: 6.1.4
.NET target: .NET 10.0
SQL Server version: N/A
Operating system: Windows 11 Pro 26200.7840
Describe the bug
Suppose you are using
IEnumerable<SqlDataRecord>as the value of a table-valuedSqlParameterand re-using the sameSqlDataRecordinstance for each item. One of the fields is typeVARBINARY(MAX), and you use theSetBytesmethod to copy data into the field. After the first call toSetBytes, a subsequent call that copies fewer bytes will write to the existing buffer without setting the field's length, causing the remaining stale buffered bytes from the first call to get copied to the server, too.To reproduce
Expected behavior
The program should output:
Further technical details
Microsoft.Data.SqlClient version: 6.1.4
.NET target: .NET 10.0
SQL Server version: N/A
Operating system: Windows 11 Pro 26200.7840