Repository navigation
[6.1.9 Cherry-pick] Validate PRELOGIN option offsets before reading option data - #4979
Open
github-actions[bot] wants to merge 2 commits into
Open
github-actions[bot] wants to merge 2 commits into
github-actions[bot] wants to merge 2 commits into
Conversation
To resolve, run: git cherry-pick ff241b6
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
* Validate PRELOGIN option offsets before reading option data ConsumePreLoginHandshake read the VERSION, ENCRYPT, INSTANCE, MARS and FEDAUTHREQUIRED option headers and data without checking that they lie within the received PRELOGIN response. A malformed response could cause an IndexOutOfRangeException to escape from SqlConnection.Open/OpenAsync. Read each option header through a helper that verifies the 4-byte header and the option data it points to are within the response, and report a CorruptedTdsStream parsing error otherwise. Responses that were previously accepted are unaffected. Add simulated-server tests covering out-of-range offsets, data truncated at the end of the response, and truncated option headers for each option, on both sync and async open paths, plus a well-formed control. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7ef2b899-d3ce-43cc-91d5-a321d447d1d4 * Validate declared PRELOGIN option lengths and all option headers Options the client reads must declare exactly their defined data length (VERSION 6 bytes; ENCRYPT, INSTANCE, MARS and FEDAUTHREQUIRED 1 byte), so a short option can no longer be read together with the bytes of the option that follows it. Every other option header (THREADID, TRACEID, unknown options and ENCRYPT under TDS 8) is now validated as well: the header and the declared data must lie within the response. Rename the helper parameter to expectedBytes and add tests for length mismatches, a short option overlapping the next option's data, and bounds violations in options the client does not read. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7ef2b899-d3ce-43cc-91d5-a321d447d1d4 * Validate PRELOGIN total size and simplify option header parsing - Read and validate each option header once, before dispatching on the option, using ReadPreLoginOptionHeader, which returns the data offset and length instead of advancing a ref offset. - Treat THREADID, TRACEID and unrecognized options in a single branch that skips the option after its header is validated; drop Debug.Fail. - Require the option tokens, headers, data and terminator to describe exactly the bytes of the response, rejecting undescribed bytes, data claimed by more than one option without a gap, and a missing terminator. - Make the test TDS server write ENCRYPT and TRACEID data only when it writes the matching option header. - Add tests for unknown options and for the total-size check. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7ef2b899-d3ce-43cc-91d5-a321d447d1d4 --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7ef2b899-d3ce-43cc-91d5-a321d447d1d4 (cherry picked from commit ff241b6)
priyankatiwari08
marked this pull request as ready for review
November 10, 2026 16:24
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The PRELOGIN response-validation backport has no active review issues.
No open issues 🎉
What changed in this PR
Backports #4902 to release 6.1.9, adding PRELOGIN response validation to SqlClient’s shared parser so invalid option bounds produce parsing errors rather than out-of-range reads during connection opening.
Changes:
- Consolidates PRELOGIN parsing across .NET and .NET Framework while preserving platform-specific encryption behavior.
- Validates option headers, data bounds, required lengths, terminators, and total response size.
- Adds 85 regression cases and corrects simulated-server serialization of optional ENCRYPT and TRACEID data.
| File | Description |
|---|---|
src/Microsoft.Data.SqlClient/tests/UnitTests/SimulatedServerTests/PreLoginOptionBoundsTests.cs |
Adds malformed-response tests and valid controls for synchronous and asynchronous opens. |
src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS/PreLogin/TDSPreLoginToken.cs |
Emits ENCRYPT and TRACEID data only when their headers are present. |
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Parser/TdsParser.cs |
Adds shared PRELOGIN parsing with bounds, length, and response-size validation. |
src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Parser/TdsParser.cs |
Removes the duplicated .NET Framework handshake parser in favor of the shared implementation. |
src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Parser/TdsParser.cs |
Removes the duplicated .NET handshake parser in favor of the shared implementation. |
Review effort: Balanced
priyankatiwari08
previously approved these changes
Nov 10, 2026
priyankatiwari08
dismissed
their stale review
November 10, 2026 16:56
Approval withdrawn at the reviewer's request.
paulmedynski
approved these changes
Nov 11, 2026
paulmedynski
enabled auto-merge (squash)
November 11, 2026 14:03
Contributor
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 3 pipeline(s) were filtered out due to trigger conditions. |
benrr101
approved these changes
Nov 11, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Backports #4902 (ff241b6) to
release/6.1for 6.1.9. The cherry-pick conflicts are resolved in commit 0a14f2c.Validates every PRELOGIN option header and its declared data bounds before reading option data. Options read by the client must declare their protocol-defined lengths, and the options plus terminator must describe exactly the response size. Malformed responses now report
CorruptedTdsStreamparsing errors instead of allowing out-of-range reads duringSqlConnection.OpenorOpenAsync.Release-branch adaptations
ConsumePreLoginHandshakefrom the separate .NET and .NET Framework parsers into the existing shared parser, applying the fix to both targets without duplicating validation logic.EnableSslimplementations unchanged; main's unrelated TLS changes are not backported.OnPreLoginRequestCorehook and nullable-disabled test project.No public API or localization changes. Invalid PRELOGIN responses are intentionally rejected; well-formed responses retain existing behavior. No separate documentation changes are needed for this internal parser fix.
Suggested release note: Fixed
SqlConnection.Open/OpenAsyncthrowingIndexOutOfRangeExceptionwhen a server's PRELOGIN response contains invalid option offsets or lengths.Issues
Cherry-pick of #4902 into
release/6.1for 6.1.9.Testing
Includes all 85 original PRELOGIN regression cases covering sync/async open, malformed offsets, truncated headers/data, incorrect declared lengths, unread/unknown options, total-size mismatches, missing terminators, and well-formed controls.
Validation on the resolved backport:
dotnet test src\Microsoft.Data.SqlClient\tests\UnitTests\Microsoft.Data.SqlClient.UnitTests.csproj -f net8.0 -r win-x64 --no-build --filter "FullyQualifiedName~SimulatedServerTests" --blame-hang-timeout 10m --verbosity quiet --logger "console;verbosity=minimal"— Passed: 431, failed: 0, skipped: 0, including the 85 PRELOGIN cases.dotnet test src\Microsoft.Data.SqlClient\tests\UnitTests\Microsoft.Data.SqlClient.UnitTests.csproj -f net462 --no-build --filter "FullyQualifiedName~PreLoginOptionBoundsTests" --blame-hang-timeout 10m --verbosity quiet --logger "console;verbosity=minimal"— Passed: 85, failed: 0, skipped: 0.git diff --cached --checkbefore committing — Passed.Build/test setup: initial compilation exposed the release-specific override and nullable-context differences, which were corrected. Both target builds then succeeded. Initial test runs failed before reaching PRELOGIN because native SNI DLLs were not copied to the test output. The restored SNI.runtime 6.0.3 Windows x64 DLL and the built .NET Framework SNI x64 DLL were staged into their respective ignored test-output directories, then the commands above passed. An attempted concurrent cross-framework build also produced an assets-file collision; final runs used the completed builds. No dependency or build configuration changes are included.
Live SQL Server/manual tests, .NET 9 tests, and the full unit suite were not run for this backport; CI remains pending.
Guidelines
Please review the contribution guidelines before submitting a pull request: