Fix: Add buffer accumulation to TDSTLSFramer for Azure SQL Database#2
Fix: Add buffer accumulation to TDSTLSFramer for Azure SQL Database#2mklahn wants to merge 1 commit into
Conversation
- Add accumulator buffer to handle fragmented TCP packets - Fix connection reset errors with Azure SQL Database - Change TDS version from 8.0 to 7.4 for compatibility Fixes connection failures when TLS ServerHello exceeds TCP segment size. Tested against Azure SQL Database with successful queries. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughTDS Pre-Login handshake handling is improved by downgrading the client version from 8.0 to 7.4 for better Azure SQL compatibility, and the TLS framer now buffers incomplete packets across multiple channel reads instead of immediately stopping on partial frames. ChangesTDS Pre-Login and TLS Framer Improvements
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Sources/CosmoMSSQL/TDS/TDSTLSFramer.swift`:
- Around line 57-65: The guard that checks the TDS packet length (reading
lengthBE in TDSTLSFramer.swift) currently treats all failures as a partial read
by saving accumulatedBuffer; change it so that a lengthBE < 8 is treated as a
protocol error rather than buffering: if lengthBE < 8, do not assign
accumulatedBuffer, instead fail the pipeline/connection (emit/throw a protocol
error indicating "invalid TDS header length") and close the connection; only
keep the existing buffering logic for cases where Int(lengthBE) >
buf.readableBytes (genuine partial frames). Ensure you reference the same
variables (lengthBE, accumulatedBuffer, buf) and perform a clear error
emission/connection teardown in the TDSTLSFramer code path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c15cd75d-6490-449d-9682-432f12857138
📒 Files selected for processing (2)
Sources/CosmoMSSQL/TDS/TDSPreLogin.swiftSources/CosmoMSSQL/TDS/TDSTLSFramer.swift
| guard | ||
| let lengthBE: UInt16 = buf.getInteger(at: buf.readerIndex + 2, endianness: .big), | ||
| Int(lengthBE) <= buf.readableBytes, | ||
| Int(lengthBE) >= 8 | ||
| else { break } | ||
| else { | ||
| // Save remaining data for next read | ||
| accumulatedBuffer = buf | ||
| return | ||
| } |
There was a problem hiding this comment.
Handle invalid TDS header lengths as protocol errors, not partial frames.
Int(lengthBE) >= 8 is currently grouped with partial-read handling. For malformed headers (lengthBE < 8), this path keeps buffering forever and never advances, which can stall the connection and grow memory.
Suggested fix
while buf.readableBytes >= 8 {
- guard
- let lengthBE: UInt16 = buf.getInteger(at: buf.readerIndex + 2, endianness: .big),
- Int(lengthBE) <= buf.readableBytes,
- Int(lengthBE) >= 8
- else {
- // Save remaining data for next read
- accumulatedBuffer = buf
- return
- }
- let packetLen = Int(lengthBE)
+ guard let lengthBE: UInt16 = buf.getInteger(at: buf.readerIndex + 2, endianness: .big) else {
+ accumulatedBuffer = buf
+ return
+ }
+ let packetLen = Int(lengthBE)
+
+ // Invalid TDS frame length: fail fast instead of buffering forever.
+ guard packetLen >= 8 else {
+ accumulatedBuffer = nil
+ context.close(promise: nil)
+ return
+ }
+
+ // Incomplete frame: keep buffering until full packet arrives.
+ guard packetLen <= buf.readableBytes else {
+ accumulatedBuffer = buf
+ return
+ }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Sources/CosmoMSSQL/TDS/TDSTLSFramer.swift` around lines 57 - 65, The guard
that checks the TDS packet length (reading lengthBE in TDSTLSFramer.swift)
currently treats all failures as a partial read by saving accumulatedBuffer;
change it so that a lengthBE < 8 is treated as a protocol error rather than
buffering: if lengthBE < 8, do not assign accumulatedBuffer, instead fail the
pipeline/connection (emit/throw a protocol error indicating "invalid TDS header
length") and close the connection; only keep the existing buffering logic for
cases where Int(lengthBE) > buf.readableBytes (genuine partial frames). Ensure
you reference the same variables (lengthBE, accumulatedBuffer, buf) and perform
a clear error emission/connection teardown in the TDSTLSFramer code path.
Fixes connection failures when TLS ServerHello exceeds TCP segment size. Tested against Azure SQL Database with successful queries.
Summary by CodeRabbit