diff options
-rw-r--r-- | OTP_VERSION | 2 | ||||
-rw-r--r-- | erts/doc/src/notes.xml | 24 | ||||
-rw-r--r-- | erts/emulator/nifs/common/zlib_nif.c | 127 | ||||
-rw-r--r-- | erts/preloaded/ebin/zlib.beam | bin | 19120 -> 19492 bytes | |||
-rw-r--r-- | erts/preloaded/src/zlib.erl | 38 | ||||
-rw-r--r-- | erts/vsn.mk | 2 | ||||
-rw-r--r-- | lib/compiler/doc/src/notes.xml | 16 | ||||
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 6 | ||||
-rw-r--r-- | lib/compiler/test/bs_match_SUITE.erl | 38 | ||||
-rw-r--r-- | lib/compiler/vsn.mk | 2 | ||||
-rw-r--r-- | lib/kernel/test/zlib_SUITE.erl | 23 | ||||
-rw-r--r-- | lib/ssh/doc/src/notes.xml | 28 | ||||
-rw-r--r-- | lib/ssh/src/ssh_connection_handler.erl | 10 | ||||
-rw-r--r-- | lib/ssh/src/ssh_transport.erl | 21 | ||||
-rw-r--r-- | lib/ssh/vsn.mk | 2 | ||||
-rw-r--r-- | otp_versions.table | 1 |
16 files changed, 231 insertions, 109 deletions
diff --git a/OTP_VERSION b/OTP_VERSION index 2e73f8d2aa..2a0e5e0a15 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -20.1 +20.1.1 diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 1a5bea8820..fa200176e4 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,30 @@ </header> <p>This document describes the changes made to the ERTS application.</p> +<section><title>Erts 9.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The new zlib module returned a data_error when + inflating concatenated streams, which was incompatible + with the old module's behavior of returning the + uncompressed data up to the end of the first stream.</p> + <p> + Own Id: OTP-14648</p> + </item> + <item> + <p>zlib:gunzip/1 will no longer stop at the end of the + first stream when decompressing concatenated gzip + files.</p> + <p> + Own Id: OTP-14649</p> + </item> + </list> + </section> + +</section> + <section><title>Erts 9.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/emulator/nifs/common/zlib_nif.c b/erts/emulator/nifs/common/zlib_nif.c index a1a65e1946..a9c5b05e47 100644 --- a/erts/emulator/nifs/common/zlib_nif.c +++ b/erts/emulator/nifs/common/zlib_nif.c @@ -69,11 +69,27 @@ typedef enum { ST_DEFLATE = 1, ST_INFLATE = 2, ST_CLOSED = 3 -} zlib_state; +} zlib_state_t; + +/* Controls what to do when the user attempts to decompress more data after + * Z_STREAM_END has been returned: + * + * - 'cut' wipes all further input and returns empty results until reset by + * the user. This is the default behavior, matching that of the old driver. + * - 'reset' resets the state without discarding any input, making it possible + * to decompress blindly concatenated streams. + * - 'error' crashes with a data error. */ +typedef enum { + EOS_BEHAVIOR_ERROR = 0, + EOS_BEHAVIOR_RESET = 1, + EOS_BEHAVIOR_CUT = 2 +} zlib_eos_behavior_t; typedef struct { z_stream s; - zlib_state state; + zlib_state_t state; + + zlib_eos_behavior_t eos_behavior; /* These refer to the plaintext CRC, and are only needed for zlib:crc32/1 * which is deprecated. */ @@ -102,7 +118,6 @@ typedef struct { static ERL_NIF_TERM zlib_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_deflateInit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM zlib_deflateInit2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_deflateSetDictionary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_deflateReset(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_deflateEnd(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); @@ -110,7 +125,6 @@ static ERL_NIF_TERM zlib_deflateParams(ErlNifEnv *env, int argc, const ERL_NIF_T static ERL_NIF_TERM zlib_deflate(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_inflateInit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM zlib_inflateInit2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_inflateSetDictionary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_inflateGetDictionary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM zlib_inflateReset(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); @@ -130,8 +144,7 @@ static ERL_NIF_TERM zlib_enqueue_input(ErlNifEnv *env, int argc, const ERL_NIF_T static ErlNifFunc nif_funcs[] = { /* deflate */ - {"deflateInit_nif", 2, zlib_deflateInit}, - {"deflateInit_nif", 6, zlib_deflateInit2}, + {"deflateInit_nif", 6, zlib_deflateInit}, {"deflateSetDictionary_nif", 2, zlib_deflateSetDictionary}, {"deflateReset_nif", 1, zlib_deflateReset}, {"deflateEnd_nif", 1, zlib_deflateEnd}, @@ -139,8 +152,7 @@ static ErlNifFunc nif_funcs[] = { {"deflate_nif", 4, zlib_deflate}, /* inflate */ - {"inflateInit_nif", 1, zlib_inflateInit}, - {"inflateInit_nif", 2, zlib_inflateInit2}, + {"inflateInit_nif", 3, zlib_inflateInit}, {"inflateSetDictionary_nif", 2, zlib_inflateSetDictionary}, {"inflateGetDictionary_nif", 1, zlib_inflateGetDictionary}, {"inflateReset_nif", 1, zlib_inflateReset}, @@ -509,9 +521,11 @@ static ERL_NIF_TERM zlib_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[ d->s.opaque = d; d->s.data_type = Z_BINARY; - d->state = ST_NONE; + d->eos_behavior = EOS_BEHAVIOR_CUT; d->eos_seen = 0; + d->state = ST_NONE; + d->want_output_crc = 0; d->want_input_crc = 0; d->is_raw_stream = 0; @@ -551,42 +565,6 @@ static ERL_NIF_TERM zlib_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv static ERL_NIF_TERM zlib_deflateInit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { zlib_data_t *d; - int level, res; - - if(argc != 2 || !get_zlib_data(env, argv[0], &d) || - !enif_get_int(env, argv[1], &level)) { - return enif_make_badarg(env); - } else if(!zlib_process_check(env, d)) { - return enif_raise_exception(env, am_not_on_controlling_process); - } else if(d->state != ST_NONE) { - return enif_raise_exception(env, am_already_initialized); - } - - res = deflateInit(&d->s, level); - - if(res == Z_OK) { - d->state = ST_DEFLATE; - d->eos_seen = 0; - - /* FIXME: crc32/1 is documented as returning "the current calculated - * checksum," but failed to mention that the old implementation only - * calculated it when WindowBits < 0 (See zlib_deflateInit2). - * - * We could fix this behavior by setting d->want_input_crc to 1 here, - * but we've decided to retain this quirk since the performance hit is - * quite significant. */ - d->want_output_crc = 0; - d->want_input_crc = 0; - - d->output_crc = crc32(0L, Z_NULL, 0); - d->input_crc = crc32(0L, Z_NULL, 0); - } - - return zlib_return(env, res); -} - -static ERL_NIF_TERM zlib_deflateInit2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - zlib_data_t *d; int level, method, windowBits, memLevel, strategy, res; if(argc != 6 || !get_zlib_data(env, argv[0], &d) @@ -741,39 +719,12 @@ static ERL_NIF_TERM zlib_deflate(ErlNifEnv *env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM zlib_inflateInit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { zlib_data_t *d; - int res; - if(argc != 1 || !get_zlib_data(env, argv[0], &d)) { - return enif_make_badarg(env); - } else if(!zlib_process_check(env, d)) { - return enif_raise_exception(env, am_not_on_controlling_process); - } else if(d->state != ST_NONE) { - return enif_raise_exception(env, am_already_initialized); - } - - res = inflateInit(&d->s); - - if(res == Z_OK) { - d->state = ST_INFLATE; - d->eos_seen = 0; - - d->want_output_crc = 0; - d->want_input_crc = 0; - d->is_raw_stream = 0; - - d->output_crc = crc32(0L, Z_NULL, 0); - d->input_crc = crc32(0L, Z_NULL, 0); - } - - return zlib_return(env, res); -} + int windowBits, eosBehavior, res; -static ERL_NIF_TERM zlib_inflateInit2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - zlib_data_t *d; - int windowBits, res; - - if(argc != 2 || !get_zlib_data(env, argv[0], &d) - || !enif_get_int(env, argv[1], &windowBits)) { + if(argc != 3 || !get_zlib_data(env, argv[0], &d) + || !enif_get_int(env, argv[1], &windowBits) + || !enif_get_int(env, argv[2], &eosBehavior)) { return enif_make_badarg(env); } else if(!zlib_process_check(env, d)) { return enif_raise_exception(env, am_not_on_controlling_process); @@ -785,6 +736,8 @@ static ERL_NIF_TERM zlib_inflateInit2(ErlNifEnv *env, int argc, const ERL_NIF_TE if(res == Z_OK) { d->state = ST_INFLATE; + + d->eos_behavior = eosBehavior; d->eos_seen = 0; d->is_raw_stream = (windowBits < 0); @@ -934,6 +887,28 @@ static ERL_NIF_TERM zlib_inflate(ErlNifEnv *env, int argc, const ERL_NIF_TERM ar return enif_raise_exception(env, am_not_initialized); } + if(d->eos_seen) { + int res; + + switch(d->eos_behavior) { + case EOS_BEHAVIOR_ERROR: + return zlib_return(env, Z_DATA_ERROR); + case EOS_BEHAVIOR_RESET: + res = inflateReset(&d->s); + + if(res != Z_OK) { + return zlib_return(env, res); + } + + d->eos_seen = 0; + break; + case EOS_BEHAVIOR_CUT: + zlib_reset_input(d); + + return enif_make_tuple2(env, am_finished, enif_make_list(env, 0)); + } + } + return zlib_codec(&inflate, env, d, input_chunk_size, output_chunk_size, flush); } diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex 267b5cb0a8..5048bdb846 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl index dca5a42779..3170ab6351 100644 --- a/erts/preloaded/src/zlib.erl +++ b/erts/preloaded/src/zlib.erl @@ -23,7 +23,7 @@ -export([open/0,close/1,deflateInit/1,deflateInit/2,deflateInit/6, deflateSetDictionary/2,deflateReset/1,deflateParams/3, deflate/2,deflate/3,deflateEnd/1, - inflateInit/1,inflateInit/2, + inflateInit/1,inflateInit/2,inflateInit/3, inflateSetDictionary/2,inflateGetDictionary/1, inflateReset/1, inflate/2,inflate/3,inflateEnd/1, inflateChunk/2,inflateChunk/1, @@ -68,6 +68,13 @@ -define(MAX_WBITS, 15). +-define(DEFAULT_MEMLEVEL, 8). +-define(DEFAULT_WBITS, 15). + +-define(EOS_BEHAVIOR_ERROR, 0). +-define(EOS_BEHAVIOR_RESET, 1). +-define(EOS_BEHAVIOR_CUT, 2). + %% Chunk sizes are hardcoded on account of them screwing with the %% predictability of the system. zlib is incapable of trapping so we need to %% ensure that it never operates on any significant amount of data. @@ -130,10 +137,7 @@ deflateInit(Z) -> Z :: zstream(), Level :: zlevel(). deflateInit(Z, Level) -> - deflateInit_nif(Z, arg_level(Level)). - -deflateInit_nif(_Z, _Level) -> - erlang:nif_error(undef). + deflateInit(Z, Level, deflated, ?DEFAULT_WBITS, ?DEFAULT_MEMLEVEL, default). -spec deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) -> 'ok' when Z :: zstream(), @@ -225,16 +229,21 @@ deflateEnd_nif(_Z) -> -spec inflateInit(Z) -> 'ok' when Z :: zstream(). inflateInit(Z) -> - inflateInit_nif(Z). -inflateInit_nif(_Z) -> - erlang:nif_error(undef). + inflateInit(Z, ?DEFAULT_WBITS). -spec inflateInit(Z, WindowBits) -> 'ok' when Z :: zstream(), WindowBits :: zwindowbits(). inflateInit(Z, WindowBits) -> - inflateInit_nif(Z, WindowBits). -inflateInit_nif(_Z, _WindowBits) -> + inflateInit(Z, WindowBits, cut). + +-spec inflateInit(Z, WindowBits, EoSBehavior) -> 'ok' when + Z :: zstream(), + WindowBits :: zwindowbits(), + EoSBehavior :: error | reset | cut. +inflateInit(Z, WindowBits, EoSBehavior) -> + inflateInit_nif(Z, arg_bitsz(WindowBits), arg_eos_behavior(EoSBehavior)). +inflateInit_nif(_Z, _WindowBits, _EoSBehavior) -> erlang:nif_error(undef). -spec inflateSetDictionary(Z, Dictionary) -> 'ok' when @@ -532,7 +541,7 @@ gzip(Data) -> gunzip(Data) -> Z = open(), Bs = try - inflateInit(Z, 16+?MAX_WBITS), + inflateInit(Z, 16+?MAX_WBITS, reset), B = inflate(Z, Data), inflateEnd(Z), B @@ -652,6 +661,11 @@ arg_strategy(_) -> erlang:error(bad_compression_strategy). arg_method(deflated) -> ?Z_DEFLATED; arg_method(_) -> erlang:error(bad_compression_method). +arg_eos_behavior(error) -> ?EOS_BEHAVIOR_ERROR; +arg_eos_behavior(reset) -> ?EOS_BEHAVIOR_RESET; +arg_eos_behavior(cut) -> ?EOS_BEHAVIOR_CUT; +arg_eos_behavior(_) -> erlang:error(bad_eos_behavior). + -spec arg_bitsz(zwindowbits()) -> zwindowbits(). arg_bitsz(Bits) when is_integer(Bits) andalso ((8 =< Bits andalso Bits < 48) orelse @@ -678,4 +692,4 @@ enqueue_input_1(Z, IOVec) -> end. enqueue_nif(_Z, _IOVec) -> - erlang:nif_error(undef).
\ No newline at end of file + erlang:nif_error(undef). diff --git a/erts/vsn.mk b/erts/vsn.mk index 380be1b534..1c6472a0ab 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 9.1 +VSN = 9.1.1 # Port number 4365 in 4.2 # Port number 4366 in 4.3 diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index 9b32ec54c4..bd095c422a 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,22 @@ <p>This document describes the changes made to the Compiler application.</p> +<section><title>Compiler 7.1.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The compiler could issue an incorrect internal + consistency failure diagnostic for some complicated bit + syntax maches.</p> + <p> + Own Id: OTP-14640 Aux Id: ERL-490 </p> + </item> + </list> + </section> + +</section> + <section><title>Compiler 7.1.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 00901077d3..be8908dd6b 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -1430,13 +1430,13 @@ merge_types(bool, {atom,A}) -> merge_bool(A); merge_types({atom,A}, bool) -> merge_bool(A); -merge_types(#ms{id=Id1,valid=B0,slots=Slots}, - #ms{id=Id2,valid=B1,slots=Slots}) -> +merge_types(#ms{id=Id1,valid=B1,slots=Slots1}, + #ms{id=Id2,valid=B2,slots=Slots2}) -> Id = if Id1 =:= Id2 -> Id1; true -> make_ref() end, - #ms{id=Id,valid=B0 band B1,slots=Slots}; + #ms{id=Id,valid=B1 band B2,slots=min(Slots1, Slots2)}; merge_types(T1, T2) when T1 =/= T2 -> %% Too different. All we know is that the type is a 'term'. term. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 0ec05456ec..2fe8cd0cff 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -39,7 +39,7 @@ match_string_opt/1,select_on_integer/1, map_and_binary/1,unsafe_branch_caching/1, bad_literals/1,good_literals/1,constant_propagation/1, - parse_xml/1,get_payload/1]). + parse_xml/1,get_payload/1,num_slots_different/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -71,7 +71,7 @@ groups() -> match_string_opt,select_on_integer, map_and_binary,unsafe_branch_caching, bad_literals,good_literals,constant_propagation,parse_xml, - get_payload]}]. + get_payload,num_slots_different]}]. init_per_suite(Config) -> @@ -1524,6 +1524,40 @@ do_get_payload(ExtHdr) -> <<_:13,_:35>> = ExtHdr#ext_header.ext_hdr_opts, ExtHdrOptions. +%% ERL-490 +num_slots_different(_Config) -> + Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>}, + {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>}, + {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>}, + {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}], + _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts], + + {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)), + ok. + + +lgettext(<<"de">>, <<"default">>, <<"Remove">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Results">>) -> + {ok, <<"Ergebnisse">>}; +lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"navigation">>, <<"Results">>) -> + {ok, <<"Ergebnisse">>}; +lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) -> + {ok, <<"Ressourcen">>}. + + check(F, R) -> R = F(). diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 43fe0c8f6d..435a57aac2 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.1.2 +COMPILER_VSN = 7.1.3 diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index e246276262..d17eded811 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -276,10 +276,10 @@ api_inflateInit(Config) when is_list(Config) -> ?m(ok,zlib:close(Z12)) end, lists:seq(8,15)), ?m(?EXIT(badarg), zlib:inflateInit(gurka, -15)), - ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 7)), - ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, -7)), - ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 48)), - ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, -16)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 7)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -7)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 48)), + ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -16)), ?m(ok, zlib:close(Z1)). %% Test inflateSetDictionary. @@ -416,6 +416,9 @@ api_inflateChunk(Config) when is_list(Config) -> {more, Part1AsIOList} = zlib:inflateChunk(Z1, Compressed), {more, Part2AsIOList} = zlib:inflateChunk(Z1), {more, Part3AsIOList} = zlib:inflateChunk(Z1), + + [] = zlib:inflateChunk(Z1), + [] = zlib:inflateChunk(Z1), [] = zlib:inflateChunk(Z1), ?m(Part1, iolist_to_binary(Part1AsIOList)), @@ -483,7 +486,8 @@ api_safeInflate(Config) when is_list(Config) -> SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []), - ?m(?EXIT(data_error), zlib:safeInflate(Z1, Compressed)), + ?m({finished, []}, zlib:safeInflate(Z1, Compressed)), + ?m({finished, []}, zlib:safeInflate(Z1, Compressed)), ?m(ok, zlib:inflateReset(Z1)), ?m(?EXIT(badarg), zlib:safeInflate(gurka, Compressed)), @@ -632,6 +636,7 @@ api_g_un_zip(Config) when is_list(Config) -> ?m(?EXIT(badarg),zlib:gzip(not_a_binary)), Bin = <<1,11,1,23,45>>, Comp = zlib:gzip(Bin), + ?m(Comp, zlib:gzip(binary_to_list(Bin))), ?m(?EXIT(badarg), zlib:gunzip(not_a_binary)), ?m(?EXIT(data_error), zlib:gunzip(<<171,171,171,171,171>>)), @@ -639,6 +644,14 @@ api_g_un_zip(Config) when is_list(Config) -> ?m(Bin, zlib:gunzip(Comp)), ?m(Bin, zlib:gunzip(binary_to_list(Comp))), + %% RFC 1952: + %% + %% "A gzip file consists of a series of "members" (compressed data + %% sets). [...] The members simply appear one after another in the file, + %% with no additional information before, between, or after them." + Concatenated = <<Bin/binary, Bin/binary>>, + ?m(Concatenated, zlib:gunzip([Comp, Comp])), + %% Bad CRC; bad length. BadCrc = bad_crc_data(), ?m(?EXIT(data_error),(catch zlib:gunzip(BadCrc))), diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 4ba75b761f..ef3e94a1e1 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,34 @@ <file>notes.xml</file> </header> +<section><title>Ssh 4.6.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed broken printout</p> + <p> + Own Id: OTP-14645</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Disable aes_gcm ciphers if peer is OpenSSH 6.2 which is + known to have trouble with them in some cases.</p> + <p> + Own Id: OTP-14638</p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 4.6</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 8d3ddb09a4..4158a52a27 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -1357,6 +1357,7 @@ handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) -> report -> Msg = lists:flatten( io_lib:format( + "*** SSH: " "Unexpected message '~p' received in state '~p'\n" "Role: ~p\n" "Peer: ~p\n" @@ -1365,7 +1366,7 @@ handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) -> StateName, Ssh#ssh.role, Ssh#ssh.peer, - ?GET_INTERNAL_OPT(address, Ssh#ssh.opts)])), + ?GET_INTERNAL_OPT(address, Ssh#ssh.opts, undefined)])), error_logger:info_report(Msg), keep_state_and_data; @@ -1374,7 +1375,8 @@ handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) -> Other -> Msg = lists:flatten( - io_lib:format("Call to fun in 'unexpectedfun' failed:~n" + io_lib:format("*** SSH: " + "Call to fun in 'unexpectedfun' failed:~n" "Return: ~p\n" "Message: ~p\n" "Role: ~p\n" @@ -1383,8 +1385,8 @@ handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) -> [Other, UnexpectedMessage, Ssh#ssh.role, - element(2,Ssh#ssh.peer), - ?GET_INTERNAL_OPT(address, Ssh#ssh.opts)] + Ssh#ssh.peer, + ?GET_INTERNAL_OPT(address, Ssh#ssh.opts, undefined)] )), error_logger:error_report(Msg), keep_state_and_data diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index c48c0800e4..0052347912 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -251,9 +251,9 @@ key_exchange_init_msg(Ssh0) -> {SshPacket, Ssh} = ssh_packet(Msg, Ssh0), {Msg, SshPacket, Ssh}. -kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs}) -> +kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs} = Ssh) -> Random = ssh_bits:random(16), - PrefAlgs = ?GET_OPT(preferred_algorithms, Opts), + PrefAlgs = adjust_algs_for_peer_version(Role, ?GET_OPT(preferred_algorithms, Opts), Ssh), kexinit_message(Role, Random, PrefAlgs, HostKeyAlgs, Opts). key_init(client, Ssh, Value) -> @@ -261,7 +261,22 @@ key_init(client, Ssh, Value) -> key_init(server, Ssh, Value) -> Ssh#ssh{s_keyinit = Value}. - +adjust_algs_for_peer_version(client, PrefAlgs, #ssh{s_version=V}) -> + adjust_algs_for_peer_version(V, PrefAlgs); +adjust_algs_for_peer_version(server, PrefAlgs, #ssh{c_version=V}) -> + adjust_algs_for_peer_version(V, PrefAlgs). +%% +adjust_algs_for_peer_version("SSH-2.0-OpenSSH_6.2"++_, PrefAlgs) -> + C0 = proplists:get_value(cipher, PrefAlgs, same([])), + C = [{D,L} || D <- [client2server, server2client], + L <- [[K || K <- proplists:get_value(D, C0, []), + K =/= '[email protected]', + K =/= '[email protected]']] + ], + lists:keyreplace(cipher, 1, PrefAlgs, {cipher,C}); +adjust_algs_for_peer_version(_, PrefAlgs) -> + PrefAlgs. + kexinit_message(Role, Random, Algs, HostKeyAlgs, Opts) -> #ssh_msg_kexinit{ cookie = Random, diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index c201e70d82..5154658e8a 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.6 +SSH_VSN = 4.6.1 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/otp_versions.table b/otp_versions.table index c70a2c44d3..6580a6e127 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-20.1.1 : compiler-7.1.3 erts-9.1.1 ssh-4.6.1 # asn1-5.0.3 common_test-1.15.2 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 crypto-4.1 debugger-4.2.3 dialyzer-3.2.2 diameter-2.1 edoc-0.9.1 eldap-1.2.2 erl_docgen-0.7.1 erl_interface-3.10 et-1.6.1 eunit-2.3.4 hipe-3.16.1 ic-4.4.2 inets-6.4.2 jinterface-1.8 kernel-5.4 megaco-3.18.2 mnesia-4.15.1 observer-2.5 odbc-2.12 orber-3.8.3 os_mon-2.4.3 otp_mibs-1.1.1 parsetools-2.1.5 public_key-1.5 reltool-0.7.5 runtime_tools-1.12.2 sasl-3.1 snmp-5.2.7 ssl-8.2.1 stdlib-3.4.2 syntax_tools-2.1.3 tools-2.11 wx-1.8.2 xmerl-1.3.15 : OTP-20.1 : asn1-5.0.3 common_test-1.15.2 compiler-7.1.2 crypto-4.1 debugger-4.2.3 dialyzer-3.2.2 diameter-2.1 edoc-0.9.1 erl_docgen-0.7.1 erts-9.1 et-1.6.1 eunit-2.3.4 hipe-3.16.1 inets-6.4.2 kernel-5.4 mnesia-4.15.1 observer-2.5 os_mon-2.4.3 public_key-1.5 reltool-0.7.5 runtime_tools-1.12.2 sasl-3.1 snmp-5.2.7 ssh-4.6 ssl-8.2.1 stdlib-3.4.2 syntax_tools-2.1.3 tools-2.11 wx-1.8.2 # cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 eldap-1.2.2 erl_interface-3.10 ic-4.4.2 jinterface-1.8 megaco-3.18.2 odbc-2.12 orber-3.8.3 otp_mibs-1.1.1 parsetools-2.1.5 xmerl-1.3.15 : OTP-20.0.5 : erts-9.0.5 inets-6.4.1 # asn1-5.0.2 common_test-1.15.1 compiler-7.1.1 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 crypto-4.0 debugger-4.2.2 dialyzer-3.2.1 diameter-2.0 edoc-0.9 eldap-1.2.2 erl_docgen-0.7 erl_interface-3.10 et-1.6 eunit-2.3.3 hipe-3.16 ic-4.4.2 jinterface-1.8 kernel-5.3.1 megaco-3.18.2 mnesia-4.15 observer-2.4 odbc-2.12 orber-3.8.3 os_mon-2.4.2 otp_mibs-1.1.1 parsetools-2.1.5 public_key-1.4.1 reltool-0.7.4 runtime_tools-1.12.1 sasl-3.0.4 snmp-5.2.6 ssh-4.5.1 ssl-8.2 stdlib-3.4.1 syntax_tools-2.1.2 tools-2.10.1 wx-1.8.1 xmerl-1.3.15 : OTP-20.0.4 : dialyzer-3.2.1 erts-9.0.4 # asn1-5.0.2 common_test-1.15.1 compiler-7.1.1 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 crypto-4.0 debugger-4.2.2 diameter-2.0 edoc-0.9 eldap-1.2.2 erl_docgen-0.7 erl_interface-3.10 et-1.6 eunit-2.3.3 hipe-3.16 ic-4.4.2 inets-6.4 jinterface-1.8 kernel-5.3.1 megaco-3.18.2 mnesia-4.15 observer-2.4 odbc-2.12 orber-3.8.3 os_mon-2.4.2 otp_mibs-1.1.1 parsetools-2.1.5 public_key-1.4.1 reltool-0.7.4 runtime_tools-1.12.1 sasl-3.0.4 snmp-5.2.6 ssh-4.5.1 ssl-8.2 stdlib-3.4.1 syntax_tools-2.1.2 tools-2.10.1 wx-1.8.1 xmerl-1.3.15 : |