diff options
author | Nick Vatamaniuc <vatamane@apache.org> | 2019-01-22 11:02:34 -0500 |
---|---|---|
committer | Nick Vatamaniuc <vatamane@apache.org> | 2019-01-22 11:53:22 -0500 |
commit | 18f508fa8f863580ab6342c7a1ae15a3d2468960 (patch) | |
tree | 414279adedc8575e764ed08505817616b292ee51 | |
parent | 00ce1c1610507caecf0a02e2301f4a6b91379c37 (diff) | |
download | couchdb-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.yml | 2 | ||||
-rw-r--r-- | rebar.config.script | 2 | ||||
-rw-r--r-- | src/chttpd/test/chttpd_socket_buffer_size_test.erl | 163 |
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). |