dotnet / dotnet/SqlClient

SqlDataRecord.SetBytes fails to set length, incorrectly preserving data from a previous call

Open
#3,957 7 comments 1 reaction 0 assignees View on GitHub
Dominant language
C#
Stars
989
Forks
340
Avg merge
4d 19h
Merged PRs (30d)
72

Description

### Describe the bug
Suppose you are using `IEnumerable` 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
```c#
#!/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:
```txt
Two Words
One
Three
```

### 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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.