From ed104c7ad0e488d57040c96974b8d0d022a775da Mon Sep 17 00:00:00 2001
From: Sina Samavati <sina.samv@gmail.com>
Date: Mon, 19 Jan 2015 20:44:57 +0330
Subject: httpc: Avoid parsing invalid 'Set-Cookie' headers

Parsing invalid 'Set-Cookie' header would make httpc crash.
This commit filters invalid 'Set-Cookie' headers so that httpc wouldn't try to parse them.
---
 lib/inets/src/http_client/httpc_cookie.erl | 18 ++++++++++++++++--
 lib/inets/test/httpc_SUITE.erl             | 20 ++++++++++++++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

(limited to 'lib')

diff --git a/lib/inets/src/http_client/httpc_cookie.erl b/lib/inets/src/http_client/httpc_cookie.erl
index 134115bdfa..5d71a0bb8f 100644
--- a/lib/inets/src/http_client/httpc_cookie.erl
+++ b/lib/inets/src/http_client/httpc_cookie.erl
@@ -334,9 +334,23 @@ add_domain(Str, #http_cookie{domain_default = true}) ->
 add_domain(Str, #http_cookie{domain = Domain}) ->
     Str ++ "; $Domain=" ++  Domain.
 
+is_set_cookie_valid("") ->
+    %% an empty Set-Cookie header is not valid
+    false;
+is_set_cookie_valid([$=|_]) ->
+    %% a Set-Cookie header without name is not valid
+    false;
+is_set_cookie_valid(SetCookieHeader) ->
+    %% a Set-Cookie header without name/value is not valid
+    case string:chr(SetCookieHeader, $=) of
+        0 -> false;
+        _ -> true
+    end.
+
 parse_set_cookies(CookieHeaders, DefaultPathDomain) ->
-    %% empty Set-Cookie header is invalid according to RFC but some sites violate it
-    SetCookieHeaders = [Value || {"set-cookie", Value} <- CookieHeaders, Value /= ""],
+    %% filter invalid Set-Cookie headers
+    SetCookieHeaders = [Value || {"set-cookie", Value} <- CookieHeaders,
+                                 is_set_cookie_valid(Value)],
     Cookies = [parse_set_cookie(SetCookieHeader, DefaultPathDomain) || 
 		  SetCookieHeader <- SetCookieHeaders],
     %% print_cookies("Parsed Cookies", Cookies),
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index c535d59b9f..545cc3f11b 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -91,6 +91,7 @@ only_simulated() ->
      cookie,
      cookie_profile,
      empty_set_cookie,
+     invalid_set_cookie,
      trace,
      stream_once,
      stream_single_chunk,
@@ -567,6 +568,18 @@ empty_set_cookie(Config) when is_list(Config) ->
 
     ok = httpc:set_options([{cookies, disabled}]).
 
+%%-------------------------------------------------------------------------
+invalid_set_cookie(doc) ->
+    ["Test ignoring invalid Set-Cookie header"];
+invalid_set_cookie(Config) when is_list(Config) ->
+    ok = httpc:set_options([{cookies, enabled}]),
+
+    URL = url(group_name(Config), "/invalid_set_cookie.html", Config),
+    {ok, {{_,200,_}, [_|_], [_|_]}} =
+        httpc:request(get, {URL, []}, [], []),
+
+    ok = httpc:set_options([{cookies, disabled}]).
+
 %%-------------------------------------------------------------------------
 headers_as_is(doc) ->
     ["Test the option headers_as_is"];
@@ -1686,6 +1699,13 @@ handle_uri(_,"/empty_set_cookie.html",_,_,_,_) ->
 	"Content-Length:32\r\n\r\n"++
 	"<HTML><BODY>foobar</BODY></HTML>";
 
+handle_uri(_,"/invalid_set_cookie.html",_,_,_,_) ->
+    "HTTP/1.1 200 ok\r\n" ++
+	"set-cookie: =\r\n" ++
+	"set-cookie: name-or-value\r\n" ++
+	"Content-Length:32\r\n\r\n"++
+	"<HTML><BODY>foobar</BODY></HTML>";
+
 handle_uri(_,"/missing_crlf.html",_,_,_,_) ->
     "HTTP/1.1 200 ok" ++
 	"Content-Length:32\r\n" ++
-- 
cgit v1.2.3