From ba1eca6b97fadf1f5e24516f732738be9570282c Mon Sep 17 00:00:00 2001 From: Ali Sabil Date: Mon, 10 Jun 2013 15:22:05 +0200 Subject: Avoid crashing in cowboy_req on invalid Accept-Encoding header Certain clients send malformed Accept-Encoding headers, which causes cowboy_req to crash is compression is enabled. --- src/cowboy_req.erl | 55 +++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 0e1c8a7..41b7b55 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -1021,31 +1021,36 @@ reply(Status, Headers, Body, Req=#http_req{ reply_may_compress(Status, Headers, Body, Req, RespHeaders, HTTP11Headers, Method) -> BodySize = iolist_size(Body), - {ok, Encodings, Req2} = parse_header(<<"accept-encoding">>, Req), - CanGzip = (BodySize > 300) - andalso (false =:= lists:keyfind(<<"content-encoding">>, - 1, Headers)) - andalso (false =:= lists:keyfind(<<"content-encoding">>, - 1, RespHeaders)) - andalso (false =:= lists:keyfind(<<"transfer-encoding">>, - 1, Headers)) - andalso (false =:= lists:keyfind(<<"transfer-encoding">>, - 1, RespHeaders)) - andalso (Encodings =/= undefined) - andalso (false =/= lists:keyfind(<<"gzip">>, 1, Encodings)), - case CanGzip of - true -> - GzBody = zlib:gzip(Body), - {_, Req3} = response(Status, Headers, RespHeaders, [ - {<<"content-length">>, integer_to_list(byte_size(GzBody))}, - {<<"content-encoding">>, <<"gzip">>}, - {<<"date">>, cowboy_clock:rfc1123()}, - {<<"server">>, <<"Cowboy">>} - |HTTP11Headers], - case Method of <<"HEAD">> -> <<>>; _ -> GzBody end, - Req2), - Req3; - false -> + case parse_header(<<"accept-encoding">>, Req) of + {ok, Encodings, Req2} -> + CanGzip = (BodySize > 300) + andalso (false =:= lists:keyfind(<<"content-encoding">>, + 1, Headers)) + andalso (false =:= lists:keyfind(<<"content-encoding">>, + 1, RespHeaders)) + andalso (false =:= lists:keyfind(<<"transfer-encoding">>, + 1, Headers)) + andalso (false =:= lists:keyfind(<<"transfer-encoding">>, + 1, RespHeaders)) + andalso (Encodings =/= undefined) + andalso (false =/= lists:keyfind(<<"gzip">>, 1, Encodings)), + case CanGzip of + true -> + GzBody = zlib:gzip(Body), + {_, Req3} = response(Status, Headers, RespHeaders, [ + {<<"content-length">>, integer_to_list(byte_size(GzBody))}, + {<<"content-encoding">>, <<"gzip">>}, + {<<"date">>, cowboy_clock:rfc1123()}, + {<<"server">>, <<"Cowboy">>} + |HTTP11Headers], + case Method of <<"HEAD">> -> <<>>; _ -> GzBody end, + Req2), + Req3; + false -> + reply_no_compress(Status, Headers, Body, Req, + RespHeaders, HTTP11Headers, Method, BodySize) + end; + {error, badarg} -> reply_no_compress(Status, Headers, Body, Req, RespHeaders, HTTP11Headers, Method, BodySize) end. -- cgit v1.2.3