Skip to content

Commit 63443f4

Browse files
authored
Fix rare multi-packet string corruption (#3505)
* add test and simplify code to fix problems * review feedback * review feedback * review feedback
1 parent 9744a8e commit 63443f4

File tree

4 files changed

+214
-27
lines changed

4 files changed

+214
-27
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13116,11 +13116,10 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1311613116

1311713117
if (canContinue)
1311813118
{
13119-
if (isContinuing || isStarting)
13120-
{
13121-
temp = stateObj.TryTakeSnapshotStorage() as char[];
13122-
Debug.Assert(temp == null || length == int.MaxValue || temp.Length == length, "stored buffer length must be null or must have been created with the correct length");
13123-
}
13119+
temp = stateObj.TryTakeSnapshotStorage() as char[];
13120+
Debug.Assert(temp != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
13121+
Debug.Assert(temp == null || length == int.MaxValue || temp.Length == length, "stored buffer length must be null or must have been created with the correct length");
13122+
1312413123
if (temp != null)
1312513124
{
1312613125
startOffset = stateObj.GetSnapshotTotalSize();
@@ -13136,7 +13135,7 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1313613135
supportRentedBuff: !canContinue, // do not use the arraypool if we are going to keep the buffer in the snapshot
1313713136
rentedBuff: ref buffIsRented,
1313813137
startOffset,
13139-
isStarting || isContinuing
13138+
canContinue
1314013139
);
1314113140

1314213141
if (result == TdsOperationStatus.Done)
@@ -13163,7 +13162,7 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1316313162
}
1316413163
else if (result == TdsOperationStatus.NeedMoreData)
1316513164
{
13166-
if (isStarting || isContinuing)
13165+
if (canContinue)
1316713166
{
1316813167
stateObj.SetSnapshotStorage(temp);
1316913168
}

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13306,11 +13306,10 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1330613306

1330713307
if (canContinue)
1330813308
{
13309-
if (isContinuing || isStarting)
13310-
{
13311-
temp = stateObj.TryTakeSnapshotStorage() as char[];
13312-
Debug.Assert(temp == null || length == int.MaxValue || temp.Length == length, "stored buffer length must be null or must have been created with the correct length");
13313-
}
13309+
temp = stateObj.TryTakeSnapshotStorage() as char[];
13310+
Debug.Assert(temp != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
13311+
Debug.Assert(temp == null || length == int.MaxValue || temp.Length == length, "stored buffer length must be null or must have been created with the correct length");
13312+
1331413313
if (temp != null)
1331513314
{
1331613315
startOffset = stateObj.GetSnapshotTotalSize();
@@ -13325,8 +13324,8 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1332513324
out length,
1332613325
supportRentedBuff: !canContinue, // do not use the arraypool if we are going to keep the buffer in the snapshot
1332713326
rentedBuff: ref buffIsRented,
13328-
startOffset,
13329-
isStarting || isContinuing
13327+
startOffset,
13328+
canContinue
1333013329
);
1333113330

1333213331
if (result == TdsOperationStatus.Done)
@@ -13353,7 +13352,7 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1335313352
}
1335413353
else if (result == TdsOperationStatus.NeedMoreData)
1335513354
{
13356-
if (isStarting || isContinuing)
13355+
if (canContinue)
1335713356
{
1335813357
stateObj.SetSnapshotStorage(temp);
1335913358
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,11 +1529,10 @@ public TdsOperationStatus TryReadByteArrayWithContinue(int length, out byte[] by
15291529
(bool canContinue, bool isStarting, bool isContinuing) = GetSnapshotStatuses();
15301530
if (canContinue)
15311531
{
1532-
if (isContinuing || isStarting)
1533-
{
1534-
temp = TryTakeSnapshotStorage() as byte[];
1535-
Debug.Assert(bytes == null || bytes.Length == length, "stored buffer length must be null or must have been created with the correct length");
1536-
}
1532+
temp = TryTakeSnapshotStorage() as byte[];
1533+
Debug.Assert(temp != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
1534+
Debug.Assert(bytes == null || bytes.Length == length, "stored buffer length must be null or must have been created with the correct length");
1535+
15371536
if (temp != null)
15381537
{
15391538
offset = GetSnapshotTotalSize();
@@ -1554,7 +1553,7 @@ public TdsOperationStatus TryReadByteArrayWithContinue(int length, out byte[] by
15541553
}
15551554
else if (result == TdsOperationStatus.NeedMoreData)
15561555
{
1557-
if (isStarting || isContinuing)
1556+
if (canContinue)
15581557
{
15591558
SetSnapshotStorage(temp);
15601559
}
@@ -1983,11 +1982,10 @@ internal TdsOperationStatus TryReadStringWithEncoding(int length, System.Text.En
19831982
int startOffset = 0;
19841983
if (canContinue)
19851984
{
1986-
if (isContinuing || isStarting)
1987-
{
1988-
buf = TryTakeSnapshotStorage() as byte[];
1989-
Debug.Assert(buf == null || buf.Length == length, "stored buffer length must be null or must have been created with the correct length");
1990-
}
1985+
buf = TryTakeSnapshotStorage() as byte[];
1986+
Debug.Assert(buf != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
1987+
Debug.Assert(buf == null || buf.Length == length, "stored buffer length must be null or must have been created with the correct length");
1988+
19911989
if (buf != null)
19921990
{
19931991
startOffset = GetSnapshotTotalSize();
@@ -2005,7 +2003,7 @@ internal TdsOperationStatus TryReadStringWithEncoding(int length, System.Text.En
20052003
{
20062004
if (result == TdsOperationStatus.NeedMoreData)
20072005
{
2008-
if (isStarting || isContinuing)
2006+
if (canContinue)
20092007
{
20102008
SetSnapshotStorage(buf);
20112009
}

src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs

Lines changed: 191 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)