From 84d7671e91bb2dee2081172dbf651860134ae75e Mon Sep 17 00:00:00 2001 From: rambocoder Date: Wed, 6 Mar 2013 08:50:45 -0500 Subject: Check the length before reading the body in body/1 and body_qs/1 --- src/cowboy_req.erl | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 93c8656..966e463 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -82,7 +82,9 @@ -export([stream_body/1]). -export([skip_body/1]). -export([body/1]). +-export([body/2]). -export([body_qs/1]). +-export([body_qs/2]). -export([multipart_data/1]). -export([multipart_skip/1]). @@ -729,17 +731,40 @@ content_decode(ContentDecode, Data, Req) -> {error, Reason} -> {error, Reason} end. -%% @doc Return the full body sent with the request. +%% @equiv body(8000000, Req) -spec body(Req) -> {ok, binary(), Req} | {error, atom()} when Req::req(). body(Req) -> - body(Req, <<>>). + body(8000000, Req). --spec body(Req, binary()) +%% @doc Return the body sent with the request. +-spec body(non_neg_integer() | infinity, Req) -> {ok, binary(), Req} | {error, atom()} when Req::req(). -body(Req, Acc) -> +body(infinity, Req) -> + case parse_header(<<"transfer-encoding">>, Req) of + {ok, [<<"identity">>], Req2} -> + read_body(Req2, <<>>); + {ok, _, _} -> + {error, chunked} + end; +body(MaxBodyLength, Req) -> + case parse_header(<<"transfer-encoding">>, Req) of + {ok, [<<"identity">>], Req2} -> + {ok, Length, Req3} = parse_header(<<"content-length">>, Req2, 0), + if Length > MaxBodyLength -> + {error, badlength}; + true -> + read_body(Req3, <<>>) + end; + {ok, _, _} -> + {error, chunked} + end. + +-spec read_body(Req, binary()) + -> {ok, binary(), Req} | {error, atom()} when Req::req(). +read_body(Req, Acc) -> case stream_body(Req) of {ok, Data, Req2} -> - body(Req2, << Acc/binary, Data/binary >>); + read_body(Req2, << Acc/binary, Data/binary >>); {done, Req2} -> {ok, Acc, Req2}; {error, Reason} -> @@ -754,13 +779,21 @@ skip_body(Req) -> {error, Reason} -> {error, Reason} end. -%% @doc Return the full body sent with the request, parsed as an -%% application/x-www-form-urlencoded string. Essentially a POST query string. +%% @equiv body_qs(16000, Req) -spec body_qs(Req) -> {ok, [{binary(), binary() | true}], Req} | {error, atom()} when Req::req(). body_qs(Req) -> - case body(Req) of + body_qs(16000, Req). + +%% @doc Return the body sent with the request, parsed as an +%% application/x-www-form-urlencoded string. +%% Essentially a POST query string. +-spec body_qs(non_neg_integer() | infinity, Req) + -> {ok, [{binary(), binary() | true}], Req} | {error, atom()} + when Req::req(). +body_qs(MaxBodyLength, Req) -> + case body(MaxBodyLength, Req) of {ok, Body, Req2} -> {ok, cowboy_http:x_www_form_urlencoded(Body), Req2}; {error, Reason} -> -- cgit v1.2.3