Skip to content

Commit 1af7327

Browse files
Fix rare multi-packet string corruption (#3505) (#3513)
* add test and simplify code to fix problems * review feedback * review feedback * review feedback Co-authored-by: Wraith <[email protected]>
1 parent b5e036a commit 1af7327

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
@@ -13085,11 +13085,10 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1308513085

1308613086
if (canContinue)
1308713087
{
13088-
if (isContinuing || isStarting)
13089-
{
13090-
temp = stateObj.TryTakeSnapshotStorage() as char[];
13091-
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");
13092-
}
13088+
temp = stateObj.TryTakeSnapshotStorage() as char[];
13089+
Debug.Assert(temp != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
13090+
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");
13091+
1309313092
if (temp != null)
1309413093
{
1309513094
startOffset = stateObj.GetSnapshotTotalSize();
@@ -13105,7 +13104,7 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1310513104
supportRentedBuff: !canContinue, // do not use the arraypool if we are going to keep the buffer in the snapshot
1310613105
rentedBuff: ref buffIsRented,
1310713106
startOffset,
13108-
isStarting || isContinuing
13107+
canContinue
1310913108
);
1311013109

1311113110
if (result == TdsOperationStatus.Done)
@@ -13132,7 +13131,7 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1313213131
}
1313313132
else if (result == TdsOperationStatus.NeedMoreData)
1313413133
{
13135-
if (isStarting || isContinuing)
13134+
if (canContinue)
1313613135
{
1313713136
stateObj.SetSnapshotStorage(temp);
1313813137
}

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
@@ -13266,11 +13266,10 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1326613266

1326713267
if (canContinue)
1326813268
{
13269-
if (isContinuing || isStarting)
13270-
{
13271-
temp = stateObj.TryTakeSnapshotStorage() as char[];
13272-
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");
13273-
}
13269+
temp = stateObj.TryTakeSnapshotStorage() as char[];
13270+
Debug.Assert(temp != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
13271+
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");
13272+
1327413273
if (temp != null)
1327513274
{
1327613275
startOffset = stateObj.GetSnapshotTotalSize();
@@ -13285,8 +13284,8 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1328513284
out length,
1328613285
supportRentedBuff: !canContinue, // do not use the arraypool if we are going to keep the buffer in the snapshot
1328713286
rentedBuff: ref buffIsRented,
13288-
startOffset,
13289-
isStarting || isContinuing
13287+
startOffset,
13288+
canContinue
1329013289
);
1329113290

1329213291
if (result == TdsOperationStatus.Done)
@@ -13313,7 +13312,7 @@ internal TdsOperationStatus TryReadPlpUnicodeCharsWithContinue(TdsParserStateObj
1331313312
}
1331413313
else if (result == TdsOperationStatus.NeedMoreData)
1331513314
{
13316-
if (isStarting || isContinuing)
13315+
if (canContinue)
1331713316
{
1331813317
stateObj.SetSnapshotStorage(temp);
1331913318
}

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,11 +1527,10 @@ public TdsOperationStatus TryReadByteArrayWithContinue(int length, out byte[] by
15271527
(bool canContinue, bool isStarting, bool isContinuing) = GetSnapshotStatuses();
15281528
if (canContinue)
15291529
{
1530-
if (isContinuing || isStarting)
1531-
{
1532-
temp = TryTakeSnapshotStorage() as byte[];
1533-
Debug.Assert(bytes == null || bytes.Length == length, "stored buffer length must be null or must have been created with the correct length");
1534-
}
1530+
temp = TryTakeSnapshotStorage() as byte[];
1531+
Debug.Assert(temp != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
1532+
Debug.Assert(bytes == null || bytes.Length == length, "stored buffer length must be null or must have been created with the correct length");
1533+
15351534
if (temp != null)
15361535
{
15371536
offset = GetSnapshotTotalSize();
@@ -1552,7 +1551,7 @@ public TdsOperationStatus TryReadByteArrayWithContinue(int length, out byte[] by
15521551
}
15531552
else if (result == TdsOperationStatus.NeedMoreData)
15541553
{
1555-
if (isStarting || isContinuing)
1554+
if (canContinue)
15561555
{
15571556
SetSnapshotStorage(temp);
15581557
}
@@ -1981,11 +1980,10 @@ internal TdsOperationStatus TryReadStringWithEncoding(int length, System.Text.En
19811980
int startOffset = 0;
19821981
if (canContinue)
19831982
{
1984-
if (isContinuing || isStarting)
1985-
{
1986-
buf = TryTakeSnapshotStorage() as byte[];
1987-
Debug.Assert(buf == null || buf.Length == length, "stored buffer length must be null or must have been created with the correct length");
1988-
}
1983+
buf = TryTakeSnapshotStorage() as byte[];
1984+
Debug.Assert(buf != null || !isContinuing, "if continuing stored buffer must be present to contain previous data to continue from");
1985+
Debug.Assert(buf == null || buf.Length == length, "stored buffer length must be null or must have been created with the correct length");
1986+
19891987
if (buf != null)
19901988
{
19911989
startOffset = GetSnapshotTotalSize();
@@ -2003,7 +2001,7 @@ internal TdsOperationStatus TryReadStringWithEncoding(int length, System.Text.En
20032001
{
20042002
if (result == TdsOperationStatus.NeedMoreData)
20052003
{
2006-
if (isStarting || isContinuing)
2004+
if (canContinue)
20072005
{
20082006
SetSnapshotStorage(buf);
20092007
}

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)