-
Notifications
You must be signed in to change notification settings - Fork 5.3k
fix buffer handling in Tls handshake #32267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| private interface ISslIOAdapter | ||
| { | ||
| ValueTask<int> ReadAsync(byte[] buffer, int offset, int count); | ||
| ValueTask<int> ReadAsync(Memory<byte> buffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need the ValueTask<int> ReadAsync(byte[] buffer, int offset, int count); overload?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used in FillBufferAsync() but that is easy to fix.
| if (!receiveFirst) | ||
| { | ||
| message = _context.NextMessage(reAuthenticationData, 0, (reAuthenticationData == null ? 0 : reAuthenticationData.Length)); | ||
| message = _context.NextMessage(reAuthenticationData == null ? default : new ReadOnlySpan<byte>(reAuthenticationData)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This conditional shouldn't be necessary, as a null array is converted to a default span by span's ctor/implicit cast/etc.
| message = _context.NextMessage(reAuthenticationData == null ? default : new ReadOnlySpan<byte>(reAuthenticationData)); | |
| message = _context.NextMessage(reAuthenticationData); |
| if (reAuthenticationData == null) | ||
| { | ||
| _nestedAuth = 0; | ||
| _handshakeBuffer.Dispose(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we need to dispose this if reAuthenticationData != null? Also, should we set _handshakeBuffer to default after it's been disposed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, we should. I missed that part.
| int version = -1; | ||
|
|
||
| if ((bytes == null || bytes.Length <= 0)) | ||
| if (bytes.Length <= 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll never be < 0.
| if (bytes.Length <= 0) | |
| if (bytes.Length == 0) |
This change primarily fixes a regression caused by #453. In an attempt to not allocate a new buffer for each message we start using _internalBuffer also for the handshake. That unfortunately caused #20507 and #1291
This change brings one buffer used through the entire handshake. The live cycle is managed within ForceAuthenticationAsync() used for both initial handshakes as well as possible renegotiation triggered by reading.
Since ArrayBuffer has convenient APIs, I decided to use it instead of implementing the logic again. This also allowed to complete spanification of SslStream where we have now clean path from ArrayBuffer all the way to native call on all platforms.
I was able to reproduce #1291 on my local systems in ~ 100 runs. So far I did several hundred with this change and I did not see any issue. (aside from flaky DNS)
This change also brings
FillHandshakeBufferAsync()very similar toFillBufferAsync.I think there is opportunity for more refactor but I would like to put out a fix for the failing tests to decrease CI noise for everybody.
fixes #1291
fixes #20507