Visitar URL original
[6.1.9 Cherry-pick] Validate PRELOGIN option offsets before reading option data by github-actions[bot] · Pull Request #4979 · dotnet/SqlClient · GitHub
Skip to content

[6.1.9 Cherry-pick] Validate PRELOGIN option offsets before reading option data - #4979

Open
github-actions[bot] wants to merge 2 commits into
release/6.1from
dev/automation/pr-4902-to-6.1.9
Open

github-actions[bot] wants to merge 2 commits into
release/6.1from
dev/automation/pr-4902-to-6.1.9

Conversation

@github-actions

@github-actions github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Description

Backports #4902 (ff241b6) to release/6.1 for 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 CorruptedTdsStream parsing errors instead of allowing out-of-range reads during SqlConnection.Open or OpenAsync.

Release-branch adaptations

  • Moves ConsumePreLoginHandshake from the separate .NET and .NET Framework parsers into the existing shared parser, applying the fix to both targets without duplicating validation logic.
  • Preserves the release branch's framework-specific encryption flags, negotiation behavior, and existing packet-size error handling. Leaves the platform-specific EnableSsl implementations unchanged; main's unrelated TLS changes are not backported.
  • Adapts the simulated-server override to this branch's OnPreLoginRequestCore hook and nullable-disabled test project.
  • Includes the original simulated TDS server correction so ENCRYPT and TRACEID data are emitted only when their option headers are present.

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/OpenAsync throwing IndexOutOfRangeException when a server's PRELOGIN response contains invalid option offsets or lengths.

Issues

Cherry-pick of #4902 into release/6.1 for 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 --check before 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.

  • Tests added or updated
  • Public API changes documented (no public API changes)
  • Verified against customer repro (not applicable; malformed responses covered by simulated-server tests)
  • Ensure no breaking changes introduced (well-formed responses retain existing behavior)

Guidelines

Please review the contribution guidelines before submitting a pull request:

To resolve, run:  git cherry-pick ff241b6
@github-actions github-actions Bot added this to the 6.1.9 milestone Nov 3, 2026
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Nov 3, 2026
@azure-pipelines

Copy link
Copy Markdown
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 priyankatiwari08 changed the title [6.1.9 Cherry-pick - CONFLICTS] Validate PRELOGIN option offsets before reading option data [6.1.9 Cherry-pick] Validate PRELOGIN option offsets before reading option data Nov 10, 2026
@priyankatiwari08
priyankatiwari08 marked this pull request as ready for review November 10, 2026 16:24
@priyankatiwari08
priyankatiwari08 requested a review from a team as a code owner November 10, 2026 16:24
Copilot AI balanced review requested due to automatic review settings November 10, 2026 16:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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
priyankatiwari08 dismissed their stale review November 10, 2026 16:56

Approval withdrawn at the reviewer's request.

@paulmedynski paulmedynski moved this from To triage to In review in SqlClient Board Nov 11, 2026
@paulmedynski
paulmedynski enabled auto-merge (squash) November 11, 2026 14:03
@paulmedynski

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).
3 pipeline(s) were filtered out due to trigger conditions.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

5 participants