mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 04:10:24 +00:00
Websocket: Also apply max_frame_size limit to decompressed data
Before this commit frames could "cheat" by compressing data below the limit which would get expanded above the limit. Now Cowboy will stop decompressing data when the limit is reached.
This commit is contained in:
parent
6e221d38b1
commit
7f739cad6d
3 changed files with 26 additions and 3 deletions
|
@ -480,12 +480,16 @@ parse_header(State=#state{opts=Opts, frag_state=FragState, extensions=Extensions
|
|||
websocket_close(State, HandlerState, {error, badframe})
|
||||
end.
|
||||
|
||||
parse_payload(State=#state{frag_state=FragState, utf8_state=Incomplete, extensions=Extensions},
|
||||
parse_payload(State=#state{opts=Opts, frag_state=FragState, utf8_state=Incomplete, extensions=Extensions},
|
||||
HandlerState, ParseState=#ps_payload{
|
||||
type=Type, len=Len, mask_key=MaskKey, rsv=Rsv,
|
||||
unmasked=Unmasked, unmasked_len=UnmaskedLen}, Data) ->
|
||||
MaxFrameSize = case maps:get(max_frame_size, Opts, infinity) of
|
||||
infinity -> infinity;
|
||||
MaxFrameSize0 -> MaxFrameSize0 - UnmaskedLen
|
||||
end,
|
||||
case cow_ws:parse_payload(Data, MaskKey, Incomplete, UnmaskedLen,
|
||||
Type, Len, FragState, Extensions, Rsv) of
|
||||
Type, Len, FragState, Extensions#{max_inflate_size => MaxFrameSize}, Rsv) of
|
||||
{ok, CloseCode, Payload, Utf8State, Rest} ->
|
||||
dispatch_frame(State#state{utf8_state=Utf8State}, HandlerState,
|
||||
ParseState#ps_payload{unmasked= <<Unmasked/binary, Payload/binary>>,
|
||||
|
|
|
@ -203,6 +203,25 @@ do_ws_version(Socket) ->
|
|||
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
|
||||
ok.
|
||||
|
||||
ws_deflate_max_frame_size_close(Config) ->
|
||||
doc("Server closes connection when decompressed frame size exceeds max_frame_size option"),
|
||||
%% max_frame_size is set to 8 bytes in ws_max_frame_size.
|
||||
{ok, Socket, Headers} = do_handshake("/ws_max_frame_size",
|
||||
"Sec-WebSocket-Extensions: permessage-deflate\r\n", Config),
|
||||
{_, "permessage-deflate"} = lists:keyfind("sec-websocket-extensions", 1, Headers),
|
||||
Mask = 16#11223344,
|
||||
Z = zlib:open(),
|
||||
zlib:deflateInit(Z, best_compression, deflated, -15, 8, default),
|
||||
CompressedData0 = iolist_to_binary(zlib:deflate(Z, <<0:800>>, sync)),
|
||||
CompressedData = binary:part(CompressedData0, 0, byte_size(CompressedData0) - 4),
|
||||
MaskedData = do_mask(CompressedData, Mask, <<>>),
|
||||
Len = byte_size(MaskedData),
|
||||
true = Len < 8,
|
||||
ok = gen_tcp:send(Socket, << 1:1, 1:1, 0:2, 1:4, 1:1, Len:7, Mask:32, MaskedData/binary >>),
|
||||
{ok, << 1:1, 0:3, 8:4, 0:1, 2:7, 1009:16 >>} = gen_tcp:recv(Socket, 0, 6000),
|
||||
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
|
||||
ok.
|
||||
|
||||
ws_deflate_opts_client_context_takeover(Config) ->
|
||||
doc("Handler is configured with client context takeover enabled."),
|
||||
{ok, _, Headers1} = do_handshake("/ws_deflate_opts?client_context_takeover",
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
-export([websocket_info/2]).
|
||||
|
||||
init(Req, State) ->
|
||||
{cowboy_websocket, Req, State, #{max_frame_size => 8}}.
|
||||
{cowboy_websocket, Req, State, #{max_frame_size => 8, compress => true}}.
|
||||
|
||||
websocket_handle({text, Data}, State) ->
|
||||
{[{text, Data}], State};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue