0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00

Fix infinite loop on incomplete multipart body

I have amended a lot of changes from the original commit
to make it behave as expected, including returning a 400
error. LH
This commit is contained in:
Jeffrey Griffin 2017-05-16 14:50:01 -07:00 committed by Loïc Hoguin
parent 292e732abf
commit 6460e9d2d2
No known key found for this signature in database
GPG key ID: 71366FF21851DF03
2 changed files with 48 additions and 9 deletions

View file

@ -506,7 +506,7 @@ read_part(Req) ->
read_part(Req, Opts) ->
case maps:is_key(multipart, Req) of
true ->
{Data, Req2} = stream_multipart(Req, Opts),
{Data, Req2} = stream_multipart(Req, Opts, headers),
read_part(Data, Opts, Req2);
false ->
read_part(init_multipart(Req), Opts)
@ -515,10 +515,10 @@ read_part(Req, Opts) ->
read_part(Buffer, Opts, Req=#{multipart := {Boundary, _}}) ->
try cow_multipart:parse_headers(Buffer, Boundary) of
more ->
{Data, Req2} = stream_multipart(Req, Opts),
{Data, Req2} = stream_multipart(Req, Opts, headers),
read_part(<< Buffer/binary, Data/binary >>, Opts, Req2);
{more, Buffer2} ->
{Data, Req2} = stream_multipart(Req, Opts),
{Data, Req2} = stream_multipart(Req, Opts, headers),
read_part(<< Buffer2/binary, Data/binary >>, Opts, Req2);
{ok, Headers0, Rest} ->
Headers = maps:from_list(Headers0),
@ -557,7 +557,7 @@ read_part_body(Buffer, Opts, Req=#{multipart := {Boundary, _}}, Acc) ->
true ->
{more, Acc, Req#{multipart => {Boundary, Buffer}}};
false ->
{Data, Req2} = stream_multipart(Req, Opts),
{Data, Req2} = stream_multipart(Req, Opts, body),
case cow_multipart:parse_body(<< Buffer/binary, Data/binary >>, Boundary) of
{ok, Body} ->
read_part_body(<<>>, Opts, Req2, << Acc/binary, Body/binary >>);
@ -583,12 +583,20 @@ init_multipart(Req) ->
'Missing boundary parameter for multipart media type.'})
end.
stream_multipart(Req=#{multipart := done}, _) ->
stream_multipart(Req=#{multipart := done}, _, _) ->
{<<>>, Req};
stream_multipart(Req=#{multipart := {_, <<>>}}, Opts) ->
{_, Data, Req2} = read_body(Req, Opts),
{Data, Req2};
stream_multipart(Req=#{multipart := {Boundary, Buffer}}, _) ->
stream_multipart(Req=#{multipart := {_, <<>>}}, Opts, Type) ->
case read_body(Req, Opts) of
{more, Data, Req2} ->
{Data, Req2};
%% We crash when the data ends unexpectedly.
{ok, <<>>, _} ->
exit({request_error, {multipart, Type},
'Malformed body; multipart expected.'});
{ok, Data, Req2} ->
{Data, Req2}
end;
stream_multipart(Req=#{multipart := {Boundary, Buffer}}, _, _) ->
{Buffer, Req#{multipart => {Boundary, <<>>}}}.
%% Response.