Fixed a bug in websocket receive, when a compressed frame with no payload is received.#52621
Conversation
…rely marked as processed. Compressed frames should always go through inflation in order to make sure there is no lefover from previous receives.
|
Tagging subscribers to this area: @dotnet/ncl Issue DetailsThere are extremely rare cases where it is possible to receive an empty frame, part of compressed a message. If such a frame happened to be the last frame of the message, and there was lefover data available in the inflater, the receive One other condition for this case is that the receive buffer is small enough, so the inflate cannot flush everything to the user. This was caught by @BrennanConroy running Autobahn Testsuite with receive buffer 4096. The Testsuite sends such frames occasionally to make sure the implementation handles them correctly. Our internal implementation however cannot produce such frame. When sending an empty compressed frame, the resulting payload will always be 1 byte - a zero. This is why I couldn't write a unit test for this. The fix for this is to treat empty compressed frames as not processed, until inflation has been run. @BrennanConroy could you try and run your test server with this branch, please? Fixes #52551 //cc @CarnaViire
|
Can we produce a raw byte stream that simulates a WebSocket with such a frame? |
I see no reason why not. I will give it a go in a moment. |
|
Thanks for the suggestion @halter73! Created a test and verified that with the implementation before the fix, the test fails. |
|
All 12.* and 13.* autobahn tests pass now! |
There are extremely rare cases where it is possible to receive an empty frame, part of compressed a message.
If such a frame happened to be the last frame of the message, and there was leftover data available in the inflater, the receive
operation would ignore the data and think that there is nothing and return 0 bytes received to the user.
runtime/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs
Line 1249 in b306268
runtime/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs
Lines 810 to 817 in b306268
One other condition for this case is that the receive buffer is small enough, so the inflate cannot flush everything to the user. This was caught by @BrennanConroy running Autobahn Testsuite with receive buffer size of 4096. The Testsuite sends such frames occasionally to make sure the implementation handles them correctly.
Our internal implementation however cannot produce such frame. When sending an empty compressed frame, the resulting payload will always be 1 byte - a zero.
The fix for this is to treat empty compressed frames as not processed, until inflation has been run.
@BrennanConroy could you try and run your test server with this branch, please?
Fixes #52551
//cc @CarnaViire