@@ -150,6 +150,106 @@ defmodule WebSocketProtocolTest do
150150 expected_payload = String . duplicate ( payload , 3 )
151151 assert SimpleWebSocketClient . recv_binary_frame ( client ) == { :ok , expected_payload }
152152 end
153+
154+ test "zero byte fin continuation frames are accepted" , context do
155+ client = SimpleWebSocketClient . tcp_client ( context )
156+ SimpleWebSocketClient . http1_handshake ( client , EchoWebSock )
157+
158+ payload = String . duplicate ( "0123456789" , 1_000 )
159+ SimpleWebSocketClient . send_binary_frame ( client , payload , 0x0 )
160+ SimpleWebSocketClient . send_continuation_frame ( client , payload , 0x0 )
161+ SimpleWebSocketClient . send_continuation_frame ( client , << >> )
162+
163+ expected_payload = String . duplicate ( payload , 2 )
164+ assert SimpleWebSocketClient . recv_binary_frame ( client ) == { :ok , expected_payload }
165+ end
166+
167+ test "zero byte non-fin continuation frames are rejected" , context do
168+ output =
169+ capture_log ( fn ->
170+ client = SimpleWebSocketClient . tcp_client ( context )
171+ SimpleWebSocketClient . http1_handshake ( client , TerminateWebSock )
172+
173+ SimpleWebSocketClient . send_binary_frame ( client , "0123456789" , 0x0 )
174+ SimpleWebSocketClient . send_continuation_frame ( client , << >> , 0x0 )
175+
176+ # Get the error that terminate saw, to ensure we're closing for the expected reason
177+ assert_receive { :error , "Received zero byte non-fin continuation frame" } , 500
178+
179+ assert SimpleWebSocketClient . recv_connection_close_frame ( client ) == { :ok , << 1008 :: 16 >> }
180+
181+ # Verify that the server didn't send any extraneous frames
182+ assert SimpleWebSocketClient . connection_closed_for_reading? ( client )
183+ Process . sleep ( 500 )
184+ end )
185+
186+ assert output =~ "Received zero byte non-fin continuation frame"
187+ end
188+
189+ test "max_fragmented_message_size enforced for continuation frames" , context do
190+ output =
191+ capture_log ( fn ->
192+ context =
193+ http_server ( context , websocket_options: [ max_fragmented_message_size: 2_000_000 ] )
194+
195+ client = SimpleWebSocketClient . tcp_client ( context )
196+ SimpleWebSocketClient . http1_handshake ( client , TerminateWebSock )
197+
198+ payload = String . duplicate ( "0123456789" , 99_999 )
199+ SimpleWebSocketClient . send_binary_frame ( client , payload , 0x0 )
200+ SimpleWebSocketClient . send_continuation_frame ( client , payload , 0x0 )
201+
202+ # We should still be alive here
203+ refute_receive { :error , "Received oversize fragmented message" } , 50
204+
205+ # This should send us over the edge
206+ SimpleWebSocketClient . send_continuation_frame ( client , payload , 0x0 )
207+
208+ # Get the error that terminate saw, to ensure we're closing for the expected reason
209+ assert_receive { :error , "Received oversize fragmented message" } , 500
210+
211+ assert SimpleWebSocketClient . recv_connection_close_frame ( client ) == { :ok , << 1009 :: 16 >> }
212+
213+ # Verify that the server didn't send any extraneous frames
214+ assert SimpleWebSocketClient . connection_closed_for_reading? ( client )
215+ Process . sleep ( 500 )
216+ end )
217+
218+ assert output =~ "Received oversize fragmented message"
219+ end
220+
221+ test "max_fragmented_message_size enforced for continuation fin frames" , context do
222+ output =
223+ capture_log ( fn ->
224+ context =
225+ http_server ( context , websocket_options: [ max_fragmented_message_size: 2_000_000 ] )
226+
227+ client = SimpleWebSocketClient . tcp_client ( context )
228+ SimpleWebSocketClient . http1_handshake ( client , TerminateWebSock )
229+
230+ payload = String . duplicate ( "0123456789" , 99_999 )
231+ SimpleWebSocketClient . send_binary_frame ( client , payload , 0x0 )
232+
233+ SimpleWebSocketClient . send_continuation_frame ( client , payload , 0x0 )
234+
235+ # We should still be alive here
236+ refute_receive { :error , "Received oversize fragmented message" } , 50
237+
238+ # This should send us over the edge
239+ SimpleWebSocketClient . send_continuation_frame ( client , payload )
240+
241+ # Get the error that terminate saw, to ensure we're closing for the expected reason
242+ assert_receive { :error , "Received oversize fragmented message" } , 500
243+
244+ assert SimpleWebSocketClient . recv_connection_close_frame ( client ) == { :ok , << 1009 :: 16 >> }
245+
246+ # Verify that the server didn't send any extraneous frames
247+ assert SimpleWebSocketClient . connection_closed_for_reading? ( client )
248+ Process . sleep ( 500 )
249+ end )
250+
251+ assert output =~ "Received oversize fragmented message"
252+ end
153253 end
154254
155255 describe "compressed frames" do
0 commit comments