summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2019-01-22 11:02:34 -0500
committerNick Vatamaniuc <vatamane@apache.org>2019-01-22 11:53:22 -0500
commit18f508fa8f863580ab6342c7a1ae15a3d2468960 (patch)
tree414279adedc8575e764ed08505817616b292ee51
parent00ce1c1610507caecf0a02e2301f4a6b91379c37 (diff)
downloadcouchdb-fix-lower-buffer-crash.tar.gz
Update to mochiweb 2.19.0fix-lower-buffer-crash
It has a fix to revert user socket buffer size to 8192 and also allow setting this buffer values directly (not necessarily via {recbuf, ...}). Fixes #1810 Warning: 2.19.0 blacklists a series of OTP releases: 21.2, 21.2.1, 21.2.2 This is done via a runtime check of the ssl application version. The blacklist seems valid as there is a bug which prevents data from being delivered on TSL sockets. That could affect either CouchDB server side (chttpd) or replication client side (ibrowse).
-rw-r--r--.travis.yml2
-rw-r--r--rebar.config.script2
-rw-r--r--src/chttpd/test/chttpd_socket_buffer_size_test.erl163
3 files changed, 165 insertions, 2 deletions
diff --git a/.travis.yml b/.travis.yml
index 45ff9edd2..dd414ce27 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ os: linux
dist: trusty
otp_release:
- - 21.1
+ - 21.2.3
- 20.3
- 19.3
diff --git a/rebar.config.script b/rebar.config.script
index 019e6f182..c82049e44 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -65,7 +65,7 @@ DepDescs = [
{hyper, "hyper", {tag, "CouchDB-2.2.0-4"}},
{ibrowse, "ibrowse", {tag, "CouchDB-4.0.1"}},
{jiffy, "jiffy", {tag, "CouchDB-0.14.11-2"}},
-{mochiweb, "mochiweb", {tag, "CouchDB-v2.18.0-1"}},
+{mochiweb, "mochiweb", {tag, "v2.19.0"}},
{meck, "meck", {tag, "0.8.8"}}
],
diff --git a/src/chttpd/test/chttpd_socket_buffer_size_test.erl b/src/chttpd/test/chttpd_socket_buffer_size_test.erl
new file mode 100644
index 000000000..650bf9b0b
--- /dev/null
+++ b/src/chttpd/test/chttpd_socket_buffer_size_test.erl
@@ -0,0 +1,163 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_socket_buffer_size_test).
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+
+-define(USER, "chttpd_db_socket_buffer_size_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(CONTENT_JSON, {"Content-Type", "application/json"}).
+
+
+setup() ->
+ Hashed = couch_passwords:hash_admin_password(?PASS),
+ ok = config:set("admins", ?USER, ?b2l(Hashed), _Persist=false),
+ SocketOptions = config:get("chttpd", "socket_options"),
+ Db = ?tempdb(),
+ Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
+ Port = integer_to_list(mochiweb_socket_server:get(chttpd, port)),
+ Url = "http://" ++ Addr ++ ":" ++ Port ++ "/" ++ ?b2l(Db),
+ create_db(Url),
+ {Db, SocketOptions}.
+
+
+teardown({Db, SocketOptions}) ->
+ delete_db(url(Db)),
+ ok = config:delete("chttpd", "socket_options", _Persist=false),
+ ok = config:delete("admins", ?USER, _Persist=false),
+ case SocketOptions of
+ undefined ->
+ ok;
+ _ ->
+ ok = config:set("chttpd", "socket_options", SocketOptions)
+ end.
+
+
+socket_buffer_size_test_() ->
+ {
+ "chttpd socket_buffer_size_test",
+ {
+ setup,
+ fun chttpd_test_util:start_couch/0,
+ fun chttpd_test_util:stop_couch/1,
+ {
+ foreach,
+ fun setup/0, fun teardown/1,
+ [
+ fun buffer_too_small_url_fails/1,
+ fun buffer_too_small_header_fails/1,
+ fun recbuf_too_small_url_fails/1,
+ fun recbuf_too_small_header_fails/1,
+ fun default_buffer_settings_work/1
+ ]
+ }
+ }
+ }.
+
+
+buffer_too_small_url_fails({Db, _}) ->
+ ?_test(begin
+ restart_chttpd("[{buffer, 1024}]"),
+ Id = data(1500),
+ Status1 = put_req(url(Db) ++ "/" ++ Id, "{}"),
+ ?assertEqual(400, Status1),
+ restart_chttpd("[{buffer, 2048}]"),
+ Status2 = put_req(url(Db) ++ "/" ++ Id, "{}"),
+ ?assert(Status2 =:= 201 orelse Status2 =:= 202)
+ end).
+
+
+buffer_too_small_header_fails({Db, _}) ->
+ ?_test(begin
+ restart_chttpd("[{buffer, 1024}]"),
+ Headers = [{"Blah", data(1500)}],
+ Status1 = put_req(url(Db) ++ "/d", Headers, "{}"),
+ ?assertEqual(400, Status1),
+ restart_chttpd("[{buffer, 2048}]"),
+ Status2 = put_req(url(Db) ++ "/d", Headers, "{}"),
+ ?assert(Status2 =:= 201 orelse Status2 =:= 202)
+ end).
+
+
+recbuf_too_small_url_fails({Db, _}) ->
+ ?_test(begin
+ restart_chttpd("[{recbuf, 1024}]"),
+ Id = data(1500),
+ Status1 = put_req(url(Db) ++ "/" ++ Id, "{}"),
+ ?assertEqual(400, Status1),
+ restart_chttpd("[{recbuf, 2048}]"),
+ Status2 = put_req(url(Db) ++ "/" ++ Id, "{}"),
+ ?assert(Status2 =:= 201 orelse Status2 =:= 202)
+ end).
+
+
+recbuf_too_small_header_fails({Db, _}) ->
+ ?_test(begin
+ restart_chttpd("[{recbuf, 1024}]"),
+ Headers = [{"Blah", data(1500)}],
+ Status1 = put_req(url(Db) ++ "/d", Headers, "{}"),
+ ?assertEqual(400, Status1),
+ restart_chttpd("[{recbuf, 2048}]"),
+ Status2 = put_req(url(Db) ++ "/d", Headers, "{}"),
+ ?assert(Status2 =:= 201 orelse Status2 =:= 202)
+ end).
+
+
+default_buffer_settings_work({Db, _}) ->
+ ?_test(begin
+ restart_chttpd("[{recbuf, undefined}]"),
+ Id = data(7000),
+ Status = put_req(url(Db) ++ "/" ++ Id, "{}"),
+ ?assert(Status =:= 201 orelse Status =:= 202)
+ end).
+
+
+% Helper functions
+
+url(Db) ->
+ Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
+ Port = integer_to_list(mochiweb_socket_server:get(chttpd, port)),
+ "http://" ++ Addr ++ ":" ++ Port ++ "/" ++ ?b2l(Db).
+
+
+create_db(Url) ->
+ Status = put_req(Url ++ "?q=1&n=1", "{}"),
+ ?assert(Status =:= 201 orelse Status =:= 202).
+
+
+delete_db(Url) ->
+ {ok, 200, _, _} = test_request:delete(Url, [?AUTH]).
+
+
+put_req(Url, Body) ->
+ put_req(Url, [], Body).
+
+
+put_req(Url, Headers, Body) ->
+ AllHeaders = Headers ++ [?CONTENT_JSON, ?AUTH],
+ {ok, Status, _, _} = test_request:put(Url, AllHeaders, Body),
+ Status.
+
+
+data(Size) ->
+ string:copies("x", Size).
+
+
+restart_chttpd(ServerOptions) ->
+ ok = application:stop(chttpd),
+ ok = application:stop(mochiweb),
+ config:set("chttpd", "server_options", ServerOptions, _Persist=false),
+ ok = application:start(mochiweb),
+ ok = application:start(chttpd).