From 4df8cf1f67a12d2c730e85ab4de64b6fd7557050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Tue, 7 May 2019 11:39:34 +0200 Subject: [PATCH 01/73] kernel: Force synchronous port_commands in user/user_drv Banging data to a local port was always synchronous prior to Erlang/OTP R16, and these modules relied on that behavior to report that data had successfully been enqueued on the stdout port. This would cause data to be silently dropped if the command didn't run synchronously and the emulator halted before the port received the data. This was fairly rare in practice, but could be seen from time to time on Windows with escripts that ended with a call to io:format/2, such as the one used by the escript_SUITE:create_and_extract test. This is a minimal band-aid to make things reliable again. A more complete fix would add explicit synchronization with the port. --- lib/kernel/src/user.erl | 3 ++- lib/kernel/src/user_drv.erl | 37 ++++++++++++++++--------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/lib/kernel/src/user.erl b/lib/kernel/src/user.erl index 0c9e1ea3035..5a3487a9bae 100644 --- a/lib/kernel/src/user.erl +++ b/lib/kernel/src/user.erl @@ -296,7 +296,8 @@ io_requests([], Stat, _) -> %% port. put_port(List, Port) -> - send_port(Port, {command, List}). + true = port_command(Port, List), + ok. %% send_port(Port, Command) diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl index 69ff8e7971e..644aa752b6e 100644 --- a/lib/kernel/src/user_drv.erl +++ b/lib/kernel/src/user_drv.erl @@ -543,19 +543,14 @@ set_unicode_state(Iport, Bool) -> %% io_request(Request, InPort, OutPort) %% io_requests(Requests, InPort, OutPort) %% Note: InPort is unused. - -io_request(Request, Iport, Oport) -> - try io_command(Request) of - {command,_} = Command -> - Oport ! {self(),Command}, - ok; - {Command,Reply} -> - Oport ! {self(),Command}, - Reply - catch - {requests,Rs} -> - io_requests(Rs, Iport, Oport); - _ -> +io_request({requests,Rs}, Iport, Oport) -> + io_requests(Rs, Iport, Oport); +io_request(Request, _Iport, Oport) -> + case io_command(Request) of + {Data, Reply} -> + true = port_command(Oport, Data), + Reply; + unhandled -> ok end. @@ -575,19 +570,19 @@ put_int16(N, Tail) -> %% to the console before the vm stops when calling erlang:halt(integer()). -dialyzer({no_improper_lists, io_command/1}). io_command({put_chars_sync, unicode,Cs,Reply}) -> - {{command,[?OP_PUTC_SYNC|unicode:characters_to_binary(Cs,utf8)]},Reply}; + {[?OP_PUTC_SYNC|unicode:characters_to_binary(Cs,utf8)], Reply}; io_command({put_chars, unicode,Cs}) -> - {command,[?OP_PUTC|unicode:characters_to_binary(Cs,utf8)]}; + {[?OP_PUTC|unicode:characters_to_binary(Cs,utf8)], ok}; io_command({move_rel,N}) -> - {command,[?OP_MOVE|put_int16(N, [])]}; + {[?OP_MOVE|put_int16(N, [])], ok}; io_command({insert_chars,unicode,Cs}) -> - {command,[?OP_INSC|unicode:characters_to_binary(Cs,utf8)]}; + {[?OP_INSC|unicode:characters_to_binary(Cs,utf8)], ok}; io_command({delete_chars,N}) -> - {command,[?OP_DELC|put_int16(N, [])]}; + {[?OP_DELC|put_int16(N, [])], ok}; io_command(beep) -> - {command,[?OP_BEEP]}; -io_command(Else) -> - throw(Else). + {[?OP_BEEP], ok}; +io_command(_) -> + unhandled. %% gr_new() %% gr_get_num(Group, Index) From 529aec04776dcead1eb7b7fe3ff975d7538cfa5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Mon, 13 May 2019 09:20:44 +0200 Subject: [PATCH 02/73] erts: Fix buffer overflow in xxx_to_existing_atom --- erts/emulator/beam/atom.c | 77 ++++++++++++++++++++++++-------- erts/emulator/beam/atom.h | 8 ++-- erts/emulator/test/bif_SUITE.erl | 10 +++++ 3 files changed, 73 insertions(+), 22 deletions(-) diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c index 38e02c386f9..8c7d04e1fd7 100644 --- a/erts/emulator/beam/atom.c +++ b/erts/emulator/beam/atom.c @@ -202,11 +202,15 @@ atom_free(Atom* obj) ASSERT(obj->slot.index == atom_val(am_ErtsSecretAtom)); } -static void latin1_to_utf8(byte* conv_buf, const byte** srcp, int* lenp) +static void latin1_to_utf8(byte* conv_buf, Uint buf_sz, + const byte** srcp, Uint* lenp) { byte* dst; const byte* src = *srcp; - int i, len = *lenp; + Uint i, len = *lenp; + + ASSERT(len <= MAX_ATOM_CHARACTERS); + ASSERT(buf_sz >= MAX_ATOM_SZ_FROM_LATIN1); for (i=0 ; i < len; ++i) { if (src[i] & 0x80) { @@ -236,11 +240,11 @@ static void latin1_to_utf8(byte* conv_buf, const byte** srcp, int* lenp) * erts_atom_put_index() may fail. Returns negative indexes for errors. */ int -erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) +erts_atom_put_index(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc) { byte utf8_copy[MAX_ATOM_SZ_FROM_LATIN1]; const byte *text = name; - int tlen = len; + Uint tlen; Sint no_latin1_chars; Atom a; int aix; @@ -249,13 +253,16 @@ erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) erts_smp_atomic_inc_nob(&atom_put_ops); #endif - if (tlen < 0) { - if (trunc) - tlen = 0; - else - return ATOM_MAX_CHARS_ERROR; + if (len < 0) { + if (trunc) { + len = 0; + } else { + return ATOM_MAX_CHARS_ERROR; + } } + tlen = len; + switch (enc) { case ERTS_ATOM_ENC_7BIT_ASCII: if (tlen > MAX_ATOM_CHARACTERS) { @@ -279,7 +286,7 @@ erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) return ATOM_MAX_CHARS_ERROR; } no_latin1_chars = tlen; - latin1_to_utf8(utf8_copy, &text, &tlen); + latin1_to_utf8(utf8_copy, sizeof(utf8_copy), &text, &tlen); break; case ERTS_ATOM_ENC_UTF8: /* First sanity check; need to verify later */ @@ -340,7 +347,7 @@ erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) * erts_atom_put() may fail. If it fails THE_NON_VALUE is returned! */ Eterm -erts_atom_put(const byte *name, int len, ErtsAtomEncoding enc, int trunc) +erts_atom_put(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc) { int aix = erts_atom_put_index(name, len, enc, trunc); if (aix >= 0) @@ -350,7 +357,7 @@ erts_atom_put(const byte *name, int len, ErtsAtomEncoding enc, int trunc) } Eterm -am_atom_put(const char* name, int len) +am_atom_put(const char* name, Sint len) { /* Assumes 7-bit ascii; use erts_atom_put() for other encodings... */ return erts_atom_put((byte *) name, len, ERTS_ATOM_ENC_7BIT_ASCII, 1); @@ -389,23 +396,57 @@ int atom_table_sz(void) } int -erts_atom_get(const char *name, int len, Eterm* ap, ErtsAtomEncoding enc) +erts_atom_get(const char *name, Uint len, Eterm* ap, ErtsAtomEncoding enc) { byte utf8_copy[MAX_ATOM_SZ_FROM_LATIN1]; Atom a; int i; int res; - a.len = (Sint16) len; - a.name = (byte *)name; - if (enc == ERTS_ATOM_ENC_LATIN1) { - latin1_to_utf8(utf8_copy, (const byte**)&a.name, &len); - a.len = (Sint16) len; + switch (enc) { + case ERTS_ATOM_ENC_LATIN1: + if (len > MAX_ATOM_CHARACTERS) { + return 0; + } + + latin1_to_utf8(utf8_copy, sizeof(utf8_copy), (const byte**)&name, &len); + + a.name = (byte*)name; + a.len = (Sint16)len; + break; + case ERTS_ATOM_ENC_7BIT_ASCII: + if (len > MAX_ATOM_CHARACTERS) { + return 0; + } + + for (i = 0; i < len; i++) { + if (name[i] & 0x80) { + return 0; + } + } + + a.len = (Sint16)len; + a.name = (byte*)name; + break; + case ERTS_ATOM_ENC_UTF8: + if (len > MAX_ATOM_SZ_LIMIT) { + return 0; + } + + /* We don't need to check whether the encoding is legal as all atom + * names are stored as UTF-8 and we know a lookup with a badly encoded + * name will fail. */ + + a.len = (Sint16)len; + a.name = (byte*)name; + break; } + atom_read_lock(); i = index_get(&erts_atom_table, (void*) &a); res = i < 0 ? 0 : (*ap = make_atom(i), 1); atom_read_unlock(); + return res; } diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h index 385120a8d91..bc8219120c6 100644 --- a/erts/emulator/beam/atom.h +++ b/erts/emulator/beam/atom.h @@ -133,14 +133,14 @@ typedef enum { int atom_table_size(void); /* number of elements */ int atom_table_sz(void); /* table size in bytes, excluding stored objects */ -Eterm am_atom_put(const char*, int); /* ONLY 7-bit ascii! */ -Eterm erts_atom_put(const byte *name, int len, ErtsAtomEncoding enc, int trunc); -int erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc); +Eterm am_atom_put(const char*, Sint); /* ONLY 7-bit ascii! */ +Eterm erts_atom_put(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc); +int erts_atom_put_index(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc); void init_atom_table(void); void atom_info(fmtfn_t, void *); void dump_atoms(fmtfn_t, void *); Uint erts_get_atom_limit(void); -int erts_atom_get(const char* name, int len, Eterm* ap, ErtsAtomEncoding enc); +int erts_atom_get(const char* name, Uint len, Eterm* ap, ErtsAtomEncoding enc); void erts_atom_get_text_space_sizes(Uint *reserved, Uint *used); #endif diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index 04b7f2de159..b9d078ff99b 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -592,6 +592,16 @@ binary_to_existing_atom(Config) when is_list(Config) -> UnlikelyAtom = binary_to_atom(id(UnlikelyBin), latin1), UnlikelyAtom = binary_to_existing_atom(UnlikelyBin, latin1), + + %% ERL-944; a binary that was too large would overflow the latin1-to-utf8 + %% conversion buffer. + OverflowAtom = <<0:511/unit:8, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133>>, + {'EXIT', _} = (catch binary_to_existing_atom(OverflowAtom, latin1)), + ok. From c87913e32fd271c1d2c7b872d55f0108430ff48c Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 8 May 2019 10:39:20 +0200 Subject: [PATCH 03/73] ssl: Remove legacy calls to next_record Conflicts: lib/ssl/src/dtls_connection.erl lib/ssl/src/ssl_connection.erl --- lib/ssl/src/dtls_connection.erl | 8 ++++---- lib/ssl/src/tls_connection.erl | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index e0700069003..6928d7a93d5 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -51,7 +51,7 @@ -export([encode_alert/3, send_alert/2, send_alert_in_connection/2, close/5, protocol_name/0]). %% Data handling --export([next_record/1, socket/4, setopts/3, getopts/3]). +-export([socket/4, setopts/3, getopts/3]). %% gen_statem state functions -export([init/3, error/3, downgrade/3, %% Initiation and take down states @@ -451,11 +451,11 @@ init({call, From}, {start, Timeout}, HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions), State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}), {State2, Actions} = send_handshake(Hello, State1#state{connection_env = CEnv#connection_env{negotiated_version = HelloVersion}}), - State3 = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion + State = State2#state{connection_env = CEnv#connection_env{negotiated_version = Version}, %% RequestedVersion session = Session0#session{session_id = Hello#client_hello.session_id}, start_or_recv_from = From}, - next_event(hello, no_record, State3, [{{timeout, handshake}, Timeout, close} | Actions]); + next_event(hello, no_record, State, [{{timeout, handshake}, Timeout, close} | Actions]); init({call, _} = Type, Event, #state{static_env = #static_env{role = server}, protocol_specific = PS} = State) -> Result = gen_handshake(?FUNCTION_NAME, Type, Event, @@ -514,7 +514,7 @@ hello(internal, #client_hello{cookie = <<>>, VerifyRequest = dtls_handshake:hello_verify_request(Cookie, ?HELLO_VERIFY_REQUEST_VERSION), State1 = prepare_flight(State0#state{connection_env = CEnv#connection_env{negotiated_version = Version}}), {State, Actions} = send_handshake(VerifyRequest, State1), - next_event(?FUNCTION_NAME, no_record, + next_event(?FUNCTION_NAME, no_record, State#state{handshake_env = HsEnv#handshake_env{ tls_handshake_history = ssl_handshake:init_handshake_history()}}, diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index a05858221a8..a394c88fc05 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -62,7 +62,7 @@ close/5, protocol_name/0]). %% Data handling --export([next_record/1, socket/4, setopts/3, getopts/3]). +-export([socket/4, setopts/3, getopts/3]). %% gen_statem state functions -export([init/3, error/3, downgrade/3, %% Initiation and take down states From 2d217a647e6d4a14aac679a8cd05d48703fc56d5 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 8 May 2019 11:35:55 +0200 Subject: [PATCH 04/73] ssl: Internal active n must back off when user does not read data TLS connections should not buffer too much application data if they want to benefit from TCP flow control. Certain applications may want to customize the value of internal_active_n as there is a tradeoff between buffering memory and throughput. Conflicts: lib/ssl/src/tls_connection.erl --- lib/ssl/src/tls_connection.erl | 93 ++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index a394c88fc05..0b477b7c81f 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -161,32 +161,60 @@ pids(#state{protocol_specific = #{sender := Sender}}) -> %%==================================================================== %% State transition handling %%==================================================================== -next_record(#state{handshake_env = +next_record(_, #state{handshake_env = #handshake_env{unprocessed_handshake_events = N} = HsEnv} = State) when N > 0 -> {no_record, State#state{handshake_env = HsEnv#handshake_env{unprocessed_handshake_events = N-1}}}; -next_record(#state{protocol_buffers = - #protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts}, - connection_states = ConnectionStates, - ssl_options = #ssl_options{padding_check = Check}} = State) -> +next_record(_, #state{protocol_buffers = + #protocol_buffers{tls_cipher_texts = [_|_] = CipherTexts}, + connection_states = ConnectionStates, + ssl_options = #ssl_options{padding_check = Check}} = State) -> next_record(State, CipherTexts, ConnectionStates, Check); -next_record(#state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, - protocol_specific = #{active_n_toggle := true, active_n := N} = ProtocolSpec, - static_env = #static_env{socket = Socket, - close_tag = CloseTag, - transport_cb = Transport} - } = State) -> - case tls_socket:setopts(Transport, Socket, [{active, N}]) of - ok -> - {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}}; - _ -> - self() ! {CloseTag, Socket}, - {no_record, State} - end; -next_record(State) -> +next_record(connection, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, + protocol_specific = #{active_n_toggle := true} + } = State) -> + %% If ssl application user is not reading data wait to activate socket + flow_ctrl(State); + +next_record(_, #state{protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, + protocol_specific = #{active_n_toggle := true} + } = State) -> + activate_socket(State); +next_record(_, State) -> {no_record, State}. + +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = undefined} = State) when Size =/= 0 -> + {no_record, State}; +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = 0} = State) when Size =/= 0 -> + {no_record, State}; +flow_ctrl(#state{user_data_buffer = {_,Size,_}, + socket_options = #socket_options{active = false}, + bytes_to_read = BytesToRead} = State) when (Size >= BytesToRead) andalso + (BytesToRead > 0) -> + {no_record, State}; +flow_ctrl(State) -> + activate_socket(State). + + +activate_socket(#state{protocol_specific = #{active_n_toggle := true, active_n := N} = ProtocolSpec, + static_env = #static_env{socket = Socket, + close_tag = CloseTag, + transport_cb = Transport} + } = State) -> + case tls_socket:setopts(Transport, Socket, [{active, N}]) of + ok -> + {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}}; + _ -> + self() ! {CloseTag, Socket}, + {no_record, State} + end. + %% Decipher next record and concatenate consecutive ?APPLICATION_DATA records into one %% next_record(State, CipherTexts, ConnectionStates, Check) -> @@ -224,31 +252,20 @@ next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, Connec State#state{protocol_buffers = Buffers#protocol_buffers{tls_cipher_texts = CipherTexts}, connection_states = ConnectionStates}}. - next_event(StateName, Record, State) -> next_event(StateName, Record, State, []). %% next_event(StateName, no_record, State0, Actions) -> - case next_record(State0) of + case next_record(StateName, State0) of {no_record, State} -> {next_state, StateName, State, Actions}; - {#ssl_tls{} = Record, State} -> - {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; - #alert{} = Alert -> - Version = State0#state.connection_env#connection_env.negotiated_version, - ssl_connection:handle_own_alert(Alert, Version, StateName, State0) + {Record, State} -> + next_event(StateName, Record, State, Actions) end; -next_event(StateName, Record, State, Actions) -> - case Record of - no_record -> - {next_state, StateName, State, Actions}; - #ssl_tls{} = Record -> - {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; - #alert{} = Alert -> - Version = State#state.connection_env#connection_env.negotiated_version, - ssl_connection:handle_own_alert(Alert, Version, StateName, State) - end. - +next_event(StateName, #ssl_tls{} = Record, State, Actions) -> + {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; +next_event(StateName, #alert{} = Alert, State, Actions) -> + {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}. %%% TLS record protocol level application data messages handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, @@ -1049,7 +1066,7 @@ next_tls_record(Data, StateName, case tls_record:get_tls_records(Data, Versions, Buf0, SslOpts) of {Records, Buf1} -> CT1 = CT0 ++ Records, - next_record(State0#state{protocol_buffers = + next_record(StateName, State0#state{protocol_buffers = Buffers#protocol_buffers{tls_record_buffer = Buf1, tls_cipher_texts = CT1}}); #alert{} = Alert -> From 4ae8ae5d17577b8a65e6367ed18af6a1d7f9187c Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 8 May 2019 13:45:46 +0200 Subject: [PATCH 05/73] ssl: Add test cases for issue reported in ERL-938 --- lib/ssl/test/ssl_payload_SUITE.erl | 157 +++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl index 27b9c258a08..2d0ffd03d70 100644 --- a/lib/ssl/test/ssl_payload_SUITE.erl +++ b/lib/ssl/test/ssl_payload_SUITE.erl @@ -48,21 +48,27 @@ groups() -> payload_tests() -> [server_echos_passive_small, + server_echos_passive_chunk_small, server_echos_active_once_small, server_echos_active_small, client_echos_passive_small, + client_echos_passive_chunk_small, client_echos_active_once_small, client_echos_active_small, server_echos_passive_big, + server_echos_passive_chunk_big, server_echos_active_once_big, server_echos_active_big, client_echos_passive_big, + client_echos_passive_chunk_big, client_echos_active_once_big, client_echos_active_big, server_echos_passive_huge, + server_echos_passive_chunk_huge, server_echos_active_once_huge, server_echos_active_huge, client_echos_passive_huge, + client_echos_passive_chunk_huge, client_echos_active_once_huge, client_echos_active_huge, client_active_once_server_close]. @@ -109,9 +115,11 @@ end_per_group(GroupName, Config) -> init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge; + TestCase == server_echos_passive_chunk_huge; TestCase == server_echos_active_once_huge; TestCase == server_echos_active_huge; TestCase == client_echos_passive_huge; + TestCase == client_echos_passive_chunk_huge; TestCase == client_echos_active_once_huge; TestCase == client_echos_active_huge -> case erlang:system_info(system_architecture) of @@ -124,9 +132,11 @@ init_per_testcase(TestCase, Config) init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_big; + TestCase == server_echos_passive_chunk_big; TestCase == server_echos_active_once_big; TestCase == server_echos_active_big; TestCase == client_echos_passive_big; + TestCase == client_echos_passive_chunk_big; TestCase == client_echos_active_once_big; TestCase == client_echos_active_big -> ct:timetrap({seconds, 60}), @@ -157,6 +167,22 @@ server_echos_passive_small(Config) when is_list(Config) -> %%-------------------------------------------------------------------- +server_echos_passive_chunk_small() -> + [{doc, "Client sends 1000 bytes in passive mode to server, that receives them in chunks, " + "sends them back, and closes."}]. + +server_echos_passive_chunk_small(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 100), + server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + + +%%-------------------------------------------------------------------- + server_echos_active_once_small() -> [{doc, "Client sends 1000 bytes in active once mode to server, that receives " " them, sends them back, and closes."}]. @@ -199,6 +225,21 @@ client_echos_passive_small(Config) when is_list(Config) -> client_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). +%%-------------------------------------------------------------------- +client_echos_passive_chunk__small() -> + [{doc, "Server sends 1000 bytes in passive mode to client, that receives them in chunks, " + "sends them back, and closes."}]. + +client_echos_passive_chunk_small(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 100), + client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + + %%-------------------------------------------------------------------- client_echos_active_once_small() -> ["Server sends 1000 bytes in active once mode to client, that receives " @@ -241,6 +282,19 @@ server_echos_passive_big(Config) when is_list(Config) -> Data = binary:copy(<<"1234567890">>, 5000), server_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). +%%-------------------------------------------------------------------- +server_echos_passive_chunk_big() -> + [{doc, "Client sends 50000 bytes to server in passive mode, that receives them, " + "sends them back, and closes."}]. + +server_echos_passive_chunk_big(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 5000), + server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). %%-------------------------------------------------------------------- @@ -286,6 +340,22 @@ client_echos_passive_big(Config) when is_list(Config) -> client_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + +%%-------------------------------------------------------------------- +client_echos_passive_chunk_big() -> + [{doc, "Server sends 50000 bytes to client in passive mode, that receives them, " + "sends them back, and closes."}]. + +client_echos_passive_chunk_big(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 5000), + client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + + %%-------------------------------------------------------------------- client_echos_active_once_big() -> [{doc, "Server sends 50000 bytes to client in active once mode, that receives" @@ -328,6 +398,20 @@ server_echos_passive_huge(Config) when is_list(Config) -> server_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). +%%-------------------------------------------------------------------- +server_echos_passive_chunk_huge() -> + [{doc, "Client sends 500000 bytes to server in passive mode, that receives " + " them, sends them back, and closes."}]. + +server_echos_passive_chunk_huge(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 50000), + server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). + %%-------------------------------------------------------------------- server_echos_active_once_huge() -> [{doc, "Client sends 500000 bytes to server in active once mode, that receives " @@ -369,7 +453,19 @@ client_echos_passive_huge(Config) when is_list(Config) -> Data = binary:copy(<<"1234567890">>, 50000), client_echos_passive( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). +%%-------------------------------------------------------------------- +client_echos_passive_chunk_huge() -> + [{doc, "Server sends 500000 bytes to client in passive mode, that receives " + "them, sends them back, and closes."}]. +client_echos_passive_chunk_huge(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + %% + Data = binary:copy(<<"1234567890">>, 50000), + client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname). %%-------------------------------------------------------------------- client_echos_active_once_huge() -> [{doc, "Server sends 500000 bytes to client in active once mode, that receives " @@ -442,6 +538,28 @@ server_echos_passive( ssl_test_lib:close(Server), ssl_test_lib:close(Client). +server_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> + Length = byte_size(Data), + Server = + ssl_test_lib:start_server( + [{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, echoer_chunk, [Length]}}, + {options, [{active, false}, {mode, binary} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client( + [{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, sender, [Data]}}, + {options, [{active, false}, {mode, binary} | ClientOpts]}]), + %% + ssl_test_lib:check_result(Server, ok, Client, ok), + %% + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). server_echos_active_once( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> @@ -513,6 +631,31 @@ client_echos_passive( ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +client_echos_passive_chunk( + Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> + Length = byte_size(Data), + Server = + ssl_test_lib:start_server( + [{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, sender, [Data]}}, + {options, [{active, false}, {mode, binary} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client( + [{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, echoer_chunk, [Length]}}, + {options, [{active, false}, {mode, binary} | ClientOpts]}]), + %% + ssl_test_lib:check_result(Server, ok, Client, ok), + %% + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + client_echos_active_once( Data, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> Length = byte_size(Data), @@ -615,6 +758,10 @@ echoer(Socket, Size) -> ct:log("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]), echo_recv(Socket, Size * 100). +echoer_chunk(Socket, Size) -> + ct:log("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]), + echo_recv_chunk(Socket, Size, Size * 100). + echoer_active_once(Socket, Size) -> ct:log("Echoer active once: ~p~n", [ssl:getopts(Socket, [active])]), echo_active_once(Socket, Size * 100). @@ -632,6 +779,16 @@ echo_recv(Socket, Size) -> ok = ssl:send(Socket, Data), echo_recv(Socket, Size - byte_size(Data)). + +%% Receive Size bytes +echo_recv_chunk(_Socket, _, 0) -> + ok; +echo_recv_chunk(Socket, ChunkSize, Size) -> + {ok, Data} = ssl:recv(Socket, ChunkSize), + ok = ssl:send(Socket, Data), + echo_recv_chunk(Socket, ChunkSize, Size - ChunkSize). + + %% Receive Size bytes echo_active_once(_Socket, 0) -> ok; From 12f93cc0a3615e414b3e1df0602f3548fb31c05c Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 9 May 2019 07:43:30 +0200 Subject: [PATCH 06/73] ssl: Avoid dialyzer warning Maybe we should only have specs for external APIs?! This is a how to write spec problem that we have to address later. --- lib/ssl/src/ssl_handshake.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 7b34991f4f9..f68d3e9b261 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -98,8 +98,8 @@ hello_request() -> #hello_request{}. %%-------------------------------------------------------------------- --spec server_hello(binary(), ssl_record:ssl_version(), ssl_record:connection_states(), - Extension::map()) -> #server_hello{}. +%%-spec server_hello(binary(), ssl_record:ssl_version(), ssl_record:connection_states(), +%% Extension::map()) -> #server_hello{}. %% %% Description: Creates a server hello message. %%-------------------------------------------------------------------- From 319dcabd1104b2a2befc46b9f49446a5f6485008 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 14 May 2019 17:08:26 +0200 Subject: [PATCH 07/73] ssl: Refactor of OTP 22 code due to patch OTP-15823 --- lib/ssl/src/tls_connection.erl | 8 ++----- lib/ssl/src/tls_connection_1_3.erl | 35 ++++++++++++------------------ 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 0b477b7c81f..61281a3fb2a 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -289,12 +289,8 @@ handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, Stat {stop, _, _} = Stop-> Stop; {Record, State1} -> - case next_event(StateName, Record, State1) of - {next_state, StateName, State, Actions} -> - ssl_connection:hibernate_after(StateName, State, Actions); - {stop, _, _} = Stop -> - Stop - end + {next_state, StateName, State, Actions} = next_event(StateName, Record, State1), + ssl_connection:hibernate_after(StateName, State, Actions) end; %%% TLS record protocol level handshake messages handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data}, diff --git a/lib/ssl/src/tls_connection_1_3.erl b/lib/ssl/src/tls_connection_1_3.erl index 701a5860c2e..76cdebc76f1 100644 --- a/lib/ssl/src/tls_connection_1_3.erl +++ b/lib/ssl/src/tls_connection_1_3.erl @@ -116,9 +116,8 @@ ]). -start(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +start(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); start(internal, #client_hello{} = Hello, State0, _Module) -> case tls_handshake_1_3:do_start(Hello, State0) of #alert{} = Alert -> @@ -132,9 +131,8 @@ start(Type, Msg, State, Connection) -> ssl_connection:handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). -negotiated(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +negotiated(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); negotiated(internal, Message, State0, _Module) -> case tls_handshake_1_3:do_negotiated(Message, State0) of #alert{} = Alert -> @@ -144,41 +142,36 @@ negotiated(internal, Message, State0, _Module) -> end. -wait_cert(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +wait_cert(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); wait_cert(internal, #certificate_1_3{} = Certificate, State0, _Module) -> case tls_handshake_1_3:do_wait_cert(Certificate, State0) of {#alert{} = Alert, State} -> ssl_connection:handle_own_alert(Alert, {3,4}, wait_cert, State); - {State1, NextState} -> - {Record, State} = tls_connection:next_record(State1), - tls_connection:next_event(NextState, Record, State) + {State, NextState} -> + tls_connection:next_event(NextState, no_record, State) end; wait_cert(Type, Msg, State, Connection) -> ssl_connection:handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). -wait_cv(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +wait_cv(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); wait_cv(internal, #certificate_verify_1_3{} = CertificateVerify, State0, _Module) -> case tls_handshake_1_3:do_wait_cv(CertificateVerify, State0) of {#alert{} = Alert, State} -> ssl_connection:handle_own_alert(Alert, {3,4}, wait_cv, State); - {State1, NextState} -> - {Record, State} = tls_connection:next_record(State1), - tls_connection:next_event(NextState, Record, State) + {State, NextState} -> + tls_connection:next_event(NextState, no_record, State) end; wait_cv(Type, Msg, State, Connection) -> ssl_connection:handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). -wait_finished(internal, #change_cipher_spec{}, State0, _Module) -> - {Record, State} = tls_connection:next_record(State0), - tls_connection:next_event(?FUNCTION_NAME, Record, State); +wait_finished(internal, #change_cipher_spec{}, State, _Module) -> + tls_connection:next_event(?FUNCTION_NAME, no_record, State); wait_finished(internal, #finished{} = Finished, State0, Module) -> case tls_handshake_1_3:do_wait_finished(Finished, State0) of From 0088de091165571be1fb7fa5a716ad4634aced83 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 15 May 2019 14:17:16 +0200 Subject: [PATCH 08/73] Prepare release --- lib/ssl/doc/src/notes.xml | 17 +++++ lib/ssl/vsn.mk | 2 +- make/otp_version_tickets | 149 +------------------------------------- 3 files changed, 20 insertions(+), 148 deletions(-) diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 5fdcf15b5f3..b86c9e87981 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,23 @@

This document describes the changes made to the SSL application.

+
SSL 9.3.1 + +
Fixed Bugs and Malfunctions + + +

+ Missing check of size of user_data_buffer made internal + socket behave as an active socket instead of active N. + This could cause memory problems.

+

+ Own Id: OTP-15825 Aux Id: ERL-934, OTP-15823

+
+
+
+ +
+
SSL 9.3
Fixed Bugs and Malfunctions diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 3c66ffd852e..cbc32cd5a88 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.3 +SSL_VSN = 9.3.1 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index 12cf3070e5f..3728402492e 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1,147 +1,2 @@ -OTP-13397 -OTP-13726 -OTP-13819 -OTP-14282 -OTP-14461 -OTP-14625 -OTP-14703 -OTP-14724 -OTP-14731 -OTP-14732 -OTP-14737 -OTP-14792 -OTP-14831 -OTP-14865 -OTP-14894 -OTP-14984 -OTP-15011 -OTP-15055 -OTP-15063 -OTP-15075 -OTP-15095 -OTP-15111 -OTP-15128 -OTP-15129 -OTP-15135 -OTP-15195 -OTP-15200 -OTP-15211 -OTP-15220 -OTP-15238 -OTP-15248 -OTP-15261 -OTP-15262 -OTP-15273 -OTP-15310 -OTP-15323 -OTP-15325 -OTP-15326 -OTP-15336 -OTP-15340 -OTP-15349 -OTP-15351 -OTP-15362 -OTP-15372 -OTP-15373 -OTP-15374 -OTP-15381 -OTP-15383 -OTP-15385 -OTP-15386 -OTP-15427 -OTP-15429 -OTP-15439 -OTP-15440 -OTP-15451 -OTP-15452 -OTP-15456 -OTP-15483 -OTP-15491 -OTP-15496 -OTP-15513 -OTP-15534 -OTP-15535 -OTP-15543 -OTP-15550 -OTP-15563 -OTP-15564 -OTP-15565 -OTP-15571 -OTP-15575 -OTP-15581 -OTP-15588 -OTP-15590 -OTP-15591 -OTP-15596 -OTP-15607 -OTP-15610 -OTP-15611 -OTP-15612 -OTP-15613 -OTP-15615 -OTP-15617 -OTP-15620 -OTP-15621 -OTP-15622 -OTP-15623 -OTP-15626 -OTP-15631 -OTP-15632 -OTP-15633 -OTP-15635 -OTP-15640 -OTP-15641 -OTP-15644 -OTP-15649 -OTP-15655 -OTP-15658 -OTP-15668 -OTP-15672 -OTP-15673 -OTP-15674 -OTP-15677 -OTP-15678 -OTP-15680 -OTP-15683 -OTP-15687 -OTP-15689 -OTP-15691 -OTP-15692 -OTP-15693 -OTP-15694 -OTP-15697 -OTP-15698 -OTP-15699 -OTP-15703 -OTP-15705 -OTP-15707 -OTP-15708 -OTP-15710 -OTP-15712 -OTP-15715 -OTP-15740 -OTP-15746 -OTP-15749 -OTP-15751 -OTP-15752 -OTP-15754 -OTP-15755 -OTP-15756 -OTP-15759 -OTP-15760 -OTP-15761 -OTP-15770 -OTP-15771 -OTP-15773 -OTP-15774 -OTP-15775 -OTP-15776 -OTP-15777 -OTP-15779 -OTP-15782 -OTP-15786 -OTP-15788 -OTP-15791 -OTP-15794 -OTP-15804 -OTP-15806 +OTP-15823 +OTP-15825 From d32991afaf3fc5f9f73e3e2448672bb9a1b80101 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 15 May 2019 14:17:18 +0200 Subject: [PATCH 09/73] Updated OTP version --- OTP_VERSION | 2 +- otp_versions.table | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OTP_VERSION b/OTP_VERSION index b090fe57f61..01c3bca9e33 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0 +22.0.1 diff --git a/otp_versions.table b/otp_versions.table index 101915dc6e2..66136a63dca 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.0.1 : ssl-9.3.1 # asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0 : asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3 stdlib-3.9 syntax_tools-2.2 tools-3.2 wx-1.8.8 xmerl-1.3.21 # diameter-2.2.1 et-1.6.4 eunit-2.3.7 ftp-1.0.2 parsetools-2.1.8 tftp-1.0.1 : OTP-21.3.8 : common_test-1.17.2 eldap-1.2.7 erl_interface-3.11.3 erts-10.3.5 public_key-1.6.6 ssl-9.2.3 stdlib-3.8.2 # asn1-5.0.8 compiler-7.3.2 crypto-4.4.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 erl_docgen-0.9 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 inets-7.0.7 jinterface-1.9.1 kernel-6.3.1 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.6 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 : OTP-21.3.7.1 : erl_interface-3.11.2.1 # asn1-5.0.8 common_test-1.17.1 compiler-7.3.2 crypto-4.4.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 eldap-1.2.6 erl_docgen-0.9 erts-10.3.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 inets-7.0.7 jinterface-1.9.1 kernel-6.3.1 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 public_key-1.6.5 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.6 ssl-9.2.2 stdlib-3.8.1 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 : From cabdef3b97c077119fe6f43538dbdd5cffe9dd91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 20 May 2019 11:54:22 +0200 Subject: [PATCH 10/73] Fix non-terminating compilation The compiler would not terminate while compiling the following code: foo(<>, Tuple, NewValue) -> _ = element(N, Tuple), setelement(N, Tuple, NewValue). The type analysis pass would attempt to construct a huge list when attempting analyse the type of `Tuple` after the call to `setelement/3`. https://bugs.erlang.org/browse/ERL-948 --- lib/compiler/src/beam_ssa_type.erl | 16 +++++++++++----- lib/compiler/test/beam_type_SUITE.erl | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 06b42f1928f..2ea7e89dfa2 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -24,7 +24,7 @@ -include("beam_ssa_opt.hrl"). -import(lists, [all/2,any/2,droplast/1,foldl/3,last/1,member/2, keyfind/3,partition/2,reverse/1,reverse/2, - seq/2,sort/1,split/2]). + sort/1,split/2]). -define(UNICODE_INT, #t_integer{elements={0,16#10FFFF}}). @@ -874,11 +874,11 @@ type(call, [#b_remote{mod=#b_literal{val=Mod}, true -> none end; - {#t_integer{elements={Min,Max}}, + {#t_integer{elements={Min,_}}=IntType, #t_tuple{elements=Es0,size=Size}=T} -> - %% We know this will land between Min and Max, so kill the - %% types for those indexes. - Es = maps:without(seq(Min, Max), Es0), + %% Remove type information for all indices that + %% falls into the range of the integer. + Es = remove_element_info(IntType, Es0), case T#t_tuple.exact of false -> T#t_tuple{elements=Es,size=max(Min, Size)}; @@ -1649,6 +1649,12 @@ get_literal_from_type(nil) -> #b_literal{val=[]}; get_literal_from_type(_) -> none. +remove_element_info(#t_integer{elements={Min,Max}}, Es) -> + foldl(fun(El, Acc) when Min =< El, El =< Max -> + maps:remove(El, Acc); + (_El, Acc) -> Acc + end, Es, maps:keys(Es)). + t_atom() -> #t_atom{elements=any}. diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 882e281a44a..0d1680fb153 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -271,8 +271,22 @@ setelement(_Config) -> T0 = id({a,42}), {a,_} = T0, {b,_} = setelement(1, T0, b), + {z,b} = do_setelement_1(<<(id(1)):32>>, {a,b}, z), + {new,two} = do_setelement_2(<<(id(1)):1>>, {one,two}, new), ok. +do_setelement_1(<>, Tuple, NewValue) -> + _ = element(N, Tuple), + %% While updating the type for Tuple, beam_ssa_type would do: + %% maps:without(lists:seq(0, 4294967295), Elements) + setelement(N, Tuple, NewValue). + +do_setelement_2(<>, Tuple, NewValue) -> + %% Cover the second clause in remove_element_info/2. The + %% type for the second element will be kept. + two = element(2, Tuple), + setelement(N, Tuple, NewValue). + cons(_Config) -> [did] = cons(assigned, did), From 7173fb8984d1822cc9c081f094841fb755f800fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 21 May 2019 14:48:11 +0200 Subject: [PATCH 11/73] Eliminate compiler crash when compiling complex receive statements Certain complex receive statements would result in an internal compiler failure. That would happen when the compiler would fail to find the common exit block following a receive. See the added test case for an example. https://bugs.erlang.org/browse/ERL-950 --- lib/compiler/src/beam_ssa_pre_codegen.erl | 11 ++++++---- lib/compiler/test/receive_SUITE.erl | 26 +++++++++++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index bf99e8fc261..9af72afca7b 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -1415,12 +1415,15 @@ fix_receive([], _Defs, Blocks, Count) -> find_loop_exit([L1,L2|_Ls], Blocks) -> Path1 = beam_ssa:rpo([L1], Blocks), Path2 = beam_ssa:rpo([L2], Blocks), - find_loop_exit_1(reverse(Path1), reverse(Path2), none); + find_loop_exit_1(Path1, cerl_sets:from_list(Path2)); find_loop_exit(_, _) -> none. -find_loop_exit_1([H|T1], [H|T2], _) -> - find_loop_exit_1(T1, T2, H); -find_loop_exit_1(_, _, Exit) -> Exit. +find_loop_exit_1([H|T], OtherPath) -> + case cerl_sets:is_element(H, OtherPath) of + true -> H; + false -> find_loop_exit_1(T, OtherPath) + end; +find_loop_exit_1([], _) -> none. %% find_rm_blocks(StartLabel, Blocks) -> [Label]. %% Find all blocks that start with remove_message within the receive diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index 0038eb1a4b4..752491f0f8a 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -26,7 +26,7 @@ init_per_testcase/2,end_per_testcase/2, export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1, wait/1,recv_in_try/1,double_recv/1,receive_var_zero/1, - match_built_terms/1]). + match_built_terms/1,elusive_common_exit/1]). -include_lib("common_test/include/ct.hrl"). @@ -47,7 +47,7 @@ groups() -> [{p,test_lib:parallel(), [recv,coverage,otp_7980,ref_opt,export,wait, recv_in_try,double_recv,receive_var_zero, - match_built_terms]}]. + match_built_terms,elusive_common_exit]}]. init_per_suite(Config) -> @@ -427,4 +427,26 @@ match_built_terms(Config) when is_list(Config) -> ?MATCH_BUILT_TERM(Ref, <>), ?MATCH_BUILT_TERM(Ref, #{ 1 => A, 2 => B}). +elusive_common_exit(_Config) -> + self() ! {1, a}, + self() ! {2, b}, + {[z], [{2,b},{1,a}]} = elusive_loop([x,y,z], 2, []), + ok. + +elusive_loop(List, 0, Results) -> + {List, Results}; +elusive_loop(List, ToReceive, Results) -> + {Result, RemList} = + receive + {_Pos, _R} = Res when List =/= [] -> + [_H|T] = List, + {Res, T}; + {_Pos, _R} = Res when List =:= [] -> + {Res, []} + end, + %% beam_ssa_pre_codegen:fix_receives() would fail to find + %% the common exit block for this receive. That would mean + %% that it would not insert all necessary copy instructions. + elusive_loop(RemList, ToReceive-1, [Result | Results]). + id(I) -> I. From 2f8ca3885a25ee4d59d0b537e73f5fbe7720b25d Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Tue, 21 May 2019 12:52:21 +0200 Subject: [PATCH 12/73] crypto: Re-enable aes_ctr for openssl cryptolib < 1.0.1 It was accidently disabled in the crypto:supports/0 and /1. It worked however in the encrypt/decrypt functions. --- lib/crypto/c_src/cipher.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c index 00072af6325..0532fb75662 100644 --- a/lib/crypto/c_src/cipher.c +++ b/lib/crypto/c_src/cipher.c @@ -334,6 +334,7 @@ ERL_NIF_TERM cipher_types_as_list(ErlNifEnv* env) continue; if ((p->cipher.p != NULL) || + (p->flags & AES_CTR_COMPAT) || (p->type.atom == atom_aes_ige256)) /* Special handling. Bad indeed... */ { hd = enif_make_list_cell(env, p->type.atom, hd); From 5959fb00182048d50f55d04684723d383d1aeee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 23 May 2019 07:22:41 +0200 Subject: [PATCH 13/73] Fix sticky class in exception When catching an exception re-throwing with a changed class, the class could be changed to the original class if the exception got caught and rethrown in (for example) an after block: sticky_class() -> try try throw(reason) catch throw:Reason:Stack -> erlang:raise(error, Reason, Stack) end after ok end. --- erts/emulator/beam/beam_emu.c | 20 +++++++++++++++ erts/emulator/beam/instrs.tab | 17 ++++++++++--- erts/emulator/test/exception_SUITE.erl | 34 ++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 3af0838794a..ec4f9b4339c 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -422,6 +422,7 @@ static Eterm add_stacktrace(Process* c_p, Eterm Value, Eterm exc); static void save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, ErtsCodeMFA *bif_mfa, Eterm args); static struct StackTrace * get_trace_from_exc(Eterm exc); +static Eterm *get_freason_ptr_from_exc(Eterm exc); static Eterm make_arglist(Process* c_p, Eterm* reg, int a); void @@ -1904,6 +1905,25 @@ static int is_raised_exc(Eterm exc) { } } +static Eterm *get_freason_ptr_from_exc(Eterm exc) { + static Eterm dummy_freason; + struct StackTrace* s; + + if (exc == NIL) { + /* + * Is is not exactly clear when exc can be NIL. Probably only + * when the exception has been generated from native code. + * Return a pointer to an Eterm that can be safely written and + * ignored. + */ + return &dummy_freason; + } else { + ASSERT(is_list(exc)); + s = (struct StackTrace *) big_val(CDR(list_val(exc))); + return &s->freason; + } +} + /* * Creating a list with the argument registers */ diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab index 42c1168f85c..999e9337ff5 100644 --- a/erts/emulator/beam/instrs.tab +++ b/erts/emulator/beam/instrs.tab @@ -951,19 +951,30 @@ raw_raise() { Eterm class = x(0); Eterm value = x(1); Eterm stacktrace = x(2); + Eterm* freason_ptr; + + /* + * Note that the i_raise instruction will override c_p->freason + * with the freason field stored inside the StackTrace struct in + * ftrace. Therefore, we must take care to store the class both + * inside the StackTrace struct and in c_p->freason (important if + * the class is different from the class of the original + * exception). + */ + freason_ptr = get_freason_ptr_from_exc(stacktrace); if (class == am_error) { - c_p->freason = EXC_ERROR & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_ERROR & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; } else if (class == am_exit) { - c_p->freason = EXC_EXIT & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_EXIT & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; } else if (class == am_throw) { - c_p->freason = EXC_THROWN & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_THROWN & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl index aec66cb9a38..6e6f7d78ab4 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -23,6 +23,7 @@ -export([all/0, suite/0, badmatch/1, pending_errors/1, nil_arith/1, top_of_stacktrace/1, stacktrace/1, nested_stacktrace/1, raise/1, gunilla/1, per/1, + change_exception_class/1, exception_with_heap_frag/1, backtrace_depth/1, line_numbers/1]). @@ -43,6 +44,7 @@ suite() -> all() -> [badmatch, pending_errors, nil_arith, top_of_stacktrace, stacktrace, nested_stacktrace, raise, gunilla, per, + change_exception_class, exception_with_heap_frag, backtrace_depth, line_numbers]. -define(try_match(E), @@ -507,6 +509,38 @@ t1(_,X,_) -> t2(_,X,_) -> (X bsl 1) + 1. +change_exception_class(_Config) -> + try + change_exception_class_1(fun() -> throw(arne) end) + catch + error:arne -> + ok; + Class:arne -> + ct:fail({wrong_exception_class,Class}) + end. + +change_exception_class_1(F) -> + try + change_exception_class_2(F) + after + %% The exception would be caught and rethrown using + %% an i_raise instruction. Before the correction + %% of the raw_raise instruction, the change of class + %% would not stick. + io:put_chars("Exception automatically rethrown here\n") + end. + +change_exception_class_2(F) -> + try + F() + catch + throw:Reason:Stack -> + %% Translated to a raw_raise instruction. + %% The change of exception class would not stick + %% if the i_raise instruction was later executed. + erlang:raise(error, Reason, Stack) + end. + %% %% Make sure that even if a BIF builds an heap fragment, then causes an exception, %% the stacktrace term will still be OK (specifically, that it does not contain From 9348c7843af13b13a91a425130a0524b5d9d64c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 24 May 2019 14:09:19 +0200 Subject: [PATCH 14/73] Fix unsafe negative type inference The type optimizer pass (`beam_ssa_type`) could make unsafe negative inferences. That is, incorrectly infer that a variable could *not* have a particular type. This bug was found when adding another optimization. It is not clear how write a failing test case without that added optimization. --- lib/compiler/src/beam_ssa_type.erl | 48 ++++++++++++++++-------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 06b42f1928f..ef42ed29ef3 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -23,7 +23,7 @@ -include("beam_ssa_opt.hrl"). -import(lists, [all/2,any/2,droplast/1,foldl/3,last/1,member/2, - keyfind/3,partition/2,reverse/1,reverse/2, + keyfind/3,reverse/1,reverse/2, seq/2,sort/1,split/2]). -define(UNICODE_INT, #t_integer{elements={0,16#10FFFF}}). @@ -1388,24 +1388,11 @@ get_type(#b_literal{val=Val}, _Ts) -> %% type for L. For example, if L was known to be 'list', subtracting %% 'cons' would give 'nil' as the only possible type. The result of the %% subtraction for L will be added to FailTypes. -%% -%% Here is another example, asking about the variable Bool: -%% -%% Head = bif:hd L -%% Bool = succeeded Head -%% -%% 'succeeded Head' will evaluate to 'true' if the instrution that -%% defined Head succeeded. In this case, it is the 'bif:hd L' -%% instruction, which will succeed if L is 'cons'. Thus, the meet of -%% the previous type for L and 'cons' will be added to SuccTypes. -%% -%% If 'succeeded Head' evaluates to 'false', it means that 'bif:hd L' -%% failed and that L is not 'cons'. 'cons' can be subtracted from the -%% previously known type for L and the result put in FailTypes. infer_types_br(#b_var{}=V, Ts, #d{ds=Ds}) -> #{V:=#b_set{op=Op,args=Args}} = Ds, - Types0 = infer_type(Op, Args, Ds), + PosTypes0 = infer_type(Op, Args, Ds), + NegTypes0 = infer_type_negative(Op, Args, Ds), %% We must be careful with types inferred from '=:='. %% @@ -1416,13 +1403,17 @@ infer_types_br(#b_var{}=V, Ts, #d{ds=Ds}) -> %% %% However, it is safe to subtract a type inferred from '=:=' if %% it is single-valued, e.g. if it is [] or the atom 'true'. - EqTypes0 = infer_eq_type(Op, Args, Ts, Ds), - {Types1,EqTypes} = partition(fun({_,T}) -> - is_singleton_type(T) - end, EqTypes0), - Types = Types1 ++ Types0, - {meet_types(EqTypes++Types, Ts),subtract_types(Types, Ts)}. + EqTypes = infer_eq_type(Op, Args, Ts, Ds), + NegTypes1 = [P || {_,T}=P <- EqTypes, is_singleton_type(T)], + + PosTypes = EqTypes ++ PosTypes0, + SuccTs = meet_types(PosTypes, Ts), + + NegTypes = NegTypes0 ++ NegTypes1, + FailTs = subtract_types(NegTypes, Ts), + + {SuccTs,FailTs}. infer_types_switch(V, Lit, Ts, #d{ds=Ds}) -> Types = infer_eq_type({bif,'=:='}, [V, Lit], Ts, Ds), @@ -1457,6 +1448,19 @@ infer_eq_lit(#b_set{op=get_tuple_element, [{Tuple,#t_tuple{size=Index,elements=Es}}]; infer_eq_lit(_, _) -> []. +infer_type_negative(Op, Args, Ds) -> + case is_negative_inference_safe(Op, Args) of + true -> + infer_type(Op, Args, Ds); + false -> + [] + end. + +%% Conservative list of instructions for which negative +%% inference is safe. +is_negative_inference_safe(is_nonempty_list, _Args) -> true; +is_negative_inference_safe(_, _) -> false. + infer_type({bif,element}, [#b_literal{val=Pos},#b_var{}=Tuple], _Ds) -> if is_integer(Pos), 1 =< Pos -> From 73c5ceba1185b0be7db9acac8593e5b913dba845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 27 May 2019 04:46:41 +0200 Subject: [PATCH 15/73] Fix loading of Core Erlang code for extracting a map element The following Core Erlang code could not be loaded: 'f'/1 = fun (_1) -> case <_1> of <~{'foo':='foo'}~> when 'true' -> _1 end Loading would fail with the following message: beam/beam_load.c(2314): Error loading function example:f/1: op i_get_map_element_hash p x a u x: no specific operation found https://bugs.erlang.org/browse/ERL-955 --- lib/compiler/src/beam_ssa_codegen.erl | 15 +++++++++++++-- lib/compiler/test/core_SUITE.erl | 7 +++++-- .../test/core_SUITE_data/get_map_element.core | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 lib/compiler/test/core_SUITE_data/get_map_element.core diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl index c2d5035b197..07f4c8b4610 100644 --- a/lib/compiler/src/beam_ssa_codegen.erl +++ b/lib/compiler/src/beam_ssa_codegen.erl @@ -1016,6 +1016,14 @@ bif_fail({catch_tag,_}) -> {f,0}. next_block([]) -> none; next_block([{Next,_}|_]) -> Next. +%% Certain instructions (such as get_map_element or is_nonempty_list) +%% are only used in guards and **must** have a non-zero label; +%% otherwise, the loader will refuse to load the +%% module. ensure_label/2 replaces a zero label with the "ultimate +%% failure" label to make the module loadable. The instruction that +%% have had the zero label replaced is **not** supposed to ever fail +%% and actually jump to the label. + ensure_label(Fail0, #cg{ultimate_fail=Lbl}) -> case bif_fail(Fail0) of {f,0} -> {f,Lbl}; @@ -1160,6 +1168,11 @@ cg_block([#cg_set{op=call}=I, #cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) -> %% A call in try/catch block. cg_block([I], none, St); +cg_block([#cg_set{op=get_map_element,dst=Dst0,args=Args0}, + #cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) -> + [Dst,Map,Key] = beam_args([Dst0|Args0], St), + Fail = ensure_label(Fail0, St), + {[{get_map_elements,Fail,Map,{list,[Key,Dst]}}],St}; cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=I, #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) -> [Dst|Args] = beam_args([Dst0|Args0], St), @@ -1606,8 +1619,6 @@ cg_test({float,Op0}, Fail, Args, Dst, #cg_set{anno=Anno}) -> '/' -> fdiv end, [line(Anno),{bif,Op,Fail,Args,Dst}]; -cg_test(get_map_element, Fail, [Map,Key], Dst, _I) -> - [{get_map_elements,Fail,Map,{list,[Key,Dst]}}]; cg_test(peek_message, Fail, [], Dst, _I) -> [{loop_rec,Fail,{x,0}}|copy({x,0}, Dst)]; cg_test(put_map, Fail, [{atom,exact},SrcMap|Ss], Dst, Set) -> diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index e5611e99d14..72016c6d76c 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -29,7 +29,8 @@ bs_shadowed_size_var/1, cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1, cover_v3_kernel_4/1,cover_v3_kernel_5/1, - non_variable_apply/1,name_capture/1,fun_letrec_effect/1]). + non_variable_apply/1,name_capture/1,fun_letrec_effect/1, + get_map_element/1]). -include_lib("common_test/include/ct.hrl"). @@ -57,7 +58,8 @@ groups() -> bs_shadowed_size_var, cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3, cover_v3_kernel_4,cover_v3_kernel_5, - non_variable_apply,name_capture,fun_letrec_effect + non_variable_apply,name_capture,fun_letrec_effect, + get_map_element ]}]. @@ -95,6 +97,7 @@ end_per_group(_GroupName, Config) -> ?comp(non_variable_apply). ?comp(name_capture). ?comp(fun_letrec_effect). +?comp(get_map_element). try_it(Mod, Conf) -> Src = filename:join(proplists:get_value(data_dir, Conf), diff --git a/lib/compiler/test/core_SUITE_data/get_map_element.core b/lib/compiler/test/core_SUITE_data/get_map_element.core new file mode 100644 index 00000000000..092b5e71eb2 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/get_map_element.core @@ -0,0 +1,18 @@ +module 'get_map_element' ['get_map_element'/0] +attributes [] + +'get_map_element'/0 = + fun () -> + apply 'match_map'/1(~{'foo'=>'bar'}~) + +'match_map'/1 = + fun (_0) -> + case _0 of + <~{'foo':='bar'}~> when 'true' -> + 'ok' + %% It will be undefined behaviour at runtime if no + %% clause of the case can be selected. That can't + %% happen for this module, because match_map/1 is + %% always called with a matching map argument. + end +end From 00dc96a9a0086e829e574b651b4a28155aa826df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Fri, 24 May 2019 15:47:37 +0200 Subject: [PATCH 16/73] compiler: Fix broken type for erlang:'++'/2 --- lib/compiler/src/beam_ssa_type.erl | 14 +++++++++----- lib/compiler/src/beam_validator.erl | 12 ++++++++---- lib/compiler/test/beam_type_SUITE.erl | 11 +++++++++-- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 06b42f1928f..fe229d25dfc 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -896,11 +896,15 @@ type(call, [#b_remote{mod=#b_literal{val=Mod}, {_,_} -> #t_tuple{} end; - {erlang,'++',[List1,List2]} -> - case get_type(List1, Ts) =:= cons orelse - get_type(List2, Ts) =:= cons of - true -> cons; - false -> list + {erlang,'++',[LHS,RHS]} -> + LType = get_type(LHS, Ts), + RType = get_type(RHS, Ts), + case LType =:= cons orelse RType =:= cons of + true -> + cons; + false -> + %% `[] ++ RHS` yields RHS, even if RHS is not a list. + join(list, RType) end; {erlang,'--',[_,_]} -> list; diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 09a5a6c1048..ebe9631e095 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -2844,10 +2844,14 @@ call_return_type_1(erlang, setelement, 3, Vst) -> setelement(3, TupleType, #{}) end; call_return_type_1(erlang, '++', 2, Vst) -> - case get_term_type({x,0}, Vst) =:= cons orelse - get_term_type({x,1}, Vst) =:= cons of - true -> cons; - false -> list + LType = get_term_type({x,0}, Vst), + RType = get_term_type({x,1}, Vst), + case LType =:= cons orelse RType =:= cons of + true -> + cons; + false -> + %% `[] ++ RHS` yields RHS, even if RHS is not a list + join(list, RType) end; call_return_type_1(erlang, '--', 2, _Vst) -> list; diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 882e281a44a..0ddd91498ed 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -24,7 +24,7 @@ integers/1,numbers/1,coverage/1,booleans/1,setelement/1, cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1, arity_checks/1,elixir_binaries/1,find_best/1, - test_size/1,cover_lists_functions/1]). + test_size/1,cover_lists_functions/1,list_append/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -47,7 +47,8 @@ groups() -> elixir_binaries, find_best, test_size, - cover_lists_functions + cover_lists_functions, + list_append ]}]. init_per_suite(Config) -> @@ -487,5 +488,11 @@ cover_lists_functions(Config) -> true = is_list(Zipped), ok. +list_append(_Config) -> + %% '++'/2 has a quirk where it returns the right-hand argument as-is when + %% the left-hand is []. + hello = id([]) ++ id(hello), + ok. + id(I) -> I. From f7fe4573880ce94d794af266d0f37459b7a86709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 24 May 2019 16:08:55 +0200 Subject: [PATCH 17/73] Fix compiler crash in beam_except The compiler would crash in `beam_except` while compiling this function: bar(Req) -> ok = case Req of "POST" -> {error, <<"BAD METHOD ", Req/binary>>, Req}; _ -> ok end. https://bugs.erlang.org/browse/ERL-954 --- lib/compiler/src/beam_except.erl | 7 +++++-- lib/compiler/test/beam_except_SUITE.erl | 20 ++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl index 28c89782c9a..23055028003 100644 --- a/lib/compiler/src/beam_except.erl +++ b/lib/compiler/src/beam_except.erl @@ -140,8 +140,11 @@ fix_block_1([{set,[],[],{alloc,Live,{F1,F2,Needed0,F3}}}|Is], Words) -> [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is] end; fix_block_1([I|Is], Words) -> - [I|fix_block_1(Is, Words)]. - + [I|fix_block_1(Is, Words)]; +fix_block_1([], _Words) -> + %% Rare. The heap allocation was probably done by a binary + %% construction instruction. + []. dig_out_fc(Arity, Is0) -> Regs0 = maps:from_list([{{x,X},{arg,X}} || X <- seq(0, Arity-1)]), diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl index 8e3b373d29e..67947dc2925 100644 --- a/lib/compiler/test/beam_except_SUITE.erl +++ b/lib/compiler/test/beam_except_SUITE.erl @@ -21,7 +21,8 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - multiple_allocs/1,bs_get_tail/1,coverage/1]). + multiple_allocs/1,bs_get_tail/1,coverage/1, + binary_construction_allocation/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -32,7 +33,8 @@ groups() -> [{p,[parallel], [multiple_allocs, bs_get_tail, - coverage]}]. + coverage, + binary_construction_allocation]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), @@ -118,6 +120,20 @@ coverage(_) -> fake_function_clause(A) -> error(function_clause, [A,42.0]). + +binary_construction_allocation(_Config) -> + ok = do_binary_construction_allocation("PUT"), + ok. + +do_binary_construction_allocation(Req) -> + %% Allocation for building the error term was done by the + %% bs_init2 instruction. beam_except crashed because it expected + %% an explicit allocation instruction. + ok = case Req of + "POST" -> {error, <<"BAD METHOD ", Req/binary>>, Req}; + _ -> ok + end. + id(I) -> I. -file("fake.erl", 1). From 528f17ad9b85c4a3a1e28428606494550eef3a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 27 May 2019 15:34:35 +0200 Subject: [PATCH 18/73] Eliminate crash in the beam_ssa_dead compiler pass The compiler could crash in the beam_ssa_dead pass while compiling complex nested `case` expressions. See the added test case for an example and explanation. https://bugs.erlang.org/browse/ERL-956 --- lib/compiler/src/beam_ssa_dead.erl | 18 ++++++++- lib/compiler/test/beam_ssa_SUITE.erl | 60 +++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl index bb43a550ae1..86f680c964d 100644 --- a/lib/compiler/src/beam_ssa_dead.erl +++ b/lib/compiler/src/beam_ssa_dead.erl @@ -436,8 +436,22 @@ get_phi_arg([{Val,From}|_], From) -> Val; get_phi_arg([_|As], From) -> get_phi_arg(As, From). eval_terminator(#b_br{bool=#b_var{}=Bool}=Br, Bs, _St) -> - Val = get_value(Bool, Bs), - beam_ssa:normalize(Br#b_br{bool=Val}); + case get_value(Bool, Bs) of + #b_literal{val=Val}=Lit -> + case is_boolean(Val) of + true -> + beam_ssa:normalize(Br#b_br{bool=Lit}); + false -> + %% Non-boolean literal. This means that this `br` + %% terminator will never actually be reached with + %% these bindings. (There must be a previous two-way + %% branch that branches the other way when Bool + %% is bound to a non-boolean literal.) + none + end; + #b_var{}=Var -> + beam_ssa:normalize(Br#b_br{bool=Var}) + end; eval_terminator(#b_br{bool=#b_literal{}}=Br, _Bs, _St) -> beam_ssa:normalize(Br); eval_terminator(#b_switch{arg=Arg,fail=Fail,list=List}=Sw, Bs, St) -> diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index 15cf9bcbf30..a741ebbdf9b 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -22,7 +22,8 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, calls/1,tuple_matching/1,recv/1,maps/1, - cover_ssa_dead/1,combine_sw/1,share_opt/1]). + cover_ssa_dead/1,combine_sw/1,share_opt/1, + beam_ssa_dead_crash/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -37,7 +38,8 @@ groups() -> maps, cover_ssa_dead, combine_sw, - share_opt + share_opt, + beam_ssa_dead_crash ]}]. init_per_suite(Config) -> @@ -492,6 +494,60 @@ do_share_opt(A) -> end, receive after 1 -> ok end. +beam_ssa_dead_crash(_Config) -> + not_A_B = do_beam_ssa_dead_crash(id(false), id(true)), + not_A_not_B = do_beam_ssa_dead_crash(false, false), + neither = do_beam_ssa_dead_crash(true, false), + neither = do_beam_ssa_dead_crash(true, true), + ok. + +do_beam_ssa_dead_crash(A, B) -> + %% beam_ssa_dead attempts to shortcut branches that branch other + %% branches. When a two-way branch is encountered, beam_ssa_dead + %% will simulate execution along both paths, in the hope that both + %% paths happens to end up in the same place. + %% + %% During the simulated execution of this function, the boolean + %% varible for a `br` instruction would be replaced with the + %% literal atom `nil`, which is not allowed, and would crash the + %% compiler. In practice, during the actual execution, control + %% would never be transferred to that `br` instruction when the + %% variable in question had the value `nil`. + %% + %% beam_ssa_dead has been updated to immediately abort the search + %% along the current path if there is an attempt to substitute a + %% non-boolean value into a `br` instruction. + + case + case not A of + false -> + false; + true -> + B + end + of + V + when + V /= nil + andalso + V /= false -> + not_A_B; + _ -> + case + case not A of + false -> + false; + true -> + not B + end + of + true -> + not_A_not_B; + false -> + neither + end + end. + %% The identity function. id(I) -> I. From a034ff64abab5f5cbf5c6aa38762044c968fe377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Sat, 25 May 2019 10:23:20 +0200 Subject: [PATCH 19/73] Fix unsafe optimizations where guard tests could be removed A repeated test could be optimized away. Example: bar(A) -> if is_bitstring(A) -> if is_binary(A) -> binary; true -> bitstring end; true -> other end. In the example, the `is_binary/1` test would be optimized away, basically turning the example into: bar(A) -> if is_bitstring(A) -> bitstring; true -> other end. Thanks user Marcus Kruse in the Elixir forum for noticing this bug. --- lib/compiler/src/beam_ssa_dead.erl | 12 ++---------- lib/compiler/test/guard_SUITE.erl | 25 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl index bb43a550ae1..e220a89dede 100644 --- a/lib/compiler/src/beam_ssa_dead.erl +++ b/lib/compiler/src/beam_ssa_dead.erl @@ -680,11 +680,8 @@ will_succeed_test(is_list, is_nonempty_list) -> maybe; will_succeed_test(is_nonempty_list, is_list) -> yes; -will_succeed_test(T1, T2) -> - case is_numeric_test(T1) andalso is_numeric_test(T2) of - true -> maybe; - false -> no - end. +will_succeed_test(_T1, _T2) -> + maybe. will_succeed_1('=:=', A, '<', B) -> if @@ -769,11 +766,6 @@ will_succeed_vars('==', Val1, '/=', Val2) when Val1 == Val2 -> no; will_succeed_vars(_, _, _, _) -> maybe. -is_numeric_test(is_float) -> true; -is_numeric_test(is_integer) -> true; -is_numeric_test(is_number) -> true; -is_numeric_test(_) -> false. - eval_type_test(Test, Arg) -> case eval_type_test_1(Test, Arg) of true -> yes; diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl index ed0a56f064c..cea7a374cdd 100644 --- a/lib/compiler/test/guard_SUITE.erl +++ b/lib/compiler/test/guard_SUITE.erl @@ -35,7 +35,8 @@ basic_andalso_orelse/1,traverse_dcd/1, check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1, bad_constants/1,bad_guards/1, - guard_in_catch/1,beam_bool_SUITE/1]). + guard_in_catch/1,beam_bool_SUITE/1, + repeated_type_tests/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -53,7 +54,8 @@ groups() -> rel_ops,rel_op_combinations, literal_type_tests,basic_andalso_orelse,traverse_dcd, check_qlc_hrl,andalso_semi,t_tuple_size,binary_part, - bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE]}]. + bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE, + repeated_type_tests]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), @@ -2261,6 +2263,25 @@ maps() -> evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} -> ok. +repeated_type_tests(_Config) -> + binary = repeated_type_test(<<42>>), + bitstring = repeated_type_test(<<1:1>>), + other = repeated_type_test(atom), + ok. + +repeated_type_test(T) -> + %% Test for a bug in beam_ssa_dead. + if is_bitstring(T) -> + if is_binary(T) -> %This test would be optimized away. + binary; + true -> + bitstring + end; + true -> + other + end. + + %% Call this function to turn off constant propagation. id(I) -> I. From 85e8792fb2f7692147a63987d0d6da7dcb812e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Tue, 28 May 2019 10:37:36 +0200 Subject: [PATCH 20/73] Update primary bootstrap --- bootstrap/bin/no_dot_erlang.boot | Bin 6546 -> 6544 bytes bootstrap/bin/start.boot | Bin 6546 -> 6544 bytes bootstrap/bin/start_clean.boot | Bin 6546 -> 6544 bytes bootstrap/lib/compiler/ebin/beam_asm.beam | Bin 11052 -> 11052 bytes bootstrap/lib/compiler/ebin/beam_except.beam | Bin 4196 -> 4204 bytes .../lib/compiler/ebin/beam_ssa_codegen.beam | Bin 37572 -> 37688 bytes .../lib/compiler/ebin/beam_ssa_dead.beam | Bin 12072 -> 12004 bytes .../compiler/ebin/beam_ssa_pre_codegen.beam | Bin 45600 -> 45604 bytes .../lib/compiler/ebin/beam_ssa_type.beam | Bin 28400 -> 28636 bytes .../lib/compiler/ebin/beam_validator.beam | Bin 50212 -> 50216 bytes .../lib/kernel/ebin/hipe_unified_loader.beam | Bin 12340 -> 12336 bytes bootstrap/lib/kernel/ebin/inet_db.beam | Bin 25360 -> 25360 bytes bootstrap/lib/stdlib/ebin/erl_lint.beam | Bin 86228 -> 86340 bytes bootstrap/lib/stdlib/ebin/io_lib.beam | Bin 13532 -> 13636 bytes bootstrap/lib/stdlib/ebin/io_lib_format.beam | Bin 13892 -> 14868 bytes bootstrap/lib/stdlib/ebin/io_lib_pretty.beam | Bin 21280 -> 21116 bytes bootstrap/lib/stdlib/ebin/queue.beam | Bin 5900 -> 5908 bytes bootstrap/lib/stdlib/ebin/string.beam | Bin 35788 -> 35872 bytes 18 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bootstrap/bin/no_dot_erlang.boot b/bootstrap/bin/no_dot_erlang.boot index 9a2412e1f085d5da2ebdc62aaa4e274f297cc9f9..1f7f088a777f183113770950e265356b20655ea9 100644 GIT binary patch delta 28 kcmbPaJi&N_2M-IgnV!jJKb~*wjFyvqc%(MRix{&40D15S(*OVf delta 32 ocmbPWJjr;22M-&onVzwp;btG6Z|uw#dWMsIcqBH*iWsv30G4P7j{pDw diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot index 9a2412e1f085d5da2ebdc62aaa4e274f297cc9f9..1f7f088a777f183113770950e265356b20655ea9 100644 GIT binary patch delta 28 kcmbPaJi&N_2M-IgnV!jJKb~*wjFyvqc%(MRix{&40D15S(*OVf delta 32 ocmbPWJjr;22M-&onVzwp;btG6Z|uw#dWMsIcqBH*iWsv30G4P7j{pDw diff --git a/bootstrap/bin/start_clean.boot b/bootstrap/bin/start_clean.boot index 9a2412e1f085d5da2ebdc62aaa4e274f297cc9f9..1f7f088a777f183113770950e265356b20655ea9 100644 GIT binary patch delta 28 kcmbPaJi&N_2M-IgnV!jJKb~*wjFyvqc%(MRix{&40D15S(*OVf delta 32 ocmbPWJjr;22M-&onVzwp;btG6Z|uw#dWMsIcqBH*iWsv30G4P7j{pDw diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam index f6e7f0d68e585443492e52108c7842e43f4a75b7..07acbb1da7c47ecd34e198127f47a66b96f0483c 100644 GIT binary patch delta 136 zcmZ1zwkB-DQB7&B&7lko42yu635eeTF(U}G1H~sl&=iHrFMx`_0Mg7r%m9`b(1OWN z2MU4oUjkxQAcn|0Xk{?FoEMn9TFaL)Zt_npMIp5Vc@{pwcjjDuDrUbwE9_}j768;) BA<6&% delta 136 zcmZ1zwkB-DQB7&P-_8sS42yu635eeTF(U}G1H~sl&=iHrFMx`_0Mg7r%m9`b(1OWN z2MU4oUjkxQAcn|0Xk{=*oadOlTFaL)X7W!hMWO#`OjjJ418RNl$+snE+<%^x1ps1I BBPIX< diff --git a/bootstrap/lib/compiler/ebin/beam_except.beam b/bootstrap/lib/compiler/ebin/beam_except.beam index 5daead0cab8bbdb36a94131c564b4ff0c3e4e443..1894483f71299bed728013307e54e19f6dd5f11a 100644 GIT binary patch delta 1497 zcmYjR-A@!(6yM94CAZ@q9T{}BM7(%W+9Gu9EV#>u-ko7tSx_mcMFj=XQmG$^qJ5~L zY5##X^WroF`@mb1#>OUnZR0~9`VaWjq)F4HAOAsL`nxRBPI7baIrp63Ilptx+~3sS zN)Df$IF`wH*T0p2HSGR6gCmyxHn1Kg4h3T6c@GUYh~o2)vtKlf7N|^`o^q&-dmz$Y zSl}>>wA$K(5LaQ~c1EF!OB}|1SSE^~Czq&dOoKK)8R4h0#R+&SBG1Q7a{jgU)sk`dQ&WH#eW^T9!``3D zR)h!xAqR?F2HlWKY{G$%O@7w!NyR4u9u#sg3Nvvho7gRQ%2YzF8v`B?^2D~jC8vxb z$LQuL^eB}FK`}Pun`Uhs%EGz_L{4to_vDN*VY8ujqYF_OIIv2kg4YG(fFG*V2H{N7 z<+iO37$J?RjuUb&7r39iAlRV1@--AuDi47~FW}=MkJ_H0G0|4f2>ps99q1yD;A)Zz zT%#h_;&MzduVSB%p#!^`c8{;|7^*tt=M`zA(UPHcuIz?5uLpTp$cmZQLJlXtxUa9q zLRPmu+v=XD{_{NbW!Cp+^Jk9;J*rDK(1eg@>*nLBJW>ORcT?E` z>poadl=vJ*`Wyvr5yPP)QV=JT7dtvuClGY94sfmxa6Xl9!tn$gFXYg9-&yd`o>aai z)#tE&FO{9RHyEI)5>L|r@l4(*z8vsHAunQ7!%m(FH$#Q>P?tjG_G3miFMxFPaW+`; zcl(V&mZyZgl-$W3xq!pvZD)l%(XtuJ1^9iMjo)4-J0IPS$5-paf^4^B&v=*&kaNh6 zUb~Ocn?ici$RqhPr&ec7^%GmlE2#{SdIT0%3p`84EnD?$z;hTc3!>bERx{Vl*S0mW z)m-c1`EAXR)y%*0P*%F0W`JDD2zkRaQJOj9eI?}kb>%AJE!h8J^Flon@&i;8=2awl z^C>Tqa$7Co9oZl7_yBFu3zW@n4`4%j%QwcC9yk^Y+V+9)0$E-1zJFFaLS*^P$DX Fe*s9R{doWY delta 1433 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 delta 18429 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 aRM^)|p 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 MdFknA<$?wO2Iu<*+5i9m delta 6484 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

_1&xHL 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 M%YLYRalwNB1DkL<%m4rY delta 20974 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%0A~M3Q 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 KW%+%}mi;fxuMIZ< delta 10162 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 diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam index 79d64b800bc4ce3875179280f516a65de0d13d80..9d0c34a94aa1bb44fea65c7b6848a35f21db1289 100644 GIT binary patch delta 1767 zcmYL}O>9h26vyApd&8Lcc+)9LN?wK_)i8v{S9n@!t5iqptAb35s4~)SgsvK^E+i)H z2I*oJBDJeb7pRYE*!WmXMC`;oFYiQnc^2UUR(mZ}r((Cl=qBowH-{Q17fCi`!Lh zBGfzQ+X+AB+7Yk4%PsVdC2I<|C-b%w9(;dgH1(vqmLDuDJYeCEWkpg-@ehHF09h=A z0IY>N2nFN>=+nR|=sW`y1=!6m;mcFdC?XV;m=R#F2Bx7g19(r3$tDeafG#vZT7YII zQQ{+XF+!Of65ud%0KP(9gz_*UKns#+&-nzcLfC=HvH)Eg_yw&tfcwmt%rJ?AS^!;! z2nRd(0-R?Oz!GQ;LV4&H-~^NK@Ef`kp}NQma1uF`aQ;ARxgL}#3DB*9f6&zxU}Va8 zJcArB6JdD>RUsw7S>^zsij_ntj~M|jBFQcjP>zJMkQ3mN29`tD8K5Y@P6arV&akQQKt26~`J3@{{srvd&LrVTJ5z-A4MK|2jl7JxTQ509Y74B!@x$$c7l4dpvm zCVc@KHSi94$^iWW@Nih-GxW3p@&X*vz!xYVx++l;fUR+dAJB6ZU}V~OWM^Fe3C&d2 zM^gfDjsQeB7Ci>Y2yhii+*KqAB^+2N&h(rWZ5xEZ{64geCMCkATocr2tIM@Cczx(C7@9VmrduO_` zr@OLc4J~Wyo%?q3*|PTwnStK!LeJs(b2WpifZ_Mr(gl1X? ziskuiWkpq{b+A}oA+NXdWT858uJ`!4o@|oo|6;OpQKxe*>s)RInvr>a0H3+J`6Xqb zH2-bS=c23|;vI6CKOKz&zTfkyXfEJMyC0Z>jtB-?@pYhy=twN`ffvbV@AGIGW(QsD z`2}=Tz?XR5hn5Gth|fWi_&b~ju-FG!j;{b$&<8OKuu^mQT|-A>SwFu)bKpOsV=&9m z%eVxH`_ZwO?cap2{eMR*TrwPBH9!k~LGzd`Xq34` zs|^NT!`F=|gL?$C8*lfVL%Bl0*UKlsKj<{f0_?+OZcb&Hj@dz9_gv|JH04R@b9%!M zD9w+h110`kiN{}}GXlQQ^KelW#ZHT9xtyIxpZlgqk!tj-yR&Bb{0cj-fh) z@${DPF4%&AD=V6R1brgl(>#9{eG;<+seGD$2qi1Y(17ZsTE2%qjae<#I9l))s`T1M zYC!S*=(7P&`v(3FOl7it(nf~2fmGHKCw|)b45$Yd4Gp+xJU)#WtGo5O*>|i@PJz{| z&tsOMN%%_XUUUg&2UWAF_M6b9m>o#X8B_mQ4@nWT1$tz(pap#avjut2o6%(fukidO zba}w_K4_m8(G>yLE2#@Kpvg-9*bVfo>IT|GgU0o4Ya?Z$5wio0k_%TlR|UKbUzt-` z6x=R05?_J!HR!cvpCtY7N2jL)YAoHt0_gcv;0>tWZR7e(#r2RV8^$Mkz8ls1Z@k9y z4pdn+UaR+C8y$eH2?px$#k*0J#}>@<{3N|D+Qo08JBE1@DUBNV6WuvH5bZAU+-P)H!1sEt zuR(JxK%3|Koc9F$O?;XzS3tEko!``Uka9%ZT<=GHhoj0{Rlgp*{r9D_KYYIM>!baL I7Pq(G2e9)&$p8QV diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam index 023d0bda6d90c4b238a83c0ad19fdb3c924ad6ba..7ff507242b40148b4a0d723fe1fd846069e5ea9b 100644 GIT binary patch delta 594 zcmV-Y0?Qo00Gqi z00!fDoUN3>YTG~%hPO%&#-~CKxeoNw9$GMIO)7_ykebGj1d$XPC`D|%qi9`u*X*t= zdhx}%=0$SoljMnd>a0whCN^Cfbg@Pw|Nr;T!YpI#C1b2L|G|HrAMSVG-Pfnb%R2e1 zpCkv%`fMjz*5^CjyL$U==L6LPs{6Z#GU>ysDfs5=kMMQ>^ki`IIfi2`$^v0lLB%Z$ z^>`u+6i`W*L#>&ju~I9T**2NA=LP*noQ+2G{6*F`E7sg7sV-ws+CibYpchcw$tjY* zK*+R#@f|h>=^lTg{b#N~D&Ha51^v&I%E>W;{b?PJdoU@GTWaGaDm2{T3c%&kK9c$T z@9X>S|@)@>oiB}g=xL!Xc(qpb2JsE zspe=`VcJ!5wA(Q4c0Dbo&F-#jwlUho@NH&kmA}Vupp|u8x%yJebg2X^R(y}tyCL{Y~-0#l5a-YWlqwDF6Tf delta 596 zcmV-a0;~P7V6?Qo00G$m z00!}RoUN2WYt%p#$H!D;=}GY5^??_?RF>7UWJ|Hur7gB4RKbEsnC`qZvu0jVO%}K61_w(n$$KyPzu)^0ykU$zV~lkcU)g`d!@ccSck$WDDo%c@ zC&~UQ{?JcW@p*rn;!TPl^|reGtsZ6XDLdFXl*tgD&tO@8u?wH}&Q6a`4`MjcqAU>R z6;#~9NKdA+KmnC>In=5d8Y{Jex!tUr7xauc8;|Mzotob?H0MT1bs2-w4hqc$C7`&I zGbDmQ$h3jUFK~Yh()|hdpSc35e1&8e^q(n}lM@8{%{rV6U|JxzRK`nGXt={QfXk)* zOXeNCt{rR$_Ly6X#*w!)oss(kd>P!c~zv?AZlvwi5J!Y diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam index e53e183312d7273a580b6e24f492b76d13b7388b..20d795e75f75f97cb41081c5ca0bfc49879863d1 100644 GIT binary patch delta 446 zcmYk2yGjE=6hLS0svGlgqeU!iEi3{?(nzofqKO)N8_|f3q_r^EEaDHOvC`HcA`+bZ zfK9&0(!z7yyO83}Ih>hgm>tdhXyzv&@#kThghtdYG{a4MTnp8+ew@12=7w|r$gwyl z9~oJ*er){{3X}H}OwUhXq}k5*FzsJ(L9_K!O#2irYPOzsQQdflOWJLtgK2+*v1aRs znD#L&XtutOX@7ysnyt4n?N6}C}|? wD|3DO-<@2*gvl@7!?;);U^ROhzdHO}7NfO#XY2Xu`}S8}SJ#J+2k~I=2ZL)XT>t<8 delta 447 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 O`akpc&0m%~-Twfnvck;( diff --git a/bootstrap/lib/stdlib/ebin/io_lib.beam b/bootstrap/lib/stdlib/ebin/io_lib.beam index c52efe1b44d162655051fae101c55480bc8ae43d..45692978e455c51df7f55952cb661fae5d98aa7c 100644 GIT binary patch literal 13636 zcmaJ{349bq)}KmGlA0j}o%BG0A`VP6jYGr043cn2CquZwNKjGHWRgrmFqwqOghN4s zAmRzAsHLbN3aopGd$0Pf=(p=0?%}bnx*m(Hx`(2!>#pvu%J+ZOJ;{Lh<@c-U*RNi^ z`qz7}Ue}RX=PsV$@l2XlQ(L{TI&*%d$5VKo$K%;u(B9S1(cVFQ=%o2ZYxNpI})k3{A4=al^)d7oJch|(q5uPZz_jX;Jo>p zdfPi%8ZyZ>nS4bWnPg9Nw#>KyIPV%lc}EGbn=9%yspdhyVLEd zen8#nWG1tAP4iTf21blA=UQ3w6-m z+MZ13yCz6<^d!BRbZ;`hCE1->t|hy>^_FC7qPHW{kW2wud#a6Ri9yZF6KUXX?`+Q$ z0ah~InQUoKWRe9++k_#+YfGjZGGynT40jCO&^D;M9cFNt%o^0%o65cwCOeXy7>r+O zXviemI|jLAZ+A!1pP}D|p7tw}EbPj3ccn8$^pn-$a~hFH`Na^9QTQ;GE2d>T(rVLG`gneIsz=T@o4 zTB4()pd*=T%Pi+j?HPsGo9XFo^0y^34PD*jtHR5ZYg^$vcN_rI8E_O4*^q!`mHSR{ znB84HJ?%{$Ya3Sfc4d++4J1^gBwb7TRfXbn1ZRVa!*sGInO+6))m`ZpE!CCrrxKmX z2IVxWU|{ev$Bb* zAFR0jLc`Q+ZpTV$sG5q2Cd8xL0cjkZ!^LY}d)JTwP8ta#S?FpSHo(v7CIxw^4x_oN zHWrChtMI96$#~?613Udsi zy~9iBOURgsW=y%B?0g*T0L#ASC%U^k)&`E3b42v^E>cO74ueLDnK$@&u3zOLWY=_O zer9>PYc=L55|cJ=+&GbyROurtNV&yrLs`Y=(3t*EjD`)_MBr;hGF3JiGEkvXg8PmM z?!>QO<#Q!8WPnszOwWC%?gr;D(3A5i7|>4{C~&+8A{uEZm)YNO5!ns-LM5C*uDvKr z7C68LIp3Iu_Ec-v5OPh<`$)@~S;r@x@e?ehWh-I@a;p28LmcM#iLOvystX^~IFg3P zQ!yB%jzWJ2JRXMPNitpPc_pKRELaeHkVRw=FA-)JL|$ZdGLly^F~}OFy(s8m-Lej^ z5!NRg7e#coU3TY{EDo~WMRmbqZ*jmj%55#SeCGFLUtuuVKC`6GU^-+IflOMqbHNI^%}q zfkk>F;{nNs=9L@)Yv^EGx3%)+F)>W?VTF2kd#uDZ7$3GG_Eq-brK+zW8Aut2m#KbA zB_9r@7)RNO;}|aaDTTp4cO1k2pK+XevT=-1`cIMkw7e3(jv<{|o6lFpIGQQY?m7}E&ZcWGf~wLquiAbfg5$?y<^4H01Jz08e@E_J=@k) z08gtB(=}!X47)sJ$FzKaw;7*aA!abG&0}j(+Z$4~aSWgy5?gJLL~O=DjmiRJBl8r!i3dIM(2U@Vx+(*+1RVu(a_eQ?g-TDjR;UptJP+2M}%CWIdQcx zCKe%#cT+!$7K(GBZW;g&W&GS-qE17!G%{XSC2Sx%j}RRs$@3(iJ}93LE7lNW({r(f zFf9VqyNhkQgAFpk7AQuBj;fd_r`a>gQ1GUEZLxF!-XXxd(uKEJ@^j#xv2ag)Oe~?k zmxRUn1mszIIlod|pzJ02j9eHenrMat12SJ>A`++?MnhUGP0k5=Q=RXCQ1B%cp(D{8z! zFyb_w%T<&j3_{Luqbe8{Kq{&CWn-m+=ZQuviJf5EOgoK~g>+IUucGRG1^)c(& zCwdXqy`nc>w^8@huN9fNr$|@xq#htH0*GS04%YBGokG3pHnSQ{8vQeLPn@Pze8BZK zwY!+wNq&jzT*SjA>oB)QYM5GJ26-8#Iz=Z^7+K{KvIA;#tMg0NK;{i2dl(-g#UUiNUjZw^+o^-Ax-tU9-~vlRgyPDOD%H5h9Vs+Om7>0 z3>th;Yy!7W@)iip0=dx@z{)5`;A+W}5SR_vn~H*1Ef5aLTVaP$^xf9*9n(Na-UdT& z35(5|f28fJfC|hxSZw+Hpn|d)Z;H4^@^)yP3yoW7k!5%#UjcQar)uH`wT#({Wz4mV zU#r4lYo)l}TkX{hQ(Uk45~jG$cZIf9_ozs|+^dV5kgzGYP#(Wd3H=ejzGK>0YVb)` zwBrQP>uvu?XY$>E{^!9%H%i_KU<+Z3n<~XN4fd$kG@whN>5j0tnMMZ7p-YI|jP;7s zep^i3sF5}R*e-b&bS#3v4pZC$z!l;)09G_`?F6o{xDB|bi=B+$Vv1WeUp2{G3>nae zNahVk<|QR_D>#}jLNZkvY_zk~_BG(e7Pm2eo7?YBLWBNqmmHfe|GDV@4%;`HmP(TG zJ0)L9T$o%sCU@7${yKOljTG~sTK&4&=q|~7AbuW{+>Hg#9gOdiJOj>RaPD!{-pBa8 zlJ^o9YVSKDZETAyuTI}4;j8?#Puy3U_WGvuN%H#g?Jb%cE-OBZyYRb^w)`R`OCyN z{Y%6*82^ST4jR7QBy-Ftf(EP$FhhK_&sbj=^aBVg zn7`?0GR1yqnl2t@{96u(@rN;Q2rob!oN9<4m2&+#@xwjh2akyF`%V?#+bF*4+aSL4 zr1#Q#XX37Rf}rXOQMJjVDFl5YlQ890Y5@dT7Tp)vemdY`D0=E5~!Qu(Ch zTcF@lD0s>ePeQ?yUq(YS;My-W{a?wqqUmL5`jblWQ>>m1%@R)|K|XB&!_$Zsfcy#L zKaGi}vx(_xH$nVN^6SvJ0gZoNDSqiTeg=)7p~k;3syr`yD#SBYod z$>P}%O-apgH|>yn))Fs-OcY>w!FMd=w0 zl0eTdIz7L{`0pjZiJ0j5rAqM!x969S?-_D0TjDkJ{2KNAO31OoYh(p5>7A^AcWjd( zL{5C-DhV86{7p>ww@MFVnjd*m9N8$2JR*+l5J#R9NA?I*AA#z_ zjQ=Sn-pYFBEf>Jsl5a`&0Iau#jiuYaA?*Zw13iVNi8Z=NJb>rzhH=gL7EQxm&Pamjwnl6qq z{vO8lfg0D*C&kf?;^-sd=nir8IdOCkRUgH;-evs#nD`(&t`FRCeJJ^@0Mzbb{O_3J zSV%Gck>t05w*qeehs`jvE8{i`71W7;GXAmTJ5hIe9pnGpC;qL~Y5TSMy0zk8nn#b+ z(dsP}hl+pQfVxJ{eyzE26R5th_{3n6-%cs0EQFnK6e^>XJ`6|iCl%sTlDLDmg-YVM z>Q4`7^$%+G-ICwAF29?PsjokvH9rXLSw?d+sP(7{)Hl~lF4yNbs*S5llEy3t`oT~gOtI*#ijxl~LY)38#+zf$ve)2GVx;0TIZ zm04bYo5h&PiXz>1z1MD5#~k?nH6vr+gB9XGXti2lVL47J3i0qk{9daJAePzD^7 z*d!~IwBM5afs=v6KETYcunIId_(A31W(^=4YmNGTkPs;lo*;M_F>Q4AofKdpt=yVP zq99_8WG06_L$vTGe`8w{C4Lz*eG#h!tH{qZf6vsArPJ)T1pMP?rhk$}i;?}b=@~=g z92CVz%cfOI6#N4;$SP|nMmQ8BguUT0>cO!T%t;;}RACj-+0oZ%HUy$HoFGA0La;eR zu=okOZT#JM7u0W2&{+{Fn^JcV4FtttuM-pj_!}Pjx&vewfDHR;AcHHcA+&|~hH}2w zaeiO`2<Cb6X9#tqkfDUXBnI=@c>^{D+I#1e zGZSv!JIBk+p)eMOww1zY6AR@G3f0DyEYmMIgUIfVvR7uRw;nRtW!e(H;lmH=sl8EeDHY1dCEZ} zVrZi`MlkH47NTGODr$%m`9}b9H9(FGTc;b0Kw@{92L#{FRkYGYczUH33{{7s$UWat z2(iCb2sPJi!H6{~6t+$aQI^n^qVFEB$juU?Vi3v(MGBvNX5z5_dqA@$$jnfcRSs8= z)+pd|5A&@vnOPn~1w|+=D2Rb;fbXN>S~NVf(mD$tp^%0^A5&^SXPJAf3T9Ra9Ia!= zTf0X!ll%v{ptANiE3Glw{aQ3^jfw7YRF6^n1jFsB`3KX%gOezqf(_3h)iqwW6!OqTqA03W9pX5~I>vS!Ek$F;g%Yld_Bvp?S4 zIJMq7r_|nKO?}R)VrJE5Yf8M&v)Vc*-tC{!=c$+c$LsPNDI;a6`Y0&%5!9l@bjVTK zKC9YjjIOq-qm5dhN81FV56;F1%1g&tIF+F3_Qdh|)0u8l)}lY;mP6}sD6G0Vq>hI% z>-JeSMg&@GkVlo)nrNSHV|f~))4EdH7n)OZ;Xc_9*P#gRlUca?thmA$R~X})ta!Aq z(wc^eWFXe28_i_)aR+G{~n;hI(4envRLn=%lcCJ&;V#4mj>+m;XIk!*dSA zn>Sf@yw8ri5j0~hUOg1yMu^1;2*>TIYg4 zKWHW3!pk~BkiebA?=Qz_8YO=Tny-cCMA&M=O`d-%`MjypN>a!n%9`m`fR_=snVgC5 z7VZVq{}o97GLGrq30p06Oc!&;-6Hub?rjDwBa35O^$1wNnNT&jOA25afTLn}jY(CP z=bVL^$z4_}E|jedGh4@6?YQWxvX;Y>Z3@Y7LeeJrADp|i5GePyDM||+WgA*yP(J#D z)9b71;M$ArL;vY1ZqewR{#9?p>UR5vIP8tP9dr3U^cuuQ*jmrbc65iEjn`nN>tUwL zV^#+t=m=Y#1D5Hmv{Gt{O8$B-8k%*1ESlFHG!V$zAV4-C98`6j4N{W7p;lM;@&iYL znYbGGBQV?mA9kzzvS@|1Qmv$bW@Xq)hx+}Lmi(}DVTSa0SS=tz&MhdM2RyKS+`zIG zl@27x;HnI6QQ|lkCtInjChP)S!2v_5MO2UEZvxJZFiFNaLzMgo<_hk&jwo$jI5{th zBk6qGS_Pxx%>PelaFfl5l9j6;-j~ zST+IR#sOS-@JjNa7Kq}~Nuz6sm_dD_qcveP#ibG*ivJnTje@sU^0#rbWL_cpUw~&D z?1_W_zbda`w?|7eCs&4GjlYt8^ayRef;iu&)#EzJ|AuzkG4Sg-_V=CRfmHFd7hRJdS8L;szC{CpELui1x6 z72$U=a|?Bbp-sG2zdN|Eue5G(!~LVL4EK*5l>hiL zN}T?GoDMKZD!t7Vci@;ZdQHY9JaPaU7P*O>3f^xpY-1bf1+-KqbI!$ zj>8R~I2b-947dsg2P9^nw-_r9xA$lPSG4`2wVN1Jp`s z=Aro=An$VRdbcz+umF%(0ew0wAbFqHe?Qo%J4_Q=I1Uc5t_e-+?^7o+SUYyzOW#$9YEClCXa2^ClGIO6a zIXL%$v)}gb#-XamQ=dsM@!%if{P>yM*$q1HAjm2dFA5|)c{wz_7q~p)a}=NZp5LT!U6qfqFNWXe&fp6C%Mq=$5# z>C#kJ;nKu6bLcUkv*S7|hab-2kIUhY&*4wV;YVG15}s%0(34$y8lKZ#nlRWobhS&9 z%uE!rC&|n~p|Q+EneWoXUywu77_;~<%%PX&&=xS8QHcK_o`lQe^2yf3 z-|IXb{(|-l=|t?Xjcaz*ZeQ57DN?j$;hvA8&>+u<{kJ#u>2ojr?njH4Jo?1WcV>KWMdDYJ zYbx)&?4co>U%ca%3varA&!caD?0e(z?$FZWPcOQ?YQZg=yMK1+<5z4vIPCg|UK!Id zKlEba?2q=}HG1=sZA^VIv_mJjv(`QE9Y@0z;4{PXue9{zjpliQB|;_)B+YVYGW zZ>#wGn49jo^sb4o9~ybpfByBw(iQVRoc7{5HIcH{M}1mz;n}x*)H3vU^Im>zi`5z( zf4~09Pj}3?|IHu0`^0;tznnAwZclY4L;1(tq%zX-ycUnPswbshQo85WML$eGvS`zP QW_)x1-uZ(bO0QV)fA2dPX8-^I literal 13532 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 GEB_DJ(D%#$ diff --git a/bootstrap/lib/stdlib/ebin/io_lib_format.beam b/bootstrap/lib/stdlib/ebin/io_lib_format.beam index 5556dc733b2cbb854d27bb6ac217f37f8b7fabe2..66047b50703bb2131e68acf986c7292e8cf3e69e 100644 GIT binary patch delta 3695 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 BKe_+_ diff --git a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam index ba644430da4ac1cb08c4b7681cd53ae37e455577..57c700cb3153acb37532a1ed5ab82a7138cd1d48 100644 GIT binary patch delta 6227 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 delta 1033 zcmXYwNlz3(6vw-!8hjEf)J(OGCd5>1%L?Ri&?rD$kab<9CUwUsAFFTUeou@m<3`Q&5)nxmr9hu5UaQ zBgKucvaY2b@JFE-;ze=S>-M-Rib&OzABsU=_Ukgw@ClyRis!Uq6agz4I5F}vxu%#6 zM$5Asnnw6eF%pGY-8U49dtOo8;oV&MMKSEx{6Z*fLG}k_m1N_7Bik^rF9R88%OnNv z0C7fl%^oKKHmYTVrcq=cjV`x((eIY#UN4!tmxgk$k!{3&-iy#tORHmBl}4kUDs!dG z6>h0_nRXc6x3oW#YuTt7Jt&G=v@5r^GM+aB;$caQF&c~e6LPaYyctMK2ji|uEz2(F zIf>0aOy-;7W-=P@5)(X)aFd9>MxVJdE=u;1Hj+^-6!(?MaKukoI?&@XnzYo9Wo*JS z9_5Q-TCE6l7KgRITX{IGL-DCZe{-rbl{Y2vWI#M-^cXpF0g^nC+9`YK$5fY?;l@SK zVbVdsXgU;=X|)+k13l=)Q%grsZ8NIPHfsU%%+gVicC2o0hp3~yb*@X?Q6(;M_RkgM zW8)S40Lrwi!Dfy%`uDs`)D`3>zYwyO7}etz#g1{Gk2m~YSUQ0MTTo!WS&Ea4URpW{ z(t+x)jPeb7&IQ7`?G{8l>$!(AxyPvvdZi6XZR}MMfViodwwj z@-ZQwES&=hKo%47**XB*9Y$YFj$7xT9Aoq~f$;hkUGRQXzTrmUt~H)7cn1)J7NKqF z_#(-uwFdP3O*C&OP^R_uO;uO!htS z;0Yej>7%DjpK49b9Fp*O28BEx&y|C^GMz1L^L(u>U75N}d)?gD_J&O9!nUU7xr3TJ zTN~Qu4QXqcTi4v#+1|NLzEVqDrg>g-r_|C_*KBuWmU=Ut3!6*lHnes%4{B|0o0mzK z1Ju0EhK_Wz-P~2au&t%By{WlwVWy?EWL{$_gEnYRLsLWNywc`l7dEttQzlLEwzao4 z5AJMU)ZE$CT-w#z(%3Auw9Rd4YsoAXI~tm#OlLz&E0FchY0snww>CF4;X%+uyJ1Nw zq1H8|X<-MNHDsE_rj|uwXR{5=TI{mL>6T1$S4Tr*b7^C`-R|&a8WuDUS=iCh+}YTG zzB1{~_QgXMwl$_P-sYykF1`UgcQ!O;fDe&oPD@)u=h7jq?TdM{A(@s;Ycl~T35SQw zS(<6C>uNc!S!`%+mFBc$*n>pHbK6^+$^gJ6+wlHi33Dk=`5{QOEwtw}cMj_4Y@XY) zq_hho%77{ztw7&9zrCdmBVR&fEo;l9>v-A=Dm4vmYquLRjcH$7^O8(~`oq{0k-r0N zGbN235@%7}1R^@;?6c6?83V=_tvx z4kCuuxwlSVLsJvT-o~|UNMlDG?_p>mRX3pwnAUYQH*_|phw)n;*&*&@W5-ac;|^h) zzWQ~o?d=_D9<+ijf^7ntNn=mk=t+)Y9NpU$I`!}GBi6W$LP-A-=v{Y{A7=?z;E+Ey>(%eC@S>nM9r7rT`L zotBQ$&X#%UOc_f<4d-Tt@+8YH#XuUGN;~QQpvLC5OlNZ$L7^(Jw$O4WuyxckJu%s4 zPh<*M86{ZupavMKwx*$Wd(%P;04A}0n|aNdx}xXd8X1N?CTgvXp<^O@Owc0QNG;zU zj{~w9{C?S^wSqCD{5cHFM1V=caCkf?_F%5?I2o&7@4m?%2I zS$>ZYaUvzd=lBJKatz9;cB)H;clw3;@#l&&Jc*OVa=(A7D0-cGufI9GP+Vbn#ZrH> zU+6H-7Ki&~p-YKnLH~5G$hwy*s(i!69v{HG=a2ZOiGJ})aa8bI(YbN3KPX7UbrcbvlI*PAPZXqp zv#Dfw85NC)`9_Mk?SMAhQJbC4_U$N0I~q|M?JI(`6HmPkYTtc}& zXng*WK?m+spYqukYN%$Ph)F>OJ3^IICL5euiNGbuU6R3pePIRPElneStLGp>C z>dQv^_AJ}h7b_d((*;S_d=usJh+#y%h8!?NP-?W-|A-@PyS&tI1Vp(aUHkI9OjSS+Okvj9~z_`wIZu5dZ_CSt3t|K(W#8xh0V88ITH;YdM{DF|V!f-W<; z7(3Xr)+if|o)l8&h;Ir?Cpps2R1x%_TpkP>GH1U+b-k==fK^5LUXB!^s$j?z-M6=b zzW1Ii`}SfiNP-1Z!Ge7RX`h78P^K!;r0z44ai1Yp`i$r}j}e6!Yv&1)5%=w-l=~w< z%1}f{+QsX)uZ0oFfgXNg-01|3>iq8_H1E8aVWI;3!A7z~FJ8*?>mLScV9HmE) zry68BNRSRJWE_NyYC)>@M}lO*m_a(oeGp}UIvAk#BT$E~@YM)X4O-$6pbkOHT0yGi z+6TdLq%fnTC>tf5!`d$x>>))J#t$I1wFngsEr6U2kcSD?+ zJs5XPe_(=C2N`GG)VGqPHf)rYrM@|`$2C85Fm1R~h7@IUMx!I?z-4 zFpmNAeO=6(sk0V_c?-ilEl6{FeG3Yh&*zxWFT#9Y9`ikc`Jse)oMS$(KQKW`=P_?# zn9paJFDPKXpa}B>!@Sjzs(|@!z}$}ey2Nr1?AoNk{u>j%PRyUO*z0Q-gBX6h;?aC< zvOgG{E|-YIJ)lcl+}AEcc-TXG%-13MjUdd4I9Yul4z98p@Pb$h&wX&GajM?9H&2#6JEy0(lUr`?MSCFwzhkPd+GlC$>zL{Kda5Js2h7MOWQ#CcW6Y=qX8Ui6*#Qi*(+IPA4(c=)Gb@kTEMNvl z?{r{xdLFaYE@rE@irJbX%uaWtS%g{6kq!iA(P}|DBj!63M5$g@YDmMQ(R@l#kXl{} zpFvT2eQU)?bct_mRO$9C#?2t1RQ!<$GtXp7&Mfy=(>$5v;(riCbCAm^m>hCC*E-U{ zCb~Y$k!sMj4*PU=ktMCg0CnFvBDg=rw@#4GAvuSaD;?quT6YT4I^B0Je5iB#e5i97 z*z+9eP=Jd8-1(S}$W3$v=>kVOjB>#kr#!+OIOh1U8DTc4Jl=O9sLb`~aH6d@3SZnP zNm92ZHB3&9@YY+Ks(hD%)Rz*e{j%=62qU@BAM{KQ!B&vyTr}D1yOhm6my~I~iv{Uo zSP}?~NPdqa9Vz)G8CYCG=7j2B8u#_^RF5MaLA+S+NJjzJJyGj2@&FXLt4BjN&d*ce zXelTK{DO43BOOB(4MDo1+;5Oq8U>f?Fs(cJx^-^dD;=pGbrT@V2Hn?7US+TDy9zdo z{33e1D(<^dE@D8#fO*p17F}+1q&Wan1>CL<`>v5Ibl)|^?rY+{jf&>mC|CM63NpFK z%tvCTuQ3k@o(B0z_R&D%Z;sRiK$DQX)@9T6f^?lDHB&CYUq9Y=gFM5d`)&mI8*tr- zIsQ6E*qbo}-y}#k6(Kv9sRIc}Y0zE)L~kxCoaYvnP3AMceI_d0;z((9wHK1NB00;C z#BGk$f;@8hZbx#KU&4~+4o8}g%zc3AoeAGvFx5&F_vq!(WTo#eWt<29ljA(&k>2b` z3!oy>NV!7B1dIg<1obY$Lf!frFAl={Vdk8vtRa7)q`yPlIp5#j0x+{GT$b{ho z48sRxVA!#|v|1XeR4AmIK$4c5(gR$6Hb%t_fWYQH!tz*#@;^Arov<_`6247rwsfSf z<)uLyfdbd@evAN`@gPR<=$0eMun|0{qs);OE-&>^Gd_}se15i^qKS0t-Tj?)x7_zg zzs~+%<$L%)b@niIhDJqQJz`+x>tU!o>PVeLzki@hGC_|y(jw4t8d&^z!uO=h;-}=P zaNm}te;23TQXWb8TN zd)hnID=P`#Gw31;kk3SAZXqEBkAsF!>%M2axI_dE7^k0!`=0gU644pUc(!0f0hGq@ zoFgp(?n&UjIqZ90rlt^)=ku5>1ty~$iEhOR9mlij2A;m);`O47*Na7XZ3bR1=)M<$ z*NX+bUX1%*0$wi_@Or5Tucd_7%Z_wB@Jc~8UkUqO&Exf|yL^WAg*kW#)84WU_(97U zdI2nN@(VmFT24jFIf}0ZrUr;~ue&I|o<|XIAc3!7{IBW0*8{j1mgGFY9{0Twz{Rkn zj5k~?17OKA!t$SvbONxP4lLgc``*f9`PLR#o=B*i$caX`5yn7dyQxMuuR%AE^=%jD zcU+v`>5uc9!1-<6_YQD=r-1W2ao@YZ`P~A}?-t>FBH{d=Bb@}C_eJaX6TS}sn+(zi z+#r3x4AKWo-9Jz^!}Ls7WLIe47o-pJVzGj0Ho{Or#IR&IvJ|uMy$@c0SmpZ&s`c@f zdc2Y;&qq4S@|NghM_NHRed0)~fYS`n@zY-4=LJjj8Mj2AktO}XRf7VgP?9MM?-}kZr75deY*3j7h?MP<;(fz>j-+Fz26gd7n=lJi$@!uK8e`omq zE(71+D-=gM6BCe8JpX_ezi)m1Vew6^lyI-qgbGZeXL0WT3Br(FJsXn{#zO+|8^-fT zzv<+^v|g^26u14eO7n<4nz$t`&LLW;9vx*Y$cHId6~da=TS25zO9~T<3XIMIaa16> zZl<7?I?`ImhdRiS&IPUZ2b94vtxW9IhA0O;I_8qH?ah zB*EkJuu9t2kKDUg$0}_nP<*x*02IibXaAch|hwk!`3%17%3JpsKuOk#=kxSa+PRg~iFT7Dgabo47*T zO;C5^A{Q=?1QEt?L-kjK;oBy(2~2UywDHoIkQ~;=BM=>c_E6a3nqtso5XJ*RUi3FA z>eY5QY4nQBq9-DBDw{ZxxG_t3ORLA59&64zj{ic|{+G|F}bd9DTK+X-rPpa$uVbTu(8=1A9p2?wFYp1s;6nbtG1v0AI*8dMeS zR<(pkyoe7u4l_a(NgCm zUWGjp(486MjZv8|jr`L?v{u0$8gU`TxDeL%_J*ctlLd8>FA|L8+wdj-mNf-+GRQF6Ff!t1(vfbZdkVy& z`*cUT6Wl!*DzeyY7;C+jkIs+}3 zj+wk^k&fLxuV90u_V1@-_h2a7C$xhYcgwT`xQ-oAq+|CM zgC?pSP|&gasHj()#dK^I>6q0|$E>(EtDs}EV%mXQ=-7dpR^3m>s^ePCKpi_s*J@oI z+ZP&hFlWO3oC!4pb*$Er?jbH5;z$pG3pHqQXs>oeLB|f~I(9he*ldxQaoCU}pks$K zW^96v!N_h+$u>cJ4lU-#VQ9pZY&LJ*U&$UESpD$-pkxnmHZ(CdgtcQx$&M7%Beqns zEo%zuk)&jQ2Z#{~?I`Ol##z)>@=w&lH0us{%-6 z)!LYnwULt9{glj(Yi$K3Yl~^^TPRt(rgijFvW~dcHBiZp)wPVPWOJc1otz2JaVB&P zRI-dCJxyF#=t!Hvg+tI{QLlDfLCKbKC0j~LwuC9!Vy0wE88e>$YbARg;*fpkyy{HmqW72x}*hk{vIo$8D)(ThO5j$5p(yMe|ycns}owzg|&vmTEk$i zVX$(_=Heq8EVTX>oYx(~+L_{tDcTu=x+bROaA*M006H|lV-1eOY~KO$<|XZ5@0Mk+wnAvwO64gcMs;Q^q-t^bXN? z9U9U7Tt|8zv^gBKIWM7I#Ap-NE<_kmy8r}|D>a7^$ib>=Jkpza{K!zaH~s-k#Ch=V z9O*;aN7K&74v)KnJfD~za95BQ=$aGd2FmeKJX-WlS4!aHedOKp(1m)Trd`B{tiaVo zrH`qXV%59|FzApGZ67<*CtHJYu_JwofgJ$?UXsvm#lWJ;X^N+2n&NNNw5y}#)g1=r z`)I&OA_|}zV#;XbWBQD9Vk3rO>|uRO zyG-{Rp6NPv!Bg1urW%)N+U2~7&ND8LYY(RkU1s>us=HcHuNZ*M*Mv>4wt*S)4P?l# z?APs;acx7P+YK?Tw_wQg-S%qQRcPWb;Bi%4dn83G5+Z}!?Z!g4Mj(|n5Uc%$Ixc41 z)iLeXXs`A}v_rf~?CMyeJt4~2-^8t(_BZA7?rsAU1m8HU(T&EG5v?_nO@@-0rUYTI zt`WnXaknD)y1olNEdP+3JjG$g)G|5IrVVjM_y>Fo(*CezXiG9SU z3Z3Eo9ao#bAzM~r+GEh9?`er%3+OB%Q_k{Ih^s6^YNyvifd^_$6STi zY2+CNi0Nqh18085k$z;%zgC2m`-u)65MU(y&!qtPCki8AQN1yQ0MkE0Zh+|@q3+?` zVDz=b(O8iTWV)`So#(MSPQ`;d~OYE zn`9xbZ4!sk=5EN5eq}200EidxP78VHh=e2kn`^|~Tq8oX8%RTNq~ADEkouhwQ6h*9f1HSI3m#5I$5 z#kD5`Mu_7>q6rglH!-LPn?DGfUhQ6{5%-ct+|#eyd*a%?g>LVSY4;U0BH!(Onsz^$ z_zQU4AJ?8jNU>kH59r#{9Lr5H?P3HaH?xpc(paKxjxxdD9IfVpUtet`1BM(jqPn3# zvua_iyjb)fODM5V@bAgfKM#z!=O(!+vm{TBTH?wxC0M{zEy>HX9$2hB zqr39_jNU!G9&Gx1kM5o9&tTA8YIiW7UJg=U;2lmie{~# zVhiy*nz9~;KGXdPNA;RfL4DGN6o728hEKVWNFG_n(-2l_@rtt)2yq4zTS9wPyj&Dx z+P?s^j3^8rff5v~LxM<+*mSSg+!Fs z<(P);OEEP?`=_A39@pL=J;yYka@663bH3;eP5TZ-(5rv;YHu<7^cLBtH&cAZR;Fn0 z3hJA2?JX!Ke|RgVyq~8b9?~8e2rx=sok82-69M+K-Q4C+U5?PCVD+A{!Z33DhvE{4jRd=k^17l#=%DZt}#T~bx%Hs%Xr2uAP| zgf2iPLx(^j!38?tnv7oUN1f#OM<&PKl}JF2KXvi^408NgUXH!;f0kn}ljFc}1A_Lc zu6>p#ftP1}7S=xZLXJaNaY9f*x~<6Z=S(Ew$Ms3Ew@8XPq%V53pGb-m+Ltb#Ujfgr z@_6e11y7yfiJ6uV{ZiMy$|I_~d0&OKuaRaP1~2-di7Fm6`N`@USf@T3+AZ!-k;~Yh5Q>#c_8mt1Pd$f;?<^AC5YP zG}uxBCxjCU-nu&cJE8sN z^657;{|zRfc8d0gp#B!uekX~CF4h)I05AGovno-98RL&$%R^4Pm0w>-5*EqgFMF-s^o?X@rgs9_44Rl=L-JfkFTg=)3qp zOTA!vd#zH|EuBt9mjUW>uwa(PtU-ld0@MpK2eBHuBA9~-NQew30g+jvQiCyn;amiWQi3^zp$iWJR+sp)J-HV+OOmjBY^JhyL*@>o*w{R! z1fQw!q5+?&tZ^Y|xHXPxc(VSXW!|P?iEJNFr zE6}w85(IN-*eZty3+rkGYMC_jQypd;&2m(n@j_cIZCre^CqML z$Qb>X8nA6)wkP2oqg%U+32Qr-6x#vu?FytQVdL5^Zf(yrzkaJzmbrZ~DR`3|V%pDQ zxxwDfQJB{)>RcIiBwt(hlR?lN=yB+;W;}Ce&VC5@R;LmUN$Ig7Y{s)fE}pvp&t39({(ojXGo)L)Rx zE#wb{t+=?N*V4&%wRBS3Xv$yBqD^E%c>u|Th0^mTRA+vosmH8X$lt-&*$4p@)sAV_ zo*YQ1ID5~y)tqvD+7$W!Y({e(QXT^|I};%acl1amON|kn6;1W?_jU9P>76S$&2>UECWD-(^GPBwh_1H(Sm*; zg1phx0)lQNP1OiRe>Gk)^$?cgbgwK^FZ@h~IW1-#6z#QI^Kmt+mBrO?``_YfR`P#| ztC`9EaW!>!Zt^S=)xNlzx(D<9E!wz8T+NyfOBiwEYCJ*lg~(RoYSzSV!A$j7^W90e zUtCSayH?gjin59sM6wWq27j9zbs|m2(=whWT75LZ8bwL|GyY82G7))G^?alP2^M)% zb=L?}`DRRgC33ooFsvTA>Igic^EdFRy+3R?|` z6Iu=VIH6j_%vn8zp)XFTPU6<=NN&ygB6I3wR~NCC^fE_tFXE=x?+sgrk~ORGk~OO# zEa zE?~*Cj*eN!6l_@@OI~!0X4L^maC*RHInS<(TkYgO4x|+@BwE$$RtHXXcCbLG*$}fP zh`m-O9|*NFED(y@e+`6MbN;tLs5z%N5UTFYjTD`5Aiu1uC=j|2H&l(xQ0Z2u;;2SG z5Xur{s0?l`3V~2-BK*?E9;=g7&rzr5%?lFT$D5irF9?KM$MQfZOEB}&XFO=N($r&h z5uCg$f<-%JH@nX%cad(+&1d9&m3b~4+DV`wrD5bEaP&l%h*9AB^s zY*7L~&V*Dia_2rs^%5r4OGv60d&vkuwV5_?fm|H7mU!J!!3!pJToSXE7Npwi>K-pz zs#(VY2o5gxlj`H*)-uOlwgPLamsrIZZJ6DTn}QeVT5q z9^kdC9&eq_yq43q=C!P0UJI9Pw*3gNSTh0cW^+=Xxz? zZt1nG?Xj*K;I%M6u4Zc-Sk4;Yv79yDI-B8h4)8gpT$YVK-+a{-An;_e?v#HMRZ=23zw&^_5uXDFDI`BWDX$`=-+ z>{^=(|I9LWImDJ-D};07mQY0_t6Vz zi*e&G=qIc@085m^*1b^?C&UKPoAl;A3F|(9!VxxBj8|UK09E>4ccohQ5_DMW`=}N^ zf-_adIMrrsN{&ca_q(Xvk5H`_r^~E6f%^RnADT@caMZaNPb2ueDPg^f%8gwK>qYr; z8B_F&jbZD##+BtAYq6=aGGKJEIW@`7*2tKP=F$89SZ{@`hsCnVz1D*%@>L$p?>Qu= zSbrDH2V>SlDLQorDglwt(fe87wR9fJAr z^yUf!k8zZZiuR4=>4f!+3;P+seukY1ad+H?cYq1c#I0uuOT*igtuJgt8Ts!eamjg> z`XoBiaul&5*7CVtYjd(2MBhwA@1EXR0{Xrnn44qP^GUzaJw1uajUvx{p4CW#=r0fz zy2L>kyI{T;v)*kiU)#;SCLD3X;i($tG(|Ipyoz2&P-LS^p`9Kz?KSL=T!&i0`wn{8 zdPxTF?IEd%xY!;dMid;!T8TtAi+waDsjJ!=BNH`N(MAZ-d#zx;l(2ouR0TVBaLJlr zdRj1xUkX{8oUzNncg=beynh|Me_1eJ?zPKc;n&z@qTjQa{*!qDHuK32VI@NezHc<2 z43aEn64oo;sb1P6dIcnZ1?+rHFkgvVuabjD^KX%ypyXA}9!e#G`5G}a6_61)RHlnc z4Pzxnfrtn&T_wBtzn-w(p#7^Wyy)T$bnyn`s?N82hpz=!--uiPB$$T2D%<^6T>U3? zoIk7wADOj$Ghw||0R9$$zXkl?5zM#Z*4r-rT-KX#9E{ zFHry8g!KSayfJS5TP*MHVAD`zKjntk>8K013HcdTApj-+HV|TQJPJ6Yw3TZ=!et*Z z?SG$X|NArvzZW9?4v{eaB$)5Tt@lGlh(Ej^vpy)8gAhq3YJ8wsAMz$Cp7CMa9u}g| zREV8*pi^gjtCJUh1naO3vkqTFLOzGId@PtBC#+9gHTwiK`$U{#eI}Tn#H~-6bs(On zinxxlPYY`N*;cJXhDmF;V1AykzHmW*0nlFn^jCuUMcn#w3+sUVFAHG5B4G-_I%Kx6 z4&3qp_SXsP8yEIBfc*`VBVJ!*!Lo1S*1u>3*^a*wqJQO0L&h}?-4MTTd#&#oN4_VH zd>3FA*X77}aqD~dft;A%$E+U;90|A_`9ZUOUjEn@YxVE)ZnnxZ zYS^xHG-W8YhKxvV#x++Z@NaC_R$(dqdw^_|obiZDY+0+3fo^p~jpj%b;jut$*}AnUlpBzh;O?2%-`?9#GPwg+bH55fF{kzaSa z`4ipzDf{uIDl+Eur7GgspN6-%qyF|k?di1xN(4qQAVz>b{<}u7jf`LhMi2>Z1lza~ ztWDSg-~Y5rWX;BrXTDJ$*kYsH)9*-E0G4iw?G@63ZkOm_ID04w+hSmbhi^8qjZ3ya z&dQjQvOK;G2-Mxn!ZDA*oWp}u_bKjX>W(6C;2b<(1<@_(?J=L zqCIq2?l`J3-X1Hin5JWOVUMBJh3*dkAQlY+k4jI|-Sq{X?a+nv7&_Zgq5wE;5*&{e z26jT(R?~Dj1n&SZH0bzzp}lRjklv1Wu)W*C{{nvdBJkN@#8H>^>%q%=z?-b-0fgBh zW(T9gjCuqH>0l*JM%J)z?WxOYC57->kG-QCKfsnY%oS^B2|;(rjk25}8dD=?TOjSHF~-rJeJVhD!8B|&uZivRDK?~p&H+p>I?HR12RV0- z+0p-amUj*4fD=;Qggud*Ku0~DOd_4*MS>f6d@F>XjxQM(n5?=XjCmPS|_6 zMn3|hA3^*7?>XM|9=aXTT@#k_(&lwK61FG&w{yJd377&5?|(bTo1WNX*RVhUtpRnI z54P?D^Ff_xl|2(onJGu&_ROsu*Ud4P)ZUlG&I?OL{)nTV!Rc=FZP}YuN0*MtolK>lXEN<@!w-v|1_`zj%$~PauWb69$o|-*7l%E86t9Zgr zaCgT}0B8dCA~nUHB%~8@yNWrY5T3$;VJfK7>_cGcC-vHUVUe@c-V6SkjS~u>P73Gt z?0tmvT+VY3JV)m3!{%wX74)IZqDVn`EZ-Udpl(Bc*u1#(2v~YSKQo8^d6e76M zYvUyhbPLVX?5W)6qi&}Q>8Wvh8r($wFfC>$3*82&ThvHuc8WKlZjq6S+lLiJ$@0e( z=$LYPI(5t}8Fjp`ZXYft>=`ZxW`I~T3LIc3gwr$Pwn-ewZv9Yk+AJnNZ!$AxhqpXb zd={xx!lv^EWUP*aE}cydhYs06f@>H1U=6}Hz4j4w#L7N`DV2965>TrBTs-%OQth8t zs{ieX6+8Ev-cPsp&&vuwRGi*FY#;F74i%>l00H=MldT@H;=rvQ`$$r$ggwi}^FZKv zU>?u^?TA$g9R*9z((MEDc;bVylyzX(uBHQ4;KUXOtl07HbTyUz<@u@-3WB8%g3%pk``p6I75>6kTu;)MuqRE&&CyKp9%*P7+-4Lc|CI2!7zUaeVrs%Pc zDfkQ6hY69ta5P{XQ)$=H-j7T>ROdYw zTX8G!`qPy%HkQc8ZV=M-04k&#`1g;q5gcZ7+(}WSgWKsj+>=Oe&6Bv0nY(!yT*14$ zh#R{`m__FAaOFE1%GX$FH&x)&7u#t|G3V-HJ`VP=A1^*Z$j5=I| zR$W6H3C=m%bA@y>U<>KF-0NWaduhLs%+u{w_99|B9kY+x>X}L#Unu_TGnLqm^TIZZ zaMN2T%nhGGr@)Txs6E8LguMWyz?#msl}dX)_yvC=1jS#^$9Wn5s8OD+a2@a>JaaI> zSCaC}`{BEw$F@lr*bA|w6WA8NkYvk7e{^qi)GHuk^T7D_giW6fR-)im5?(}&W_K#( za7>fT`IE8LtJCKS6{zQxoJGfiML<75=;NC^a0!hJ$0rnT<6g#MDcY&w~iPmh%LfYZPXVfrX3F$5pjTDGO zBt@*rQLh3yuIaHej0mZG-w>q?Eob9Li%`;HYRF}Th|d? z5;l9k9>Ug5BIKyoGjd$-l7r-BS&!Y_Pk@$#(`407z!>R%B1l4l)a|I((fuSxy#WH% z0)bkQuxWQ0+W_{-2-{)OJy{9ctCVE%Tj!2?BL(Eb_DV$KKq*pod~g*Cyb^4r4f*sc z_OiQ;b;Zds`_!V>(c#l0%8PG>sW;{0yJ7nj#B~wQfJcXI1Nw4n`V?ByFQ#VX`E<99Ky4X}W#7 z$aW{FY&E^BPFl&4yR{FwH9(G4BT-w!qcAx)3X>z%VlsF-upwIJ9F@LzlRm>yZv#!| zgD7VvZ1pS&FGoHb}c=@gJn()Wt@eN z8x4xsXA0@FWA?gec@Uq|!%7C5e6$qJkK>NMahy{ivTJeA1i#P0c)S4WsCP2ycSL+; zk1QOs$y8%q!ag5ZL$}V~+FWoKXTfHY* zk#U}GUnr9F&=TPMzAta~vE-hR!M(aRrUCiyZY{3W!|nsPt`|^d*jZA2_!FW4|~d-YWchO4z5+Dm;(P_FQ7>0I>L!4&As-vuH`8QD z^n)D4Mu0#Z+`cNHbBQJnJ%rCcj|khnFh+Rwn1r^sKt<*e{T&8k1I3>xx=()4RfY2W zt7Q1pP5&wz(I??^wWB@)eAeB#sYcb_+)9qUb95!R00hrEeA$`X(`_Ag;#F|R`F1bcX-&twj zEek^WF86mG$|grq|L$JN$MW{ zLaz?ls0SwZ=r-ODpV7^q?se4X^IPgj@MQ=-H3J&U2-si?F-enftyl^s*9+#T z{vYQ3i!83GyWu+Z1%?E@xeb<(uk#{D;(iDxUWF$F?oZecc&B1xENnj@>oNNQjP)hz zx)#-u;PHi*czglt@}!|h`{D3_>x7q0_A-E*!XQxL9AepIo#j60sLv6@A9B=}P5AhK zchnc?`C&(Wg`OV)g-O64b<|fWAMa|v299PTLi(|={W#Ryjlq{q#*c`kA5Yj%C{vYa zQn#N-;!ElO5luQHxfYy3rN$ScLB187tqO4`^9K~D!$0Rl2`cM5cN&^ z&`$a#-F_MCZnopWsr|AG8s8&z>%8KqZ-K;%(D|#q_PYfVzuiaTw~55Ba}vMKNc=h@ z@#{&v@?KA$Oo3v+`%}mjB`r$=`rBMSUlUj0NIgxYDK`}KYPFDlZDS~~Aw>Jyh~207 z9Q3+w|5F|op;#oNW5A$gmCC+~W53rY`0sMSZ;(|6NZ0Pa3jE(7I^kp_qtibNVNDkr zD(LrA|_q#raJyyb#qQ^VVgFYgTC z%R2-3@&V(^ySn{Bf4;njfs(Sk5A^8%K@p#Ln-3lJL-1)a@c2l#KURwUL-KCbk8l8v z{l_nS(a$JF$x#f6rH1_}X!CKx{*btjp+JF)|cQNx>Lo)8(T@6h=tj`|7kSc2rIz4pIEBY9O)tX^V&m86eX;8so6vxXaC z$VI^j%e5pLSe&Szg5EH|U%~)?!ws;beug!hG_n@o)(r&~+h4F3FltvK(Y+z$rI#+4 zUVcsvPQ?BUYwyotnbz1}<3~sr(|_i3FsYKUSowmi9i4h&2@14+kvDtX=5e~z3+c~v zK=Ri!eWq1XE$kCBbDz`xE>3c=OuSM<7WNBQY#sGWV$zpk;9oYmkogrETah+-sS&id zgthu=V^Z7z8ae9M)aq+T{f6x1Hy{MrNxX#3^1pS|e}S+|p&sA$=1MTBT~#C2FR}lm ziES}%*mmspG?uStd-@bM!dk2EG>5Xvkk`>yI2$qAZ#jkk5GUn?JcYkw6kaE;+gO`g zZ2w;CS%*oEB?xW^qT;CELp7kxiJS*+saLnZUxn-`_K!mP`>_2(2%gz0{`dolerOfY z|B)T>_<=L#-(bvdAW6*r$%}3_)QVVb|H#SWCTRcf$NW49zY6J}!}c%Omt>vd@fW6V)akDU8m|+FuLo!Tt)pLJBXA<(>%>MX_>FDTuVQS} z!A8pay@1+J#E?J2AQIS^$M@%fY+S`!{kgG5+yIU^>Mv-O#lXHts4FXg+F)b0#LWj4 ze+3(l^9xzHS-%37G+cydlf_Qxzfo{}P{X`kY1aDBT=Z4^w9xB8Z=AUT096*O@ zIiG9@QG#pafYLUO>7g=1$odnx;eeY2+zL7AnE1F0`-KXuu%i6)BfLq4W8yO|2Jedj z8LsEH5n*%Cm+Y93^0E`qS0J8)XTt_CQpk>QOfMB+03#E*ZP@@4xzSiOBx}OC(a9*8 z9n2iqF%#L$Au`)wmf|OCb`Ix8!MgKBWOkHe4r0Gvq2q(om@fiewp|1bj^yxLd)d*B zIk<=x=zCi|H^QaG7{`==#)-ghyLfI)A1!tevfDf65Gn(V9TGX(cuk6l+)hBTrZJq` zsU}I^18ZdaMnKW^B$LaVpy!%8*O-LoO9%mN&OUwUFJ>G0V471$Kyx5UaA2 zWBQ6n4BUcxZhM!+V;yrC(Co$#c249Jpow5XF62@&gw-eFP4uO^+|EK)(Q_d&o*Rpg z@e+GNNb*PeA2oFLLhh3 zF)P>vnHxvL9nQuQKok+{V=pm5MXPb-gu++J?xyD|MJ}Xa$CLqd1$rAF&xPIIb{Ddm zV+N=I?RHP(A_IFH!F$_-d$t60562w2MYp@7c|_0QR~wm1OmIy4^~IIwZDKeVl`G;o zCZSO+H$kqvKh@OUDZU_7YIB@k6H$AEG4I{h@V~*Vq z&oBt|)G;NkbkhA!-s_n1F3OL6+Nv93fWpj zyD;=ah3p}YIgTb7is*}SqT<#&ESx(8KY^M%#6^3yV}{Z0bO1X% zo|`Rdx!Dlk+4PBgYH_5HJ;E`^Qw=~qGMqaKC5)U$Ii}`zQ1l~F=oUYhx(QNF{vz!f z=8gpDqaAa1z@XXU82q>?sZG6*t#iyhC>Is#wOpMWN1%BEKilb;5pN_1mk@3ziQycy zZE(y9XmAElnUl!Tn|35XjWPmfAU5+i5t=MJ6OAWQW89d7LY9RCL063!)*K<*q~{vI z^9in*CwXml%qYOGMWwmGlE$AFvhy4h`&wmd(P>)C&69D#Q6`mkzaNNG2PS?lF;`!i zYk_mh*9zGd!h?cvv>oS|_!&eDrUI@n7JW$yWL4)D0OWkfj05^v)k1bbBG--~(L~Xz zU_!IucwyCJCh+T3z^;|$_=6qOYm!L{4K|8{07J;y;arJ* zOUQOQ=48qR$+{-XxlWv88=YHJc1~_#*_pYFkj=Q>~VRBRx6hUZC4@ zN|pw5CwYYIV#l09@IaX*fVY^zJ07r(1I(pDb}9UQ^b8os@e}|b&kZb|9g}`I5kE7? zzyZ@`j=2xOtpj??6FK_OEEdbT6Ch!1azo=2wA?a;46-Ncxn&UkWw3iB3f+!LznOS0 z8lIHMt)hmIw3RY~;EeOs7k)S~caol4!NPRe6~)GRW!~mbqdLVUtMptq`ssH2IoUCj z=m#;{>?vCAWErF&vC9hCQynu!C7?uB%blt?=5)Lz2EQ*_nL7>K#~5JGBe|H6J*_gg zItqmLWzz=zC`~RWWLJlCYoau?HI6xBrjR||F--tG4*+w79%4QU*lPmATKb+K!dRv$ z;SFRVdxm4qMAdVE)tOrEj67Cn3E8!dNxyq|4uG7c<<!~Ek_;m0Kx&?vJ`&J z0rm&{nkZz?uFRc7NaD>l%xw(G^Mvd<;oLfg ziUOn}9m-fY#eYzZyQ>UK5cuNC+$Ds2Eyq2{Qq>*Fu}B@lT-<09ASp>hqcDDwtP!%H zbvd$z6phK92iz|S=PqR7}kuvFeV z2U1r!=HaMzpespYN`Rb2Skdu{{1L+zMHFg>Twyn_N8SlK2u*E<9s>NAflF6(7w zuj2oZw@`LeaoJU9yU{U^MmHCso2#|lwdm$r`rU@yHTc~I$HWUgSlsbmu3<&*sJXul z`4L5RMMZyOML*;JkUvmVUsQB0`nb+98_>ta=;Qi$?gsnACv}?1PR;Z|htE2oEK4 zfA51Z7cH(Vf&fULZP0TOlPeJe>3e4+=W|_L}e+^BRFMlnsAeg(s87z9^tdMn@{x(T>1Pxit>pL`TS5(esxiL7dK5X$GK_h zcQ!6+dlastapiGKyJ^br!bNqc{-wC`b=D6^mrP$myc3&{Z{q6V<=(s8G;ZEI@XsBe zmw0>$F2M8Ng!{#A`g+_QTq5!>chl(KyB_Ha-24mOH04v?Id1-0ZkqDXM4B#wlXcUS ze+trPyZKApH09GcDWC8;7WcKds4dZg(o|lywap`WFXiVcI9EdLwH@yP)yj(9uIPdF0YDPMKd zlutS)<03d?arto(9MT&~Q~l9yn(B|hH53=sr}Df#ARQg-<`eJeqB;bN+EKdXfR;=x z?j&=!ExEX{zW$x2`uh3>&op;??*C}};N$C_-t_R3=RS6BY12@BUi6#v=VL~X+4iCf zE_9BZUGhli!srDDkDgt#X7#sg4jz5yx8J@W{cgX5U#MBr-MO>c**f#Iai>lHwEkbM zgM_B8gOC0p)BWBY^|Pw(xf?$Gpz=IV^X!u*9)5WJjFZ;g`0C)0cRBamv)yygy))Tk-~A_f zJS!iWQ9a$Bo;e`l@eB!jJf16tbZ5F++vob)TDvp#nU4B7Z5@r7()sPpEpvvnbhS0M z&mGp@I;Xy+tE;1HvwWr2_Dsv%mM*2WyS~Ng%q;R|y5_f(&S`AxZW+?n(mpqnE(fT& zU5%aT7N@1Ve13atQ%7@4{rpU8Tglv}QVwm%?8fHCuDPWxN6&9;lc()6&D-A5-ZHeS z<(QVP?v~Q-w$`Q=rL}!dYkO;Ek=)tXtYo?xTibxFcXmf6J+!T*u^A7NE<242O9{2^ zVa@Y9(X27kA~&}lBX_kpz^v6NTaa$ev~+hiHno&Cr8}HXZ>I66mSOWdJ6pP%8qrrK z-PN&R*!=dUG{)P~Jk-TEfak8prVQ{Q(#&pcZ|qt$tgT~#Xf`a*HIjBFPzy@CK>wiR{ zFHdz|R$h2Q(NGeI`nK*N;y%P_A!3W%jGLQ*C_w&O+gqB4pb411SreqDwXLPTvoQm4 zXdglXRNppK+?vE=Mm%Pk6v4XsNkcjFKp~f7_0DjSs_$%VI;y;%fBgmBN40jAWZH%h zL+jmJm#?w88Dwu4+BU4IvtINtypXD&R0d4zyIUH&n$jc0EsyLl_pzySIMs27uvvfo z`nHaa&QdNrBZ_ic+mG=Ne5{`|IHSF|0Zd78IUWZ#pp3~fq;E)5M?17sZc2A~fp3?L z5^op&DQ)h^ywKM6(kA*pq45om69^oXIc>ja}V9s7tww5^=1zpxt_KIvsb_lPvdy2! z6!0=i@a!RtFjVc$!<~-i`4|99V#j84TQc=U&m(m*3_DHM+nT~hMt7Q|NA=NqzC9iX zWpnrgvd8KLV@CP2Ihe@+lZ4^$cuv?0bA=xl{jKwOybt4kj^t8(C+`$jkiF`o523zj~!A2UonT20fu=FRMMKDw`qI zltM$IzWb#O>r{Cy%1ucf67=0Ey_-*b&3Z~k-t3nY{|LXIts3h0Cwvw1blEGjHD15Z z?+^N`y)y4!shHv$DfjvS=6!$EKSTD*SIA?6-^%R9q5hzxj5JV0cq%GewWlm80k*zm zWEmBWs`8DNajC;gqp}LjmC-=s2}v2lHc*wQq>P;!@{Ji|F7<7`+BZ&8#-V(aq->7c z^OCX!dzY%2lCovQw^gicBnCBBQno^yEvU^lt9@Hb%GPF#M*FIyY$H-{NlK7?jg~3~ zIKIyp%2Ua=EhiIhc{-I)%g-cb+dQF4h)^F$O32Ko!c6f4RsiGKPWOdX4VP5z51L?^ zQsE8yzA=2;W0c!_&6yrSi0wH!Dw#5p8e){1?wf#y6I2O_P^E8z6e1gUl~y=rMtABuh_M12!O5npAfY*fDEfM^pzn@E4h5#I4csw!3abeVtw zlx~*LZAYez0z#t!aVK+FFlLsG2@NrQF-eIsWi*ul)k#z$awjuo4CR9UF_3)nn1-^k zzMad)`Krps_zX!gbl+sPJZhRTuc-!18I&69^*_p#aZ5`5Wnp>o_rr_byyXBMM1&1zrkNEqx0g-1XF?_QxL*71-i`TV*F6g zDzj`XdJ2&`M}5;!x(idbrHY{c)be1^R0aD(RM*R^26$DJ@5+=gRRu$)8NS^@=zF)R zs&7}$f+Scl9W2;gQg%=H%+T~uENS@6WZY-Ul|D1JgU5_PjP=!$V#a;DhRXd>AZ3PR zrflc+JL_Ns@_6YCcui0EX1G9R0LTmgnNa|;R8nRT5Lgv}JXumuLx6 zBYKvNQQeWIm{JM!VF{ILbEcmcLD8m3${tM7P!hrzXQFw`Tumalm!w!s*?|f$;#pK6 za`$A)1j>a7?q&G)SF3z`lTfSEe72Ic*2U!KE{Q+uE0(Ib0U#+Cnq9q;y>HxH?laxB4eGnX` zL^vg7)hrPl)_=fY4=AcIaS*9(*nH){0?2~_@*qh$2LhPeH(Ft+CM*6mVBC=d zfk{d|WSn=?&_mFV&*PXM zRlxkHBFqyU^EReT0p=5cxfAzw%jF)}wOxk#Z%p{QFn_9YpRYp>V)z{)kM3(%{lQ?h zS|X41fG+KEUxy0e;SU{EzE0V124PO*Y86v0)#%iHM~fzI#?f)#F=!GpA!ww(QyyW%w-enWdh< zp`~SdkH^cImN9qm$R|+`0l5NAck>2w58}4C)c>v*azd%gVRker;jD(9M3s@Jm>ThNja|1 z*Hhs134+rn6mfcSp3^hH=`P}QQgC|lKwy%xB+u#NIj2wHobD-bx~GWKDbDE=nNkhR zqriM=dDLG)#yTDLon+1of+%}n{+$UuX${YiJz+Bp`pzW(&9@8=+{~yvlBSDg$gjYx zXbts$&8Np%L;Z?>itl837hFNK#B{S@i!fVh&a44udu@!_-W;=239|+P>QomqJCE5uzzmMwX~68X zJZ39g%vNj?vz0}doyL@X2(uhh_626K8c8|5%6A5cQnR?!R7S>P`BW%`)RI#8453h; zZkdECWoBPRZQ96Lf2<9 zr50TquurRtENLAEX!y>O!To8zvnAy$l5=>u$^qV>eXFFLZTQZC4|Ptz4|NU)doEKB z1h^`II}g(lxrt0t&S%O&lnchN@+f!UxZ}fTgo8oliM|U!WuZrh5N*9N_~K?slDaLa z<#KYUx52)5itiGT`Vu0wUp0IeVk8&%gP!UzYz2wVg;Tx0OZeP#ahdMBNK!6>C4s=m zP50fgYL9s$`nFHeCZl%Nvu zOUh+TIg%=xl5%;u-z2Xz1}@cOT4(vX^={oOn9_i{36N#2;p-!>vd{2c37bWJ5j|cR z_g$eDF`#kKJn4)=m+P1^8(^jYx2qz)tJMm_cQvv5>bP%RNcXK%D}C!Em0V=*BXQH$ zlm`S)gZw1t5Fl|4Qt_6T*s6a$_4oAC;DzsXL=0ZjR1cGt{XAOU&jf1 zGiKnMB;}?eWan^oAOR^2I>!Uin~MtPx`ky^#fg+CFL%{L_hnk6zJmmB9%}D_XuvuBY~1&p7nh9Ac*b)DBMP82h7C+v z2;7sv{rQOR1(ljYL|({avIv-rVG7-f5js|6(+xa*(Z%Z}7q6F!@OmD2y=eGe0$wi_ z@Omlkdl`7WT)^w)BD@w6Uav6aIN+6nY`z-ty_U!8HFx<8>kD)65T?Dwo$!MebMyjO z-sBf}RJ4SOmIxGI4@?gb>E3Wrd?Sw{;6MUj#rR)0d~XDBaV*Jsek1OCGk}X@Nf~dt zSO&n7#f0TQnQ}a^tOk~EMSO4Pv3z?YEKeX*P7p+++bDA|vOQFzN7SGj$oh_p^Sdt2 z?+(QIE#Ul);d>W2zgxih-MH^P;QU?z=l6BDSF;wf5jrDjL zSDudzl;thaCrnvNIDN{L<-lns==fQm?~8&Z`dnC|&&d*f&MndB9JS9?pjK0@hWf1# zf;pd$z!D}D7;J@3;<$c=fztecvY_pk1=PI(5`fP@jxRO~k~IkkYw|xg`*Mo!Ul{Sf zHy-gRe8m4UP)2jSHy~C^{{|K`>aUn`64{ThnUclmEuipCpYJ;?Bd!d|(G|XLLws%a zZ3v_P7Hjtq39uw z_eV~_A4AVq`hJn1B`e4)E6g|m^&>CHb9yDG-cQ1YpGKh-G3(H>_opeopE2@ZHy(M8 zkNjr?W!&!k67hYnN>HI+nX;0`{u@(H2cmm|kXUT+1FMk^^yEE+I66U5Pg=-IO* zt&}ONARpQgrkn#>?FA@9tMoFtPano*BoQGeHdJ)XbnZ>LKKyALZA& zNIzex2S^Gpbfqxwh@zVdu|@<#3IS3(?Fi*�(e=%|T>s!>!;EX2#dW`zOb|Wzb-eSD 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 Date: Tue, 28 May 2019 09:38:07 +0200 Subject: [PATCH 21/73] stdlib: Fix a bug concerning io_lib option 'chars_limit' See also https://bugs.erlang.org/browse/ERL-957. --- lib/stdlib/src/io_lib_pretty.erl | 2 ++ lib/stdlib/test/io_SUITE.erl | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl index 8f2fd7ea8f3..ffc02febdc5 100644 --- a/lib/stdlib/src/io_lib_pretty.erl +++ b/lib/stdlib/src/io_lib_pretty.erl @@ -795,6 +795,8 @@ printable_bin0(Bin, D, T, Enc) -> end, printable_bin(Bin, Len, D, Enc). +printable_bin(_Bin, 0, _D, _Enc) -> + false; printable_bin(Bin, Len, D, latin1) -> N = erlang:min(20, Len), L = binary_to_list(Bin, 1, N), diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 824f5d19f2f..7796da66b85 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -32,7 +32,7 @@ io_with_huge_message_queue/1, format_string/1, maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1, otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1, - otp_15159/1, otp_15639/1]). + otp_15159/1, otp_15639/1, otp_15847/1]). -export([pretty/2, trf/3]). @@ -65,7 +65,7 @@ all() -> io_lib_width_too_small, io_with_huge_message_queue, format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175, otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159, - otp_15639]. + otp_15639, otp_15847]. %% Error cases for output. error_1(Config) when is_list(Config) -> @@ -2680,3 +2680,9 @@ otp_15639(_Config) -> "\"12345678\"..." = pretty("123456789"++[x], UOpts), "[[...]|...]" = pretty(["1","2","3","4","5","6","7","8"], UOpts), ok. + +otp_15847(_Config) -> + T = {someRecord,<<"1234567890">>,some,more}, + "{someRecord,<<...>>,...}" = + pretty(T, [{chars_limit,20}, {encoding,latin1}]), + ok. From c664548ad77ff24f7f7eb5ea1e8f2b0057e8889f Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 29 May 2019 13:24:51 +0200 Subject: [PATCH 22/73] Prepare release --- erts/doc/src/notes.xml | 17 +++++++++ erts/vsn.mk | 2 +- lib/compiler/doc/src/notes.xml | 61 +++++++++++++++++++++++++++++++++ lib/compiler/vsn.mk | 2 +- lib/crypto/doc/src/notes.xml | 17 +++++++++ lib/crypto/vsn.mk | 2 +- lib/stdlib/doc/src/notes.xml | 17 +++++++++ lib/stdlib/src/stdlib.appup.src | 8 +++-- lib/stdlib/vsn.mk | 2 +- make/otp_version_tickets | 13 +++++-- 10 files changed, 133 insertions(+), 8 deletions(-) diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index aad7e27f80a..ddf17097bdc 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,23 @@

This document describes the changes made to the ERTS application.

+
Erts 10.4.1 + +
Fixed Bugs and Malfunctions + + +

In nested use of try/catch, rethrowing + an exception using erlang:raise/3 with a different + class would not always be able to change the class of the + exception.

+

+ Own Id: OTP-15834 Aux Id: ERIERL-367

+
+
+
+ +
+
Erts 10.4
Fixed Bugs and Malfunctions diff --git a/erts/vsn.mk b/erts/vsn.mk index 224570fb092..4d8282bf153 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 10.4 +VSN = 10.4.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 275c6268fa6..3090a99c35e 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,67 @@

This document describes the changes made to the Compiler application.

+
Compiler 7.4.1 + +
Fixed Bugs and Malfunctions + + +

The type optimization pass of the compiler could hang + or loop for a long time when analyzing a + setelement/3 call with a varible position.

+

+ Own Id: OTP-15828 Aux Id: ERL-948

+
+ +

Certain complex receive statements would result in an + internal compiler failure.

+

+ Own Id: OTP-15832 Aux Id: ERL-950

+
+ +

Fixed an unsafe type optimization.

+

+ Own Id: OTP-15838

+
+ +

Fixed a crash when optimizing compiler-generated + exceptions (like badmatch) whose offending term was a + constructed binary.

+

+ Own Id: OTP-15839 Aux Id: ERL-954

+
+ +

Fixed a bad optimization related to the ++/2 + operator, where the compiler assumed that it always + produced a list ([] ++ RHS returns RHS + verbatim, even if it's not a list).

+

+ Own Id: OTP-15841

+
+ +

An is_binary/1 test followed by + is_bitstring/1 (or vice versa) could fail because + of an usafe optimization.

+

+ Own Id: OTP-15845

+
+ +

A Core Erlang module where the last clause in a + case matched a map would fail to load.

+

+ Own Id: OTP-15846 Aux Id: ERL-955

+
+ +

Fixed a bug that could cause the compiler to crash + when compiling complex nested case expressions.

+

+ Own Id: OTP-15848 Aux Id: ERL-956

+
+
+
+ +
+
Compiler 7.4
Fixed Bugs and Malfunctions diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 494de072ff2..090579e7eed 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.4 +COMPILER_VSN = 7.4.1 diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index b69657bfa81..5f47981855f 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,23 @@

This document describes the changes made to the Crypto application.

+
Crypto 4.5.1 + +
Fixed Bugs and Malfunctions + + +

+ The cipher aes-ctr was disabled by misstake in + crypto:supports for cryptolibs before 1.0.1. It worked + however in the encrypt and decrypt functions.

+

+ Own Id: OTP-15829

+
+
+
+ +
+
Crypto 4.5
Fixed Bugs and Malfunctions diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index 72a51bfec9c..2315cb3c48d 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 4.5 +CRYPTO_VSN = 4.5.1 diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 605a9f224d2..385f092069e 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,23 @@

This document describes the changes made to the STDLIB application.

+
STDLIB 3.9.1 + +
Fixed Bugs and Malfunctions + + +

Fix a bug that could cause a failure when formatting + binaries using the control sequences p or P + and limiting the output with the option + chars_limit.

+

+ Own Id: OTP-15847 Aux Id: ERL-957

+
+
+
+ +
+
STDLIB 3.9
Fixed Bugs and Malfunctions diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 7038cc159c3..4990c81dfee 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -38,7 +38,9 @@ {<<"^3\\.8$">>,[restart_new_emulator]}, {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], + {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.9$">>,[restart_new_emulator]}, + {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], [{<<"^3\\.5$">>,[restart_new_emulator]}, {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, @@ -50,4 +52,6 @@ {<<"^3\\.8$">>,[restart_new_emulator]}, {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. + {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.9$">>,[restart_new_emulator]}, + {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 07224afdc90..cc0ab6684ca 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 3.9 +STDLIB_VSN = 3.9.1 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index 3728402492e..a9ca1cb1312 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1,2 +1,11 @@ -OTP-15823 -OTP-15825 +OTP-15828 +OTP-15829 +OTP-15832 +OTP-15834 +OTP-15838 +OTP-15839 +OTP-15841 +OTP-15845 +OTP-15846 +OTP-15847 +OTP-15848 From abbe8d424676a473bcebdf3b97996ac7a5a70f16 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 29 May 2019 13:24:52 +0200 Subject: [PATCH 23/73] Updated OTP version --- OTP_VERSION | 2 +- otp_versions.table | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OTP_VERSION b/OTP_VERSION index 01c3bca9e33..95f8a283f00 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0.1 +22.0.2 diff --git a/otp_versions.table b/otp_versions.table index 66136a63dca..ad128ba98b8 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.0.2 : compiler-7.4.1 crypto-4.5.1 erts-10.4.1 stdlib-3.9.1 # asn1-5.0.9 common_test-1.17.3 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3.1 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.1 : ssl-9.3.1 # asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0 : asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3 stdlib-3.9 syntax_tools-2.2 tools-3.2 wx-1.8.8 xmerl-1.3.21 # diameter-2.2.1 et-1.6.4 eunit-2.3.7 ftp-1.0.2 parsetools-2.1.8 tftp-1.0.1 : OTP-21.3.8 : common_test-1.17.2 eldap-1.2.7 erl_interface-3.11.3 erts-10.3.5 public_key-1.6.6 ssl-9.2.3 stdlib-3.8.2 # asn1-5.0.8 compiler-7.3.2 crypto-4.4.2 debugger-4.2.6 dialyzer-3.3.2 diameter-2.2.1 edoc-0.10 erl_docgen-0.9 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 inets-7.0.7 jinterface-1.9.1 kernel-6.3.1 megaco-3.18.4 mnesia-4.15.6 observer-2.9 odbc-2.12.3 os_mon-2.4.7 otp_mibs-1.2.1 parsetools-2.1.8 reltool-0.7.8 runtime_tools-1.13.2 sasl-3.3 snmp-5.2.12 ssh-4.7.6 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 : From 6b8b77173b426cecadd94c04c2c6d904569936a7 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 4 Jun 2019 14:09:38 +0200 Subject: [PATCH 24/73] dialyzer: Correct indentation of field warnings See also https://bugs.erlang.org/browse/ERL-953. --- lib/dialyzer/src/dialyzer.erl | 6 +- .../test/small_SUITE_data/results/union_paren | 30 ++++++-- .../test/small_SUITE_data/src/union_paren.erl | 74 +++++++++++++++++++ 3 files changed, 101 insertions(+), 9 deletions(-) diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl index cfe5fa9b3f9..d4fe064edda 100644 --- a/lib/dialyzer/src/dialyzer.erl +++ b/lib/dialyzer/src/dialyzer.erl @@ -642,11 +642,11 @@ c(Cerl, _I) -> field_diffs(Src, false) -> Src; field_diffs(Src, true) -> - Fields = string:split(Src, " and "), + Fields = string:split(Src, " and ", all), lists:join(" and ", [field_diff(Field) || Field <- Fields]). field_diff(Field) -> - [F | Ts] = string:split(Field, "::"), + [F | Ts] = string:split(Field, "::", all), F ++ " ::" ++ t(lists:flatten(lists:join("::", Ts)), true). rec_type("record "++Src, I) -> @@ -658,7 +658,7 @@ ps("pattern "++Src, I) -> ps("variable "++_=Src, _I) -> Src; ps("record field"++Rest, I) -> - [S, TypeStr] = string:split(Rest, "of type "), + [S, TypeStr] = string:split(Rest, "of type ", all), "record field" ++ S ++ "of type " ++ t(TypeStr, I). %% Scan and parse a type or a literal, and pretty-print it using erl_pp. diff --git a/lib/dialyzer/test/small_SUITE_data/results/union_paren b/lib/dialyzer/test/small_SUITE_data/results/union_paren index 3a3526df898..1766773f2d7 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/union_paren +++ b/lib/dialyzer/test/small_SUITE_data/results/union_paren @@ -1,7 +1,25 @@ -union_paren.erl:12: Function t2/0 has no local return -union_paren.erl:13: The call union_paren:t2(3.14) breaks the contract (integer() | atom()) -> integer() -union_paren.erl:19: Function t3/0 has no local return -union_paren.erl:20: The pattern 3.14 can never match the type atom() | integer() -union_paren.erl:5: Function t1/0 has no local return -union_paren.erl:6: The call union_paren:t1(3.14) breaks the contract ((A::integer()) | (B::atom())) -> integer() +union_paren.erl:20: Function r1/0 has no local return +union_paren.erl:21: Record construction #r1{f1::[4,...],f2::'undefined',f3::'undefined',f8::float()} violates the declared type of field f2::[atom() | pid() | integer()] and f3::[atom() | pid() | integer()] and f8::[atom() | pid() | integer()] +union_paren.erl:23: Function t1/0 has no local return +union_paren.erl:24: The call union_paren:t1(3.14) breaks the contract ((A::integer()) | (B::atom())) -> integer() +union_paren.erl:30: Function t2/0 has no local return +union_paren.erl:31: The call union_paren:t2(3.14) breaks the contract (integer() | atom()) -> integer() +union_paren.erl:37: Function t3/0 has no local return +union_paren.erl:38: The pattern 3.14 can never match the type atom() | integer() +union_paren.erl:44: Function c1/0 has no local return +union_paren.erl:45: The call union_paren:c1({'r0', 'a', 'undefined', 'undefined'}) breaks the contract (#r0{f1::integer() | pid()}) -> atom() +union_paren.erl:51: Function c2/0 has no local return +union_paren.erl:52: The call union_paren:c2({'r0', 'a', 'undefined', 'undefined'}) breaks the contract (#r0{f1::A::integer() | pid()}) -> atom() +union_paren.erl:58: Function c3/0 has no local return +union_paren.erl:59: The call union_paren:c3({'r0', 'a', 'undefined', 'undefined'}) breaks the contract (#r0{f1::(A::integer()) | (B::pid())}) -> atom() +union_paren.erl:65: Function c4/0 has no local return +union_paren.erl:66: The call union_paren:c4({'r0', 'a', 'undefined', 'undefined'}) breaks the contract (#r0{f1::X::(A::integer()) | (B::pid())}) -> atom() +union_paren.erl:72: Function c5/0 has no local return +union_paren.erl:73: The call union_paren:c5({'r1', ['a'], [1], ['a'], ['u']}) breaks the contract (#r1{f1::[integer()] | [pid()]}) -> atom() +union_paren.erl:79: Function c6/0 has no local return +union_paren.erl:80: The call union_paren:c6({'r1', ['a'], [1], ['a'], ['u']}) breaks the contract (#r1{f1::A::[integer()] | [pid()]}) -> atom() +union_paren.erl:86: Function c7/0 has no local return +union_paren.erl:87: The call union_paren:c7({'r1', ['a'], [1], ['a'], ['u']}) breaks the contract (#r1{f1::(A::[integer()]) | (B::[pid()])}) -> atom() +union_paren.erl:93: Function c8/0 has no local return +union_paren.erl:94: The call union_paren:c8({'r1', ['a'], [1], ['a'], ['u']}) breaks the contract (#r1{f1::X::(A::[integer()]) | (B::[pid()])}) -> atom() diff --git a/lib/dialyzer/test/small_SUITE_data/src/union_paren.erl b/lib/dialyzer/test/small_SUITE_data/src/union_paren.erl index 4691a57d988..65bda1876ea 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/union_paren.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/union_paren.erl @@ -2,6 +2,24 @@ -compile(export_all). +-record(r0, + { + f1 = 4 :: atom () | integer() | pid(), + f2 :: atom() | integer() | pid(), + f3 :: A :: atom() | integer() | pid + }). + +-record(r1, + { + f1 = [4] :: [atom ()] | [integer()] | [pid()], + f2 :: [atom()] | [integer()] | [pid()], + f3 :: A :: [atom()] | [integer()] | [pid()], + f8 = [u] :: X :: [A :: atom()] | [B :: integer()] | (C :: [pid()]) + }). + +r1() -> + #r1{f8 = 3.14}. + t1() -> t1(3.14). @@ -22,3 +40,59 @@ t3() -> -spec t3(_) -> (I :: integer()) | (A :: atom()). t3(A) when is_atom(A) -> A; t3(I) when is_integer(I) -> I. + +c1() -> + c1(#r0{f1 = a}). + +-spec c1(#r0{f1 :: integer() | pid()}) -> atom(). +c1(_) -> + a. + +c2() -> + c2(#r0{f1 = a}). + +-spec c2(#r0{f1 :: A :: integer() | pid()}) -> atom(). +c2(_) -> + a. + +c3() -> + c3(#r0{f1 = a}). + +-spec c3(#r0{f1 :: (A :: integer()) | (B :: pid())}) -> atom(). +c3(_) -> + a. + +c4() -> + c4(#r0{f1 = a}). + +-spec c4(#r0{f1 :: X :: (A :: integer()) | (B :: pid())}) -> atom(). +c4(_) -> + a. + +c5() -> + c5(#r1{f1 = [a], f2 = [1], f3 = [a]}). + +-spec c5(#r1{f1 :: [integer()] | [pid()]}) -> atom(). +c5(_) -> + a. + +c6() -> + c6(#r1{f1 = [a], f2 = [1], f3 = [a]}). + +-spec c6(#r1{f1 :: A :: [integer()] | [pid()]}) -> atom(). +c6(_) -> + a. + +c7() -> + c7(#r1{f1 = [a], f2 = [1], f3 = [a]}). + +-spec c7(#r1{f1 :: (A :: [integer()]) | (B :: [pid()])}) -> atom(). +c7(_) -> + a. + +c8() -> + c8(#r1{f1 = [a], f2 = [1], f3 = [a]}). + +-spec c8(#r1{f1 :: X :: (A :: [integer()]) | (B :: [pid()])}) -> atom(). +c8(_) -> + a. From af2b8efbb054a05a27a20c2d4c769f404d874807 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 4 Jun 2019 15:43:24 +0200 Subject: [PATCH 25/73] Revert "erts: Force process_info(reductions) as signal" This reverts commit 70dbf671a8196110d2aee2e7507afc2c2c75183f. As the comment of 70dbf671a8 itself indicates, that "fix" is not really necessary. It has, however, the bad effect of always consuming reductions of the process you want to know reduction from, that is you can't meassure reduction count without affecting it. --- erts/emulator/beam/erl_bif_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 96f399fbbe9..16c06766fb8 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -761,7 +761,7 @@ static ErtsProcessInfoArgs pi_args[] = { {am_memory, 0, ERTS_PI_FLAG_NEED_MSGQ_LEN|ERTS_PI_FLAG_FORCE_SIG_SEND, ERTS_PROC_LOCK_MAIN}, {am_garbage_collection, 3+2 + 3+2 + 3+2 + 3+2 + 3+2 + ERTS_MAX_HEAP_SIZE_MAP_SZ, 0, ERTS_PROC_LOCK_MAIN}, {am_group_leader, 0, 0, ERTS_PROC_LOCK_MAIN}, - {am_reductions, 0, ERTS_PI_FLAG_FORCE_SIG_SEND, ERTS_PROC_LOCK_MAIN}, + {am_reductions, 0, 0, ERTS_PROC_LOCK_MAIN}, {am_priority, 0, 0, 0}, {am_trace, 0, 0, ERTS_PROC_LOCK_MAIN}, {am_binary, 0, ERTS_PI_FLAG_FORCE_SIG_SEND, ERTS_PROC_LOCK_MAIN}, From 52111283b6f93d89b7e460f1a02e5b13b80707b8 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 27 May 2019 16:32:37 +0200 Subject: [PATCH 26/73] ssl: Returned "alert error string" should be same as logged alert string --- lib/ssl/src/ssl_alert.erl | 31 +++++++++++----- lib/ssl/src/ssl_connection.erl | 66 +++++++++++++++++----------------- lib/ssl/test/ssl_test_lib.erl | 30 ++++++++++++---- 3 files changed, 79 insertions(+), 48 deletions(-) diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl index 06b1b005a57..2d57b72f7be 100644 --- a/lib/ssl/src/ssl_alert.erl +++ b/lib/ssl/src/ssl_alert.erl @@ -32,7 +32,11 @@ -include("ssl_record.hrl"). -include("ssl_internal.hrl"). --export([decode/1, own_alert_txt/1, alert_txt/1, reason_code/2]). +-export([decode/1, + own_alert_txt/1, + alert_txt/1, + alert_txt/4, + reason_code/4]). %%==================================================================== %% Internal application API @@ -48,20 +52,29 @@ decode(Bin) -> decode(Bin, [], 0). %%-------------------------------------------------------------------- -%% -spec reason_code(#alert{}, client | server) -> -%% {tls_alert, unicode:chardata()} | closed. -%-spec reason_code(#alert{}, client | server) -> closed | {essl, string()}. +-spec reason_code(#alert{}, client | server, ProtocolName::string(), StateName::atom()) -> + {tls_alert, {atom(), unicode:chardata()}} | closed. %% %% Description: Returns the error reason that will be returned to the %% user. %%-------------------------------------------------------------------- -reason_code(#alert{description = ?CLOSE_NOTIFY}, _) -> +reason_code(#alert{description = ?CLOSE_NOTIFY}, _, _, _) -> closed; -reason_code(#alert{description = Description, role = Role} = Alert, Role) -> - {tls_alert, {description_atom(Description), own_alert_txt(Alert)}}; -reason_code(#alert{description = Description} = Alert, Role) -> - {tls_alert, {description_atom(Description), alert_txt(Alert#alert{role = Role})}}. +reason_code(#alert{description = Description, role = Role} = Alert, Role, ProtocolName, StateName) -> + Txt = lists:flatten(alert_txt(ProtocolName, Role, StateName, own_alert_txt(Alert))), + {tls_alert, {description_atom(Description), Txt}}; +reason_code(#alert{description = Description} = Alert, Role, ProtocolName, StateName) -> + Txt = lists:flatten(alert_txt(ProtocolName, Role, StateName, alert_txt(Alert))), + {tls_alert, {description_atom(Description), Txt}}. + +%%-------------------------------------------------------------------- +-spec alert_txt(string(), server | client, StateNam::atom(), string()) -> string(). +%% +%% Description: Generates alert text for log or string part of error return. +%%-------------------------------------------------------------------- +alert_txt(ProtocolName, Role, StateName, Txt) -> + io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]). %%-------------------------------------------------------------------- -spec own_alert_txt(#alert{}) -> string(). diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index a5f754d2e31..5befda9cac8 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -328,34 +328,33 @@ prf(ConnectionPid, Secret, Label, Seed, WantedLength) -> %%==================================================================== %% Alert and close handling %%==================================================================== -handle_own_alert(Alert, _, StateName, +handle_own_alert(Alert0, _, StateName, #state{static_env = #static_env{role = Role, protocol_cb = Connection}, ssl_options = SslOpts} = State) -> try %% Try to tell the other side - send_alert(Alert, StateName, State) + send_alert(Alert0, StateName, State) catch _:_ -> %% Can crash if we are in a uninitialized state ignore end, try %% Try to tell the local user - log_alert(SslOpts#ssl_options.log_level, Role, - Connection:protocol_name(), StateName, - Alert#alert{role = Role}), + Alert = Alert0#alert{role = Role}, + log_alert(SslOpts#ssl_options.log_level, Role, Connection:protocol_name(), StateName, Alert), handle_normal_shutdown(Alert,StateName, State) catch _:_ -> ok end, {stop, {shutdown, own_alert}, State}. -handle_normal_shutdown(Alert, _, #state{static_env = #static_env{role = Role, - socket = Socket, - transport_cb = Transport, - protocol_cb = Connection, - tracker = Tracker}, - handshake_env = #handshake_env{renegotiation = {false, first}}, - start_or_recv_from = StartFrom} = State) -> +handle_normal_shutdown(Alert, StateName, #state{static_env = #static_env{role = Role, + socket = Socket, + transport_cb = Transport, + protocol_cb = Connection, + tracker = Tracker}, + handshake_env = #handshake_env{renegotiation = {false, first}}, + start_or_recv_from = StartFrom} = State) -> Pids = Connection:pids(State), - alert_user(Pids, Transport, Tracker,Socket, StartFrom, Alert, Role, Connection); + alert_user(Pids, Transport, Tracker,Socket, StartFrom, Alert, Role, StateName, Connection); handle_normal_shutdown(Alert, StateName, #state{static_env = #static_env{role = Role, socket = Socket, @@ -366,9 +365,9 @@ handle_normal_shutdown(Alert, StateName, #state{static_env = #static_env{role = socket_options = Opts, start_or_recv_from = RecvFrom} = State) -> Pids = Connection:pids(State), - alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, Connection). + alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, StateName, Connection). -handle_alert(#alert{level = ?FATAL} = Alert, StateName, +handle_alert(#alert{level = ?FATAL} = Alert0, StateName, #state{static_env = #static_env{role = Role, socket = Socket, host = Host, @@ -382,11 +381,11 @@ handle_alert(#alert{level = ?FATAL} = Alert, StateName, session = Session, socket_options = Opts} = State) -> invalidate_session(Role, Host, Port, Session), + Alert = Alert0#alert{role = opposite_role(Role)}, log_alert(SslOpts#ssl_options.log_level, Role, Connection:protocol_name(), - StateName, Alert#alert{role = opposite_role(Role)}), + StateName, Alert), Pids = Connection:pids(State), - alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, - opposite_role(Role), Connection), + alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, StateName, Connection), {stop, {shutdown, normal}, State}; handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert, @@ -396,13 +395,14 @@ handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert, StateName, State) -> handle_normal_shutdown(Alert, StateName, State), {stop,{shutdown, peer_close}, State}; -handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName, +handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert0, StateName, #state{static_env = #static_env{role = Role, protocol_cb = Connection}, handshake_env = #handshake_env{renegotiation = {true, internal}}, ssl_options = SslOpts} = State) -> + Alert = Alert0#alert{role = opposite_role(Role)}, log_alert(SslOpts#ssl_options.log_level, Role, - Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), + Connection:protocol_name(), StateName, Alert), handle_normal_shutdown(Alert, StateName, State), {stop,{shutdown, peer_close}, State}; @@ -1445,7 +1445,7 @@ handle_info({ErrorTag, Socket, econnaborted}, StateName, } = State) when StateName =/= connection -> Pids = Connection:pids(State), alert_user(Pids, Transport, Tracker,Socket, - StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, Connection), + StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, StateName, Connection), {stop, {shutdown, normal}, State}; handle_info({ErrorTag, Socket, Reason}, StateName, #state{static_env = #static_env{socket = Socket, @@ -2907,22 +2907,22 @@ send_user(Pid, Msg) -> Pid ! Msg, ok. -alert_user(Pids, Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, Connection) -> - alert_user(Pids, Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, Connection); -alert_user(Pids, Transport, Tracker, Socket,_, _, _, From, Alert, Role, Connection) -> - alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, Connection). +alert_user(Pids, Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, StateName, Connection) -> + alert_user(Pids, Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, StateName, Connection); +alert_user(Pids, Transport, Tracker, Socket,_, _, _, From, Alert, Role, StateName, Connection) -> + alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, StateName, Connection). -alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, Connection) -> - alert_user(Pids, Transport, Tracker, Socket, false, no_pid, From, Alert, Role, Connection). +alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, StateName, Connection) -> + alert_user(Pids, Transport, Tracker, Socket, false, no_pid, From, Alert, Role, StateName, Connection). -alert_user(_, _, _, _, false = Active, Pid, From, Alert, Role, _) when From =/= undefined -> +alert_user(_, _, _, _, false = Active, Pid, From, Alert, Role, StateName, Connection) when From =/= undefined -> %% If there is an outstanding ssl_accept | recv %% From will be defined and send_or_reply will %% send the appropriate error message. - ReasonCode = ssl_alert:reason_code(Alert, Role), + ReasonCode = ssl_alert:reason_code(Alert, Role, Connection:protocol_name(), StateName), send_or_reply(Active, Pid, From, {error, ReasonCode}); -alert_user(Pids, Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connection) -> - case ssl_alert:reason_code(Alert, Role) of +alert_user(Pids, Transport, Tracker, Socket, Active, Pid, From, Alert, Role, StateName, Connection) -> + case ssl_alert:reason_code(Alert, Role, Connection:protocol_name(), StateName) of closed -> send_or_reply(Active, Pid, From, {ssl_closed, Connection:socket(Pids, Transport, Socket, Tracker)}); @@ -2933,11 +2933,11 @@ alert_user(Pids, Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Con log_alert(Level, Role, ProtocolName, StateName, #alert{role = Role} = Alert) -> Txt = ssl_alert:own_alert_txt(Alert), - Report = io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]), + Report = ssl_alert:alert_txt(ProtocolName, Role, StateName, Txt), ssl_logger:notice(Level, Report); log_alert(Level, Role, ProtocolName, StateName, Alert) -> Txt = ssl_alert:alert_txt(Alert), - Report = io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]), + Report = ssl_alert:alert_txt(ProtocolName, Role, StateName, Txt), ssl_logger:notice(Level, Report). invalidate_session(client, Host, Port, Session) -> diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 3b161a0c8a8..733ee993a84 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -429,14 +429,17 @@ check_result(Pid, Msg) -> end. check_server_alert(Pid, Alert) -> receive - {Pid, {error, {tls_alert, {Alert, _}}}} -> + {Pid, {error, {tls_alert, {Alert, STxt}}}} -> + check_server_txt(STxt), ok end. check_server_alert(Server, Client, Alert) -> receive - {Server, {error, {tls_alert, {Alert, _}}}} -> + {Server, {error, {tls_alert, {Alert, STxt}}}} -> + check_server_txt(STxt), receive - {Client, {error, {tls_alert, {Alert, _}}}} -> + {Client, {error, {tls_alert, {Alert, CTxt}}}} -> + check_client_txt(CTxt), ok; {Client, {error, closed}} -> ok @@ -444,20 +447,35 @@ check_server_alert(Server, Client, Alert) -> end. check_client_alert(Pid, Alert) -> receive - {Pid, {error, {tls_alert, {Alert, _}}}} -> + {Pid, {error, {tls_alert, {Alert, CTxt}}}} -> + check_client_txt(CTxt), ok end. check_client_alert(Server, Client, Alert) -> receive - {Client, {error, {tls_alert, {Alert, _}}}} -> + {Client, {error, {tls_alert, {Alert, CTxt}}}} -> + check_client_txt(CTxt), receive - {Server, {error, {tls_alert, {Alert, _}}}} -> + {Server, {error, {tls_alert, {Alert, STxt}}}} -> + check_server_txt(STxt), ok; {Server, {error, closed}} -> ok end end. +check_server_txt("TLS server" ++ _) -> + ok; +check_server_txt("DTLS server" ++ _) -> + ok; +check_server_txt(Txt) -> + ct:fail({expected_server, {got, Txt}}). +check_client_txt("TLS client" ++ _) -> + ok; +check_client_txt("DTLS client" ++ _) -> + ok; +check_client_txt(Txt) -> + ct:fail({expected_server, {got, Txt}}). wait_for_result(Server, ServerMsg, Client, ClientMsg) -> receive From 8f25256ae1678fa3cb814b3d28fdfece1008254e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 4 Jun 2019 17:56:51 +0200 Subject: [PATCH 27/73] erts: Fix SEGV crash on shell break (p)roc info esdp==NULL if run by non scheduler thread. --- erts/emulator/beam/break.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index 80e871aaf6b..6379e4e04d8 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -84,8 +84,9 @@ process_info(fmtfn_t to, void *to_arg) * they are most likely just created and has invalid data */ if (p->heap != NULL) { - ErtsProcLocks locks = (p == esdp->current_process || - p == esdp->free_process) ? ERTS_PROC_LOCK_MAIN : 0; + ErtsProcLocks locks = ((esdp && (p == esdp->current_process || + p == esdp->free_process)) + ? ERTS_PROC_LOCK_MAIN : 0); print_process_info(to, to_arg, p, locks); } } From 9fdfaa533a131aa1b6b73accf739bdf23be84fb6 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 29 May 2019 22:53:01 +0200 Subject: [PATCH 28/73] ssl: Fix broken return value --- lib/ssl/src/ssl_connection.erl | 8 +++++++- lib/ssl/test/ssl_test_lib.erl | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index a5f754d2e31..6deb355b8eb 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -124,7 +124,7 @@ handshake(#sslsocket{pid = [Pid|_]} = Socket, Timeout) -> connected -> {ok, Socket}; {ok, Ext} -> - {ok, Socket, Ext}; + {ok, Socket, no_records(Ext)}; Error -> Error end. @@ -709,6 +709,7 @@ handle_session(#server_hello{cipher_suite = CipherSuite, {ExpectNPN, Protocol} = case Protocol0 of undefined -> + {false, CurrentProtocol}; _ -> {ProtoExt =:= npn, Protocol0} @@ -3000,3 +3001,8 @@ new_emulated([], EmOpts) -> EmOpts; new_emulated(NewEmOpts, _) -> NewEmOpts. + +no_records(Extensions) -> + maps:map(fun(_, Value) -> + ssl_handshake:extension_value(Value) + end, Extensions). diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 3b161a0c8a8..070093190cd 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -159,6 +159,7 @@ connect(ListenSocket, Node, N, _, Timeout, SslOpts, [_|_] =ContOpts) -> case ssl:handshake(AcceptSocket, SslOpts, Timeout) of {ok, Socket0, Ext} -> + [_|_] = maps:get(sni, Ext), ct:log("Ext ~p:~n", [Ext]), ct:log("~p:~p~nssl:handshake_continue(~p,~p,~p)~n", [?MODULE,?LINE, Socket0, ContOpts,Timeout]), case ssl:handshake_continue(Socket0, ContOpts, Timeout) of From 6692b1e347a6d843f11fe8117af1c1534a505085 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 4 Jun 2019 15:42:32 +0200 Subject: [PATCH 29/73] ssl: Add missing gen_server return value in DTLS packet demux process --- lib/ssl/src/dtls_packet_demux.erl | 6 ++-- lib/ssl/test/ssl_basic_SUITE.erl | 46 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/lib/ssl/src/dtls_packet_demux.erl b/lib/ssl/src/dtls_packet_demux.erl index c6431b55a92..94b350eaa59 100644 --- a/lib/ssl/src/dtls_packet_demux.erl +++ b/lib/ssl/src/dtls_packet_demux.erl @@ -154,9 +154,9 @@ handle_info({Transport, Socket, IP, InPortNo, _} = Msg, #state{listener = Socket handle_info({PassiveTag, Socket}, #state{active_n = N, listener = Socket, - transport = {_,_,_, udp_error, PassiveTag}}) -> - next_datagram(Socket, N); - + transport = {_, _, _, _, PassiveTag}} = State) -> + next_datagram(Socket, N), + {noreply, State}; %% UDP socket does not have a connection and should not receive an econnreset %% This does however happens on some windows versions. Just ignoring it %% appears to make things work as expected! diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 20d9f285121..785ea98fa05 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -164,6 +164,7 @@ api_tests() -> prf, socket_options, active_n, + internal_active_1, cipher_suites, handshake_continue, handshake_continue_timeout, @@ -488,6 +489,15 @@ init_per_testcase(accept_pool, Config) -> ssl_test_lib:ct_log_supported_protocol_versions(Config), Config end; + +init_per_testcase(internal_active_1, Config) -> + ssl:stop(), + application:load(ssl), + application:set_env(ssl, internal_active_n, 1), + ssl:start(), + ct:timetrap({seconds, 5}), + Config; + init_per_testcase(controller_dies, Config) -> ct:timetrap({seconds, 10}), Config; @@ -510,6 +520,10 @@ end_per_testcase(reuse_session_expired, Config) -> application:unset_env(ssl, session_delay_cleanup_time), end_per_testcase(default_action, Config); +end_per_testcase(internal_active_n, Config) -> + application:unset_env(ssl, internal_active_n), + end_per_testcase(default_action, Config); + end_per_testcase(Case, Config) when Case == protocol_versions; Case == empty_protocol_versions-> application:unset_env(ssl, protocol_versions), @@ -1975,6 +1989,10 @@ recv_active_once(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + + + + %%-------------------------------------------------------------------- recv_active_n() -> [{doc,"Test recv on active (n) socket"}]. @@ -2001,6 +2019,7 @@ recv_active_n(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + %%-------------------------------------------------------------------- %% Test case adapted from gen_tcp_misc_SUITE. active_n() -> @@ -2226,6 +2245,33 @@ upgrade_result(Socket) -> ok end. + +%%-------------------------------------------------------------------- +internal_active_1() -> + [{doc,"Test internal active 1 (behave as internal active once)"}]. + +internal_active_1(Config) when is_list(Config) -> + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, [{active, true} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, [{active, true} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + %%-------------------------------------------------------------------- tls_upgrade_with_timeout() -> [{doc,"Test ssl_accept/3"}]. From a726c015867beffe15cc20ee22e32778678e8fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Mon, 10 Jun 2019 17:21:52 +0200 Subject: [PATCH 30/73] beam_ssa_type: Fix incorrect bitstring unit determination The compiler would treat the "Unit" of bs_init instructions as the unit of the result instead of the required unit of the input, causing is_binary checks to be wrongly optimized away. --- lib/compiler/src/beam_ssa_type.erl | 11 ++--------- lib/compiler/test/beam_type_SUITE.erl | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 57fd7fec608..68920e7dd31 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -840,15 +840,8 @@ type({bif,Bif}, Args, Ts, _Ds) -> Type -> Type end; -type(bs_init, [#b_literal{val=Type}|Args], _Ts, _Ds) -> - case {Type,Args} of - {new,[_,#b_literal{val=Unit}]} -> - {binary,Unit}; - {append,[_,_,#b_literal{val=Unit}]} -> - {binary,Unit}; - {private_append,[_,_,#b_literal{val=Unit}]} -> - {binary,Unit} - end; +type(bs_init, _Args, _Ts, _Ds) -> + {binary, 1}; type(bs_extract, [Ctx], Ts, _Ds) -> #t_bs_match{type=Type} = get_type(Ctx, Ts), Type; diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 2297c2e0f59..076a604aa47 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -24,7 +24,7 @@ integers/1,numbers/1,coverage/1,booleans/1,setelement/1, cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1, arity_checks/1,elixir_binaries/1,find_best/1, - test_size/1,cover_lists_functions/1,list_append/1]). + test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -48,7 +48,8 @@ groups() -> find_best, test_size, cover_lists_functions, - list_append + list_append, + bad_binary_unit ]}]. init_per_suite(Config) -> @@ -508,5 +509,14 @@ list_append(_Config) -> hello = id([]) ++ id(hello), ok. +%% OTP-15872: The compiler would treat the "Unit" of bs_init instructions as +%% the unit of the result instead of the required unit of the input, causing +%% is_binary checks to be wrongly optimized away. +bad_binary_unit(_Config) -> + Bin = id(<<1,2,3>>), + Bitstring = <>, + false = is_binary(Bitstring), + ok. + id(I) -> I. From 5ee02a07b5c31aea4dd464060fa626d6e6ab8ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Mon, 10 Jun 2019 16:38:22 +0200 Subject: [PATCH 31/73] erts: Fix bad loader optimization of get_tuple_element The following sequence would be wrongly optimized into a i_get_tuple_element2 instruction, reading an element from the wrong tuple: {get_tuple_element,{x,0},1,{x,0}}. {get_tuple_element,{x,0},2,{x,1}}. --- erts/emulator/beam/ops.tab | 19 ++++++++++++------- lib/compiler/test/match_SUITE.erl | 26 +++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index 10ca74cd60f..e9107933f99 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2018. All Rights Reserved. +# Copyright Ericsson AB 1997-2019. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -699,13 +699,18 @@ is_tuple NotTupleFail Tuple=x | is_tagged_tuple WrongRecordFail Tuple Arity Atom is_tagged_tuple_ff f? f? rx A a -get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \ +get_tuple_element Reg=x P1 D1=x | \ + get_tuple_element Reg=x P2 D2=x | \ get_tuple_element Reg=x P3 D3=x | \ - succ(P1, P2) | succ(P2, P3) | \ - succ(D1, D2) | succ(D2, D3) => i_get_tuple_element3 Reg P1 D1 - -get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \ - succ(P1, P2) | succ(D1, D2) => i_get_tuple_element2 Reg P1 D1 + succ(P1, P2) | succ(P2, P3) | succ(D1, D2) | succ(D2, D3) | \ + distinct(D1, Reg) | distinct(D2, Reg) | distinct(D3, Reg) => \ + i_get_tuple_element3 Reg P1 D1 + +get_tuple_element Reg=x P1 D1=x | \ + get_tuple_element Reg=x P2 D2=x | \ + succ(P1, P2) | succ(D1, D2) | \ + distinct(D1, Reg) => \ + i_get_tuple_element2 Reg P1 D1 get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \ succ(P1, P2) | distinct(D1, Reg) => i_get_tuple_element2_dst Reg P1 D1 D2 diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index 94bfbb0efe4..aac9de278d2 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2018. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1, selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1, coverage/1,grab_bag/1,literal_binary/1, - unary_op/1,eq_types/1,match_after_return/1]). + unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1]). -include_lib("common_test/include/ct.hrl"). @@ -41,7 +41,7 @@ groups() -> shortcut_boolean,letify_guard,selectify,deselectify, underscore,match_map,map_vars_used,coverage, grab_bag,literal_binary,unary_op,eq_types, - match_after_return]}]. + match_after_return,match_right_tuple]}]. init_per_suite(Config) -> @@ -902,4 +902,24 @@ match_after_return(Config) when is_list(Config) -> mar_test_tuple(I) -> {gurka, I}. +match_right_tuple(Config) when is_list(Config) -> + %% The loader wrongly coalesced certain get_tuple_element sequences, fusing + %% the code below into a single i_get_tuple_element2 operating on {x,0} + %% even though the first one overwrites it. + %% + %% {get_tuple_element,{x,0},0,{x,0}}. + %% {get_tuple_element,{x,0},1,{x,1}}. + + Inner = {id(wrong_element), id(ok)}, + Outer = {Inner, id(wrong_tuple)}, + ok = match_right_tuple_1(Outer). + +match_right_tuple_1(T) -> + {A, _} = T, + {_, B} = A, + %% The call ensures that A is in {x,0} and B is in {x,1} + id(force_succ_regs(A, B)). + +force_succ_regs(_A, B) -> B. + id(I) -> I. From 9807d727adf8895e16fa1463bcdf7a38a0d1878f Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 5 Jun 2019 16:18:39 +0200 Subject: [PATCH 32/73] erts: Improve test of process_info(reductions) to provoke case when the main lock is released during execution. --- erts/emulator/test/process_SUITE.erl | 84 +++++++++++++++++++++------- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 0cb0d6c1e24..cef1b79035d 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -1089,42 +1089,86 @@ process_info_status_handled_signal(Config) when is_list(Config) -> %% OTP-15709 %% Provoke a bug where process_info(reductions) returned wrong result %% because REDS_IN (def_arg_reg[5]) is read when the process in not running. +%% +%% And a bug where process_info(reductions) on a process which was releasing its +%% main lock during execution could result in negative reduction diffs. process_info_reductions(Config) when is_list(Config) -> - pi_reductions_tester(spawn_link(fun() -> pi_reductions_spinnloop() end)), - pi_reductions_tester(spawn_link(fun() -> pi_reductions_recvloop() end)), + {S1, S2} = case erlang:system_info(schedulers) of + 1 -> {1,1}; + _ -> {1,2} + end, + io:format("Run on schedulers ~p and ~p\n", [S1,S2]), + Boss = self(), + Doer = spawn_opt(fun () -> + pi_reductions_tester(true, 10, fun pi_reductions_spinnloop/0, S2), + pi_reductions_tester(true, 10, fun pi_reductions_recvloop/0, S2), + pi_reductions_tester(false, 100, fun pi_reductions_main_unlocker/0, S2), + Boss ! {self(), done} + end, + [link, {scheduler, S1}]), + + {Doer, done} = receive M -> M end, ok. -pi_reductions_tester(Pid) -> - {_, DiffList} = - lists:foldl(fun(_, {Prev, Acc}) -> - %% Add another item that force sending the request - %% as a signal, like 'current_function'. - PI = process_info(Pid, [reductions, current_function]), - [{reductions,Reds}, {current_function,_}] = PI, - Diff = Reds - Prev, - {Diff, true} = {Diff, (Diff >= 0)}, - {Diff, true} = {Diff, (Diff =< 1000*1000)}, - {Reds, [Diff | Acc]} - end, - {0, []}, - lists:seq(1,10)), +pi_reductions_tester(ForceSignal, MaxCalls, Fun, S2) -> + Pid = spawn_opt(Fun, [link, {scheduler,S2}]), + Extra = case ForceSignal of + true -> + %% Add another item that force sending the request + %% as a signal, like 'current_function'. + [current_function]; + false -> + [] + end, + LoopFun = fun Me(Calls, Prev, Acc0) -> + PI = process_info(Pid, [reductions | Extra]), + [{reductions,Reds} | _] = PI, + Diff = Reds - Prev, + %% Verify we get sane non-negative reduction diffs + {Diff, true} = {Diff, (Diff >= 0)}, + {Diff, true} = {Diff, (Diff =< 1000*1000)}, + Acc1 = [Diff | Acc0], + case Calls >= MaxCalls of + true -> Acc1; + false -> Me(Calls+1, Reds, Acc1) + end + end, + DiffList = LoopFun(0, 0, []), unlink(Pid), exit(Pid,kill), - io:format("Reduction diffs: ~p\n", [DiffList]), + io:format("Reduction diffs: ~p\n", [lists:reverse(DiffList)]), ok. pi_reductions_spinnloop() -> %% 6 args to make use of def_arg_reg[5] which is also used as REDS_IN - pi_reductions_spinnloop(1, atom, "hej", self(), make_ref(), 3.14). + pi_reductions_spinnloop(999*1000, atom, "hej", self(), make_ref(), 3.14). -pi_reductions_spinnloop(A,B,C,D,E,F) -> - pi_reductions_spinnloop(B,C,D,E,F,A). +pi_reductions_spinnloop(N,A,B,C,D,E) when N > 0 -> + pi_reductions_spinnloop(N-1,B,C,D,E,A); +pi_reductions_spinnloop(0,_,_,_,_,_) -> + %% Stop to limit max number of reductions consumed + pi_reductions_recvloop(). pi_reductions_recvloop() -> receive "a free lunch" -> false end. +pi_reductions_main_unlocker() -> + Other = spawn_link(fun() -> receive die -> ok end end), + pi_reductions_main_unlocker_loop(Other). + +pi_reductions_main_unlocker_loop(Other) -> + %% Assumption: register(OtherPid, Name) will unlock main lock of calling + %% process during execution. + register(pi_reductions_main_unlocker, Other), + unregister(pi_reductions_main_unlocker), + + %% Yield in order to increase probability of process_info sometimes probing + %% this process when it's not RUNNING. + erlang:yield(), + pi_reductions_main_unlocker_loop(Other). + %% Tests erlang:bump_reductions/1. bump_reductions(Config) when is_list(Config) -> From acc3b04fb0128fca1770a3823b6651f632d73939 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 11 Jun 2019 08:58:35 +0200 Subject: [PATCH 33/73] stdlib: Fix a bug concerning io_lib option 'chars_limit' See also https://bugs.erlang.org/browse/ERL-967. --- lib/stdlib/src/io_lib_pretty.erl | 4 +++- lib/stdlib/test/io_SUITE.erl | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl index 8f2fd7ea8f3..19e41408939 100644 --- a/lib/stdlib/src/io_lib_pretty.erl +++ b/lib/stdlib/src/io_lib_pretty.erl @@ -462,7 +462,9 @@ find_upper(Lower, Term, T, Dl, Dd, D, RF, Enc, Str) -> case If of {_, _, _Dots=0, _} -> % even if Len > T If; - {_, Len, _, _} when Len =< T, D1 < D orelse D < 0 -> + {_, _Len=T, _, _} -> % increasing the depth is meaningless + If; + {_, Len, _, _} when Len < T, D1 < D orelse D < 0 -> find_upper(If, Term, T, D1, Dd2, D, RF, Enc, Str); _ -> search_depth(Lower, If, Term, T, Dl, D1, RF, Enc, Str) diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 824f5d19f2f..29c09da2e0f 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -32,7 +32,7 @@ io_with_huge_message_queue/1, format_string/1, maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1, otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1, - otp_15159/1, otp_15639/1]). + otp_15159/1, otp_15639/1, otp_15875/1]). -export([pretty/2, trf/3]). @@ -65,7 +65,7 @@ all() -> io_lib_width_too_small, io_with_huge_message_queue, format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175, otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159, - otp_15639]. + otp_15639, otp_15875]. %% Error cases for output. error_1(Config) when is_list(Config) -> @@ -2680,3 +2680,7 @@ otp_15639(_Config) -> "\"12345678\"..." = pretty("123456789"++[x], UOpts), "[[...]|...]" = pretty(["1","2","3","4","5","6","7","8"], UOpts), ok. + +otp_15875(_Config) -> + S = io_lib:format("~tp", [[{0, [<<"00">>]}]], [{chars_limit, 18}]), + "[{0,[<<48,...>>]}]" = lists:flatten(S). From be14a5043ab343a30b881d4697fd4bcd3abdb7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Tue, 11 Jun 2019 15:23:45 +0200 Subject: [PATCH 34/73] ssl: Fix ssl_packet_SUITE Unset internal_active_n when cleaning FT environment. --- lib/ssl/test/ssl_test_lib.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 3b161a0c8a8..6e158431562 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -2149,7 +2149,8 @@ clean_env() -> application:unset_env(ssl, session_cache_server_max), application:unset_env(ssl, ssl_pem_cache_clean), application:unset_env(ssl, bypass_pem_cache), - application:unset_env(ssl, alert_timeout). + application:unset_env(ssl, alert_timeout), + application:unset_env(ssl, internal_active_n). clean_start() -> ssl:stop(), From d1bd26b07f6597d46a1cb2a6f0a4af7b87b0fb4f Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 12 Jun 2019 09:51:26 +0200 Subject: [PATCH 35/73] Prepare release --- erts/doc/src/notes.xml | 33 +++++++++++++++++++++++++++++++++ erts/vsn.mk | 2 +- lib/compiler/doc/src/notes.xml | 16 ++++++++++++++++ lib/compiler/vsn.mk | 2 +- lib/dialyzer/doc/src/notes.xml | 16 ++++++++++++++++ lib/dialyzer/vsn.mk | 2 +- lib/ssl/doc/src/notes.xml | 30 ++++++++++++++++++++++++++++++ lib/ssl/vsn.mk | 2 +- lib/stdlib/doc/src/notes.xml | 17 +++++++++++++++++ lib/stdlib/src/stdlib.appup.src | 6 ++++-- lib/stdlib/vsn.mk | 2 +- make/otp_version_tickets | 20 +++++++++----------- 12 files changed, 130 insertions(+), 18 deletions(-) diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index ddf17097bdc..075972c9792 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,39 @@

This document describes the changes made to the ERTS application.

+
Erts 10.4.2 + +
Fixed Bugs and Malfunctions + + +

+ Fixed process_info(Pid,reductions) to not + categorically increase reduction count of the measured + process Pid. Repeated reduction measure of an idle + process will most often (but not guaranteed) return the + same value, like it behaved before OTP 21.3.8.

+

+ Own Id: OTP-15865 Aux Id: ERL-964

+
+ +

Fixed an incorrect load-time optimization that could + cause a crash when extracting deeply nested tuple + elements.

+

+ Own Id: OTP-15871 Aux Id: ERIERL-374

+
+ +

+ Fix bug causing VM crash when pressing P for "proc info" + in Erlang shell break menu. Bug exists since OTP 22.0.

+

+ Own Id: OTP-15873 Aux Id: ERL-965

+
+
+
+ +
+
Erts 10.4.1
Fixed Bugs and Malfunctions diff --git a/erts/vsn.mk b/erts/vsn.mk index 4d8282bf153..53dce5e8157 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 10.4.1 +VSN = 10.4.2 # 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 3090a99c35e..f0d869381be 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,22 @@

This document describes the changes made to the Compiler application.

+
Compiler 7.4.2 + +
Fixed Bugs and Malfunctions + + +

Fixed an incorrect type determination for constructed + binaries, which could cause is_binary checks to + succeed when they shouldn't have.

+

+ Own Id: OTP-15872

+
+
+
+ +
+
Compiler 7.4.1
Fixed Bugs and Malfunctions diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 090579e7eed..508bbc902c0 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.4.1 +COMPILER_VSN = 7.4.2 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index dd0a2bfd7d0..0930f79840b 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,22 @@

This document describes the changes made to the Dialyzer application.

+
Dialyzer 4.0.1 + +
Fixed Bugs and Malfunctions + + +

Fix a bug that caused a crash when indenting a + Dialyzer warning mentioning more than one record field. +

+

+ Own Id: OTP-15861 Aux Id: ERL-953

+
+
+
+ +
+
Dialyzer 4.0
Fixed Bugs and Malfunctions diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 95984c7c85c..466bbfd0f23 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 4.0 +DIALYZER_VSN = 4.0.1 diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index b86c9e87981..5c213402f49 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,36 @@

This document describes the changes made to the SSL application.

+
SSL 9.3.2 + +
Fixed Bugs and Malfunctions + + +

+ Returned "alert error string" is now same as logged alert + string

+

+ Own Id: OTP-15844

+
+ +

+ Fix returned extension map fields to follow the + documentation.

+

+ Own Id: OTP-15862 Aux Id: ERL-951

+
+ +

+ Avoid DTLS crash due to missing gen_server return value + in DTLS packet demux process.

+

+ Own Id: OTP-15864 Aux Id: ERL-962

+
+
+
+ +
+
SSL 9.3.1
Fixed Bugs and Malfunctions diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index cbc32cd5a88..4e387fa403e 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.3.1 +SSL_VSN = 9.3.2 diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 385f092069e..092056ffdee 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,23 @@

This document describes the changes made to the STDLIB application.

+
STDLIB 3.9.2 + +
Fixed Bugs and Malfunctions + + +

Fix a bug that could cause a loop when formatting + terms using the control sequences p or P + and limiting the output with the option + chars_limit.

+

+ Own Id: OTP-15875 Aux Id: ERL-967

+
+
+
+ +
+
STDLIB 3.9.1
Fixed Bugs and Malfunctions diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 4990c81dfee..0c270e9dd51 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -40,7 +40,8 @@ {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.9$">>,[restart_new_emulator]}, - {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], + {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, + {<<"^3\\.9\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], [{<<"^3\\.5$">>,[restart_new_emulator]}, {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, @@ -54,4 +55,5 @@ {<<"^3\\.8\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.8\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.9$">>,[restart_new_emulator]}, - {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}. + {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, + {<<"^3\\.9\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index cc0ab6684ca..c2f586fef5f 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 3.9.1 +STDLIB_VSN = 3.9.2 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index a9ca1cb1312..e071f1a4307 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1,11 +1,9 @@ -OTP-15828 -OTP-15829 -OTP-15832 -OTP-15834 -OTP-15838 -OTP-15839 -OTP-15841 -OTP-15845 -OTP-15846 -OTP-15847 -OTP-15848 +OTP-15844 +OTP-15861 +OTP-15862 +OTP-15864 +OTP-15865 +OTP-15871 +OTP-15872 +OTP-15873 +OTP-15875 From b4fb2e5669acb02697d9a9ab168eb0fbff6f370c Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 12 Jun 2019 09:51:28 +0200 Subject: [PATCH 36/73] Updated OTP version --- OTP_VERSION | 2 +- otp_versions.table | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OTP_VERSION b/OTP_VERSION index 95f8a283f00..8b740661820 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0.2 +22.0.3 diff --git a/otp_versions.table b/otp_versions.table index ad128ba98b8..8e3d127e4ed 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.0.3 : compiler-7.4.2 dialyzer-4.0.1 erts-10.4.2 ssl-9.3.2 stdlib-3.9.2 # asn1-5.0.9 common_test-1.17.3 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.2 : compiler-7.4.1 crypto-4.5.1 erts-10.4.1 stdlib-3.9.1 # asn1-5.0.9 common_test-1.17.3 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3.1 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.1 : ssl-9.3.1 # asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0 : asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3 stdlib-3.9 syntax_tools-2.2 tools-3.2 wx-1.8.8 xmerl-1.3.21 # diameter-2.2.1 et-1.6.4 eunit-2.3.7 ftp-1.0.2 parsetools-2.1.8 tftp-1.0.1 : From faaf5bb3085d351715672684c6f6f9601ad1208a Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 12 Jun 2019 17:48:01 +0200 Subject: [PATCH 37/73] ssl: Correct handshake handling Solves ERL-968, a refactoring bug could cause part of a server key exchange message to be appended, to an incorrectly duplicated, certificate handshake message. In the end causing an ASN1 decoding error. That in turn did not end up the correct error handling branch. --- lib/ssl/src/ssl_handshake.erl | 2 +- lib/ssl/src/tls_connection.erl | 3 +- lib/ssl/test/ssl_certificate_verify_SUITE.erl | 41 ++++++++++++++++++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 29db1b07c4d..24d517fb5fe 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -357,7 +357,7 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef, CertDbHandle, CertDbRef) end catch - error:{badmatch,{asn1, Asn1Reason}} -> + error:{badmatch,{error, {asn1, Asn1Reason}}} -> %% ASN-1 decode of certificate somehow failed ?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN, {failed_to_decode_certificate, Asn1Reason}); error:OtherReason -> diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 52e5db731a8..fe9537157b5 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -272,8 +272,7 @@ handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data}, _ -> HsEnv = State#state.handshake_env, {next_state, StateName, - State#state{protocol_buffers = Buffers, - handshake_env = + State#state{handshake_env = HsEnv#handshake_env{unprocessed_handshake_events = unprocessed_events(Events)}}, Events} end diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl index e89104a999f..653a8d58bd2 100644 --- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl +++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl @@ -89,7 +89,8 @@ tests() -> critical_extension_verify_server, critical_extension_verify_none, customize_hostname_check, - incomplete_chain + incomplete_chain, + long_chain ]. error_handling_tests()-> @@ -1156,6 +1157,44 @@ incomplete_chain(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). +long_chain() -> + [{doc,"Test option verify_peer"}]. +long_chain(Config) when is_list(Config) -> + #{server_config := ServerConf, + client_config := ClientConf} = public_key:pkix_test_data(#{server_chain => #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}], + [{key, ssl_test_lib:hardcode_rsa_key(3)}], + [{key, ssl_test_lib:hardcode_rsa_key(4)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(5)}]}, + client_chain => #{root => [{key, ssl_test_lib:hardcode_rsa_key(3)}], + intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]], + peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]}}), + [ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerConf), + ClientCas = proplists:get_value(cacerts, ClientConf), + + Active = proplists:get_value(active, Config), + ReceiveFunction = proplists:get_value(receive_function, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active}, {verify, verify_peer}, + {cacerts, [ServerRoot]} | + proplists:delete(cacerts, ServerConf)]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active}, + {verify, verify_peer}, + {depth, 5}, + {cacerts, ServerCas ++ ClientCas} | + proplists:delete(cacerts, ClientConf)]}]), + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ From dca65c70badd3b33903a0535ef2366eecc3e12dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Fri, 14 Jun 2019 15:53:47 +0200 Subject: [PATCH 38/73] ssl: Improve handling of signature algorithms TLS 1.2 ClientHello caused handshake failure in the TLS 1.2 server if the signature_algorithms_cert extension contained legacy algorithms. Update TLS 1.2 server to properly handle legacy signature algorithms in the signature_algorithms_cert extension. Update TLS 1.3 client so that it can send legacy algorithms in its signature_algorithms_cert extension. --- lib/ssl/src/ssl_cipher.erl | 10 +++++++++- lib/ssl/src/ssl_handshake.erl | 5 +---- lib/ssl/src/tls_v1.erl | 22 ++++++++++++++++++++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index 21db887bb50..4da50d2af8c 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -923,6 +923,12 @@ signature_scheme(rsa_pss_pss_sha384) -> ?RSA_PSS_PSS_SHA384; signature_scheme(rsa_pss_pss_sha512) -> ?RSA_PSS_PSS_SHA512; signature_scheme(rsa_pkcs1_sha1) -> ?RSA_PKCS1_SHA1; signature_scheme(ecdsa_sha1) -> ?ECDSA_SHA1; +%% Handling legacy signature algorithms +signature_scheme({Hash0, Sign0}) -> + Hash = hash_algorithm(Hash0), + Sign = sign_algorithm(Sign0), + <> = <>, + SigAlg; signature_scheme(?RSA_PKCS1_SHA256) -> rsa_pkcs1_sha256; signature_scheme(?RSA_PKCS1_SHA384) -> rsa_pkcs1_sha384; signature_scheme(?RSA_PKCS1_SHA512) -> rsa_pkcs1_sha512; @@ -962,7 +968,9 @@ scheme_to_components(rsa_pss_pss_sha256) -> {sha256, rsa_pss_pss, undefined}; scheme_to_components(rsa_pss_pss_sha384) -> {sha384, rsa_pss_pss, undefined}; scheme_to_components(rsa_pss_pss_sha512) -> {sha512, rsa_pss_pss, undefined}; scheme_to_components(rsa_pkcs1_sha1) -> {sha1, rsa_pkcs1, undefined}; -scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined}. +scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined}; +%% Handling legacy signature algorithms +scheme_to_components({Hash,Sign}) -> {Hash, Sign, undefined}. %% TODO: Add support for EC and RSA-SSA signatures diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index f68d3e9b261..3d2abb714fb 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1186,10 +1186,7 @@ signature_algs_ext(undefined) -> signature_algs_ext(SignatureSchemes0) -> %% The SSL option signature_algs contains both hash-sign algorithms (tuples) and %% signature schemes (atoms) if TLS 1.3 is configured. - %% Filter out all hash-sign tuples when creating the signature_algs extension. - %% (TLS 1.3 specific record type) - SignatureSchemes = lists:filter(fun is_atom/1, SignatureSchemes0), - #signature_algorithms{signature_scheme_list = SignatureSchemes}. + #signature_algorithms{signature_scheme_list = SignatureSchemes0}. signature_algs_cert(undefined) -> undefined; diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl index 27cd5765e5d..f7c8c770aee 100644 --- a/lib/ssl/src/tls_v1.erl +++ b/lib/ssl/src/tls_v1.erl @@ -606,8 +606,26 @@ signature_schemes(Version, SignatureSchemes) when is_tuple(Version) Acc end; %% Special clause for filtering out the legacy hash-sign tuples. - (_ , Acc) -> - Acc + ({Hash, dsa = Sign} = Alg, Acc) -> + case proplists:get_bool(dss, PubKeys) + andalso proplists:get_bool(Hash, Hashes) + andalso is_pair(Hash, Sign, Hashes) + of + true -> + [Alg | Acc]; + false -> + Acc + end; + ({Hash, Sign} = Alg, Acc) -> + case proplists:get_bool(Sign, PubKeys) + andalso proplists:get_bool(Hash, Hashes) + andalso is_pair(Hash, Sign, Hashes) + of + true -> + [Alg | Acc]; + false -> + Acc + end end, Supported = lists:foldl(Fun, [], SignatureSchemes), lists:reverse(Supported); From 1564864b8e7a6cd247995eb74efa5d9ab7f9ea0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Fri, 14 Jun 2019 16:08:46 +0200 Subject: [PATCH 39/73] ssl: Add interop test Add interoperability test for TLS 1.2 server and TLS 1.3 client. --- lib/ssl/test/ssl_basic_SUITE.erl | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 785ea98fa05..93c03daa45c 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -249,6 +249,7 @@ tls13_test_group() -> tls_record_1_3_encode_decode, tls13_finished_verify_data, tls13_1_RTT_handshake, + tls12_ssl_server_tls13_ssl_client, tls13_basic_ssl_server_openssl_client, tls13_custom_groups_ssl_server_openssl_client, tls13_hello_retry_request_ssl_server_openssl_client, @@ -5351,6 +5352,41 @@ tls13_finished_verify_data(_Config) -> FinishedKey = tls_v1:finished_key(BaseKey, sha256), VerifyData = tls_v1:finished_verify_data(FinishedKey, sha256, Messages). + +tls12_ssl_server_tls13_ssl_client() -> + [{doc,"Test basic connection between TLS 1.2 server and TLS 1.3 client"}]. + +tls12_ssl_server_tls13_ssl_client(Config) -> + ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config), + ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + %% Set versions + ServerOpts = [{versions, ['tlsv1.2']}|ServerOpts0], + ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}, + {signature_algs_cert, [ecdsa_secp384r1_sha384, + rsa_pss_rsae_sha256, + rsa_pkcs1_sha256, + {sha256,rsa},{sha256,dsa}]}|ClientOpts0], + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ClientOpts}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close_port(Client). + + tls13_basic_ssl_server_openssl_client() -> [{doc,"Test TLS 1.3 basic connection between ssl server and openssl s_client"}]. From 8e60fe7df9fa2ceaa4636495a9b75d495dc336e9 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 17 Jun 2019 11:17:04 +0200 Subject: [PATCH 40/73] Don't disconnect on remote exit/2 with old incarnation as recipient --- erts/emulator/beam/dist.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 9fddac89800..26352e5534f 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -1668,9 +1668,17 @@ int erts_net_message(Port *prt, token = tuple[4]; reason = tuple[5]; } - if (is_not_pid(from) || is_not_internal_pid(to)) { + if (is_not_pid(from)) { goto invalid_message; } + if (is_not_internal_pid(to)) { + if (is_external_pid(to)) { + DistEntry *dep = external_pid_dist_entry(to); + if (dep == erts_this_dist_entry) + break; /* Old incarnation of this node... */ + } + goto invalid_message; + } rp = erts_pid2proc(NULL, 0, to, rp_locks); if (rp) { (void) erts_send_exit_signal(NULL, From 70a885cfd869612c0f0896390f72a1fd0fd07c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Mon, 17 Jun 2019 13:48:19 +0200 Subject: [PATCH 41/73] ssl: Fix ssl_handshake:extension_value/1 Handle new TLS 1.2/1.3 extensions. --- lib/ssl/src/ssl_handshake.erl | 11 ++++++++- lib/ssl/test/ssl_basic_SUITE.erl | 40 +++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index f68d3e9b261..c890beaf089 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1474,7 +1474,16 @@ extension_value(#next_protocol_negotiation{extension_data = Data}) -> extension_value(#srp{username = Name}) -> Name; extension_value(#renegotiation_info{renegotiated_connection = Data}) -> - Data. + Data; +extension_value(#signature_algorithms{signature_scheme_list = Schemes}) -> + Schemes; +extension_value(#signature_algorithms_cert{signature_scheme_list = Schemes}) -> + Schemes; +extension_value(#key_share_client_hello{client_shares = ClientShares}) -> + ClientShares; +extension_value(#client_hello_versions{versions = Versions}) -> + Versions. + %%-------------------------------------------------------------------- %%% Internal functions diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 785ea98fa05..6b4d73d5a1f 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -244,7 +244,8 @@ rizzo_tests() -> %% For testing TLS 1.3 features and possible regressions tls13_test_group() -> - [tls13_enable_client_side, + [handshake_continue_tls13_client, + tls13_enable_client_side, tls13_enable_server_side, tls_record_1_3_encode_decode, tls13_finished_verify_data, @@ -671,6 +672,43 @@ handshake_continue(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +handshake_continue_tls13_client() -> + [{doc, "Test API function ssl:handshake_continue/3"}]. +handshake_continue_tls13_client(Config) when is_list(Config) -> + ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), + ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0], + + ClientOptsHello0 = ssl_test_lib:ssl_options([{handshake, hello}], Config), + ClientOptsHello = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOptsHello0], + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ssl_test_lib:ssl_options([{reuseaddr, true}, {handshake, hello}], + Config)}, + {continue_options, proplists:delete(reuseaddr, ServerOpts)} + ]), + + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ClientOptsHello}, + {continue_options, proplists:delete(reuseaddr, ClientOpts)}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + %%------------------------------------------------------------------ handshake_continue_timeout() -> [{doc, "Test API function ssl:handshake_continue/3 with short timeout"}]. From 3cb0cb717859601de6fbaeb05cd26fbfd485eaa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Tue, 11 Jun 2019 16:31:05 +0200 Subject: [PATCH 42/73] ssl: Fix run_client_error/1 in ssl_test_lib Fix run_client_error/1 to properly propagate errors from the test client. --- lib/ssl/test/ssl_test_lib.erl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 832f8494c69..d46ba1f7878 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1103,7 +1103,15 @@ run_client_error(Opts) -> Options = proplists:get_value(options, Opts), ct:log("~p:~p~nssl:connect(~p, ~p, ~p)~n", [?MODULE,?LINE, Host, Port, Options]), Error = Transport:connect(Host, Port, Options), - Pid ! {self(), Error}. + case Error of + {error, _} -> + Pid ! {self(), Error}; + {ok, _Socket} -> + receive + {ssl_error, _, {tls_alert, _}} = SslError -> + Pid ! {self(), SslError} + end + end. accepters(N) -> accepters([], N). From 021607a213435344db07662bc79ea4895b6b94e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Mon, 3 Jun 2019 15:41:24 +0200 Subject: [PATCH 43/73] ssl: Fix negative tests in ssl_basic_SUITE --- lib/ssl/test/ssl_basic_SUITE.erl | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 6b4d73d5a1f..484a8f5c988 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -5484,14 +5484,11 @@ tls13_client_auth_empty_cert_alert_ssl_server_openssl_client(Config) -> Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts), - ssl_test_lib:check_result(Server, - {error, - {tls_alert, - {certificate_required, - "received SERVER ALERT: Fatal - Certificate required - certificate_required"}}}), + ssl_test_lib:check_server_alert(Server, certificate_required), ssl_test_lib:close(Server), ssl_test_lib:close_port(Client). + tls13_client_auth_empty_cert_ssl_server_openssl_client() -> [{doc,"TLS 1.3: Test client authentication when client sends an empty certificate and fail_if_no_peer_cert is set to false."}]. @@ -5573,11 +5570,7 @@ tls13_hrr_client_auth_empty_cert_alert_ssl_server_openssl_client(Config) -> Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts), - ssl_test_lib:check_result(Server, - {error, - {tls_alert, - {certificate_required, - "received SERVER ALERT: Fatal - Certificate required - certificate_required"}}}), + ssl_test_lib:check_server_alert(Server, certificate_required), ssl_test_lib:close(Server), ssl_test_lib:close_port(Client). @@ -5664,13 +5657,7 @@ tls13_unsupported_sign_algo_client_auth_ssl_server_openssl_client(Config) -> Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts), - ssl_test_lib:check_result( - Server, - {error, - {tls_alert, - {insufficient_security, - "received SERVER ALERT: Fatal - Insufficient Security - " - "\"No suitable signature algorithm\""}}}), + ssl_test_lib:check_server_alert(Server, insufficient_security), ssl_test_lib:close(Server), ssl_test_lib:close_port(Client). @@ -5703,12 +5690,7 @@ tls13_unsupported_sign_algo_cert_client_auth_ssl_server_openssl_client(Config) - Client = ssl_test_lib:start_basic_client(openssl, 'tlsv1.3', Port, ClientOpts), - ssl_test_lib:check_result( - Server, - {error, - {tls_alert, - {illegal_parameter, - "received CLIENT ALERT: Fatal - Illegal Parameter"}}}), + ssl_test_lib:check_server_alert(Server, certificate_required), ssl_test_lib:close(Server), ssl_test_lib:close_port(Client). From 594cbfc5d80dbc1e4ca959e9a86122b3ca532e02 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Mon, 17 Jun 2019 16:51:20 +0200 Subject: [PATCH 44/73] Prepare release --- erts/doc/src/notes.xml | 28 ++++++++++++++++++++++++++++ erts/vsn.mk | 2 +- lib/kernel/doc/src/notes.xml | 18 ++++++++++++++++++ lib/kernel/src/kernel.appup.src | 8 ++++++-- lib/kernel/vsn.mk | 2 +- lib/ssl/doc/src/notes.xml | 30 ++++++++++++++++++++++++++++++ lib/ssl/vsn.mk | 2 +- make/otp_version_tickets | 15 ++++++--------- 8 files changed, 91 insertions(+), 14 deletions(-) diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 075972c9792..128def3934a 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,34 @@

This document describes the changes made to the ERTS application.

+
Erts 10.4.3 + +
Fixed Bugs and Malfunctions + + +

Fixed a buffer overflow when + binary_to_existing_atom/2 and + list_to_existing_atom/2 was used with the + latin1 encoding.

+

+ Own Id: OTP-15819 Aux Id: ERL-944

+
+ +

+ The runtime system disconnected a connection if it + received an exit/2 signal where the recipient was + a process on an old incarnation of the current node. That + is, the receiving node had the same node name, but + another "creation" number. The signal will now just be + dropped since the receiving process no longer exists.

+

+ Own Id: OTP-15867 Aux Id: ERIERL-373

+
+
+
+ +
+
Erts 10.4.2
Fixed Bugs and Malfunctions diff --git a/erts/vsn.mk b/erts/vsn.mk index 53dce5e8157..40a9685e9d3 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 10.4.2 +VSN = 10.4.3 # Port number 4365 in 4.2 # Port number 4366 in 4.3 diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 6f68a67174b..b065cc2cd8e 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,24 @@

This document describes the changes made to the Kernel application.

+
Kernel 6.4.1 + +
Fixed Bugs and Malfunctions + + +

user/user_drv could respond to io + requests before they had been processed, which could + cause data to be dropped if the emulator was halted soon + after a call to io:format/2, such as in an + escript.

+

+ Own Id: OTP-15805

+
+
+
+ +
+
Kernel 6.4
Fixed Bugs and Malfunctions diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index cd0397a98c3..95853a7a8f8 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -38,7 +38,9 @@ {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.3$">>,[restart_new_emulator]}, {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^6\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], + {<<"^6\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^6\\.4$">>,[restart_new_emulator]}, + {<<"^6\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], [{<<"^6\\.0$">>,[restart_new_emulator]}, {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, @@ -50,4 +52,6 @@ {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.3$">>,[restart_new_emulator]}, {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^6\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. + {<<"^6\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^6\\.4$">>,[restart_new_emulator]}, + {<<"^6\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}. diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 765e8901577..e5188aa9b50 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 6.4 +KERNEL_VSN = 6.4.1 diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 5c213402f49..29bf5fc4e73 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,36 @@

This document describes the changes made to the SSL application.

+
SSL 9.3.3 + +
Fixed Bugs and Malfunctions + + +

+ Correct handshake handling, might cause strange symptoms + such as ASN.1 certificate decoding issues.

+

+ Own Id: OTP-15879 Aux Id: ERL-968

+
+ +

+ Fix handling of the signature_algorithms_cert extension + in the ClientHello handshake message.

+

+ Own Id: OTP-15887 Aux Id: ERL-973

+
+ +

+ Handle new ClientHello extensions when handshake is + paused by the {handshake, hello} ssl option.

+

+ Own Id: OTP-15888 Aux Id: ERL-975

+
+
+
+ +
+
SSL 9.3.2
Fixed Bugs and Malfunctions diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 4e387fa403e..01dee392f53 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.3.2 +SSL_VSN = 9.3.3 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index e071f1a4307..fd9b36720a6 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1,9 +1,6 @@ -OTP-15844 -OTP-15861 -OTP-15862 -OTP-15864 -OTP-15865 -OTP-15871 -OTP-15872 -OTP-15873 -OTP-15875 +OTP-15805 +OTP-15819 +OTP-15867 +OTP-15879 +OTP-15887 +OTP-15888 From 4319a7f8bc93388ec540e954eb9bb73ea1eec4ef Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Mon, 17 Jun 2019 16:51:22 +0200 Subject: [PATCH 45/73] Updated OTP version --- OTP_VERSION | 2 +- otp_versions.table | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OTP_VERSION b/OTP_VERSION index 8b740661820..758704512b5 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0.3 +22.0.4 diff --git a/otp_versions.table b/otp_versions.table index 8e3d127e4ed..956a5968772 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.0.4 : erts-10.4.3 kernel-6.4.1 ssl-9.3.3 # asn1-5.0.9 common_test-1.17.3 compiler-7.4.2 crypto-4.5.1 debugger-4.2.7 dialyzer-4.0.1 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.3 : compiler-7.4.2 dialyzer-4.0.1 erts-10.4.2 ssl-9.3.2 stdlib-3.9.2 # asn1-5.0.9 common_test-1.17.3 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.2 : compiler-7.4.1 crypto-4.5.1 erts-10.4.1 stdlib-3.9.1 # asn1-5.0.9 common_test-1.17.3 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3.1 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.1 : ssl-9.3.1 # asn1-5.0.9 common_test-1.17.3 compiler-7.4 crypto-4.5 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : From 03252470c0008443a3903eed56d3b8b96a27ed55 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 18 Jun 2019 17:27:33 +0200 Subject: [PATCH 46/73] [esock] socket:setopt add_membership fails with badarg An invalid value test caused the socket:setopt(Socket, ip, add_membership, ip_mreq()) to fail with badarg. OTP-15908 (ERL-980) --- erts/emulator/nifs/common/socket_nif.c | 100 ++++++++++++++++++++----- 1 file changed, 82 insertions(+), 18 deletions(-) diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index ee3b9f2a985..dc0847fa397 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -8860,35 +8860,67 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, #endif // It must be a map - if (!IS_MAP(env, eVal)) + if (!IS_MAP(env, eVal)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "value *not* a map\r\n") ); return enif_make_badarg(env); + } // It must have atleast two attributes - if (!enif_get_map_size(env, eVal, &sz) || (sz >= 2)) + if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "invalid map value: %T\r\n", eVal) ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) + if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed get multiaddr (map) attribute\r\n") ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) + if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed get interface (map) attribute\r\n") ); return enif_make_badarg(env); + } if ((xres = esock_decode_ip4_address(env, eMultiAddr, - &mreq.imr_multiaddr)) != NULL) + &mreq.imr_multiaddr)) != NULL) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) ); return esock_make_error_str(env, xres); + } if ((xres = esock_decode_ip4_address(env, eInterface, - &mreq.imr_interface)) != NULL) + &mreq.imr_interface)) != NULL) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed decode interface %T: %s\r\n", eInterface, xres) ); return esock_make_error_str(env, xres); + } res = socket_setopt(descP->sock, level, opt, &mreq, sizeof(mreq)); - if (res != 0) - result = esock_make_error_errno(env, sock_errno()); - else + if (res != 0) { + int save_errno = sock_errno(); + + result = esock_make_error_errno(env, save_errno); + + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed setopt: %T (%d)\r\n", result, save_errno) ); + + } else { result = esock_atom_ok; + } return result; } @@ -9492,33 +9524,65 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, #endif // It must be a map - if (!IS_MAP(env, eVal)) + if (!IS_MAP(env, eVal)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "value *not* a map\r\n") ); return enif_make_badarg(env); + } // It must have atleast two attributes - if (!enif_get_map_size(env, eVal, &sz) || (sz >= 2)) + if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "invalid map value: %T\r\n", eVal) ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) + if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed get multiaddr (map) attribute\r\n") ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) + if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed get interface (map) attribute\r\n") ); return enif_make_badarg(env); + } if ((xres = esock_decode_ip6_address(env, eMultiAddr, - &mreq.ipv6mr_multiaddr)) != NULL) + &mreq.ipv6mr_multiaddr)) != NULL) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) ); return esock_make_error_str(env, xres); + } - if (!GET_UINT(env, eInterface, &mreq.ipv6mr_interface)) + if (!GET_UINT(env, eInterface, &mreq.ipv6mr_interface)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed decode interface %T: %s\r\n", eInterface, xres) ); return esock_make_error(env, esock_atom_einval); + } res = socket_setopt(descP->sock, level, opt, &mreq, sizeof(mreq)); - if (res != 0) - result = esock_make_error_errno(env, sock_errno()); - else + if (res != 0) { + int save_errno = sock_errno(); + + result = esock_make_error_errno(env, save_errno); + + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed setopt: %T (%d)\r\n", result, save_errno) ); + + } else { result = esock_atom_ok; + } return result; } From 1f3dde12d06bb325f51ecba2bbd48b4040474136 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 18 Jun 2019 17:37:03 +0200 Subject: [PATCH 47/73] ssl: Fix hibernation bug --- lib/ssl/src/tls_connection.erl | 2 +- lib/ssl/test/ssl_basic_SUITE.erl | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 52e5db731a8..0129ba8ebc9 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -207,7 +207,7 @@ next_event(StateName, Record, State) -> next_event(StateName, no_record, State0, Actions) -> case next_record(State0) of {no_record, State} -> - {next_state, StateName, State, Actions}; + ssl_connection:hibernate_after(StateName, State, Actions); {#ssl_tls{} = Record, State} -> {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]}; #alert{} = Alert -> diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 4452adaea78..b23ef74c506 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -3769,7 +3769,7 @@ hibernate(Config) -> ssl_test_lib:check_result(Server, ok, Client, ok), - timer:sleep(1500), + ct:sleep(1500), {current_function, {erlang, hibernate, 3}} = process_info(Pid, current_function), @@ -3805,6 +3805,8 @@ hibernate_right_away(Config) -> [{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]), ssl_test_lib:check_result(Server1, ok, Client1, ok), + + ct:sleep(1000), %% Schedule out {current_function, {erlang, hibernate, 3}} = process_info(Pid1, current_function), From 1df633b6c91de483425b059daadf84984b2f49c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Wed, 19 Jun 2019 10:11:20 +0200 Subject: [PATCH 48/73] ssl: Backport fix for signature_algorithms_cert This commit fixes interoperability problems with openssl when the TLS 1.3 server is using the option signature_algs_cert. In such cases the signature_algorithms_cert extension was encoded as a signature_algorithms extension and openssl s_client returned an Illegal Parameter Alert due to its filtering of extension duplicates. --- lib/ssl/src/tls_handshake_1_3.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl index 8a4ad922e1d..e83b3f63bb6 100644 --- a/lib/ssl/src/tls_handshake_1_3.erl +++ b/lib/ssl/src/tls_handshake_1_3.erl @@ -111,7 +111,7 @@ add_signature_algorithms_cert(Extensions, undefined) -> Extensions; add_signature_algorithms_cert(Extensions, SignAlgsCert) -> Extensions#{signature_algorithms_cert => - #signature_algorithms{signature_scheme_list = SignAlgsCert}}. + #signature_algorithms_cert{signature_scheme_list = SignAlgsCert}}. filter_tls13_algs(undefined) -> undefined; From 6e763058d39a30027750fec01708677462bb27bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Wed, 19 Jun 2019 11:11:49 +0200 Subject: [PATCH 49/73] ssl: Fix handling of certificate decoding problems --- lib/ssl/src/tls_handshake_1_3.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl index 8a4ad922e1d..cb0dbc02065 100644 --- a/lib/ssl/src/tls_handshake_1_3.erl +++ b/lib/ssl/src/tls_handshake_1_3.erl @@ -802,7 +802,7 @@ validate_certificate_chain(Certs, CertDbHandle, CertDbRef, SslOptions, CRLDbHand CertDbHandle, CertDbRef) end catch - error:{badmatch,{asn1, Asn1Reason}} -> + error:{badmatch,{error, {asn1, Asn1Reason}}} -> %% ASN-1 decode of certificate somehow failed {error, {certificate_unknown, {failed_to_decode_certificate, Asn1Reason}}}; error:OtherReason -> From 7d1058ed7de3c04055feb62108a78e29c33c5ddb Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 19 Jun 2019 16:25:49 +0200 Subject: [PATCH 50/73] Fix fatal bug in erts_proc_sig_signal_size called by erlang:process_info(memory) erlang:system_info(procs) crash dump break menu Will crash VM if process has a pending monitor DOWN signal in its queue. --- erts/emulator/beam/erl_proc_sig_queue.c | 1 + erts/emulator/test/system_info_SUITE.erl | 53 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c index d475a0a634c..60060cb0927 100644 --- a/erts/emulator/beam/erl_proc_sig_queue.c +++ b/erts/emulator/beam/erl_proc_sig_queue.c @@ -3865,6 +3865,7 @@ erts_proc_sig_signal_size(ErtsSignal *sig) case ERTS_MON_TYPE_DIST_PROC: case ERTS_MON_TYPE_NODE: size = erts_monitor_size((ErtsMonitor *) sig); + break; default: ERTS_INTERNAL_ERROR("Unexpected sig type"); break; diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index 4e663fed7fc..da2c0ef8ace 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -37,10 +37,13 @@ -export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1, memory/1, ets_limit/1, atom_limit/1, + procs_bug/1, ets_count/1, atom_count/1, system_logger/1]). -export([init/1, handle_event/2, handle_call/2]). +-export([init_per_testcase/2, end_per_testcase/2]). + suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 2}}]. @@ -48,8 +51,20 @@ suite() -> all() -> [process_count, system_version, misc_smoke_tests, ets_count, heap_size, wordsize, memory, ets_limit, atom_limit, atom_count, + procs_bug, system_logger]. + +init_per_testcase(procs_bug, Config) -> + procs_bug(init_per_testcase, Config); +init_per_testcase(_, Config) -> + Config. + +end_per_testcase(procs_bug, Config) -> + procs_bug(end_per_testcase, Config); +end_per_testcase(_, _) -> + ok. + %%% %%% The test cases ------------------------------------------------------------- %%% @@ -649,3 +664,41 @@ handle_call(Msg, State) -> handle_event(Event, State) -> State ! {report_handler, Event}, {ok, State}. + + +%% OTP-15909: Provoke bug that would cause VM crash +%% if doing system_info(procs) when process have queued exit/down signals. +procs_bug(init_per_testcase, Config) -> + %% Use single scheduler and process prio to starve monitoring processes + %% from handling their received DOWN signals. + OldSchedOnline = erlang:system_flag(schedulers_online,1), + [{schedulers_online, OldSchedOnline} | Config]; +procs_bug(end_per_testcase, Config) -> + erlang:system_flag(schedulers_online, + proplists:get_value(schedulers_online, Config)), + ok. + +procs_bug(Config) when is_list(Config) -> + {Monee,_} = spawn_opt(fun () -> receive die -> ok end end, + [monitor,{priority,max}]), + Papa = self(), + Pids = [begin + P = spawn_opt(fun () -> + erlang:monitor(process, Monee), + Papa ! {self(),ready}, + receive "nada" -> no end + end, + [link, {priority,normal}]), + {P, ready} = receive M -> M end, + P + end + || _ <- lists:seq(1,10)], + process_flag(priority,high), + Monee ! die, + {'DOWN',_,process,Monee,normal} = receive M -> M end, + + %% This call did crash VM as Pids have pending DOWN signals. + erlang:system_info(procs), + process_flag(priority,normal), + [begin unlink(P), exit(P, kill) end || P <- Pids], + ok. From 0a1bcbb010d85e40257437cee24ff2f67abe3b5a Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 20 Jun 2019 11:04:46 +0200 Subject: [PATCH 51/73] [esock|test] Add test case for IP add|drop membership Add a simple test case that tests that its possible to perform socket:setopt(Socket, ip, [add|drop]_membership, MReq). OTP-15908 --- erts/emulator/test/socket_SUITE.erl | 481 ++++++++++++++++++++++++++-- 1 file changed, 456 insertions(+), 25 deletions(-) diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index e3545ccbf9b..c6b5c31503e 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -79,6 +79,7 @@ api_opt_simple_otp_options/1, api_opt_simple_otp_rcvbuf_option/1, api_opt_simple_otp_controlling_process/1, + api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** api_to_connect_tcp4/1, @@ -511,6 +512,8 @@ groups() -> [{api, [], api_cases()}, {api_basic, [], api_basic_cases()}, {api_options, [], api_options_cases()}, + {api_options_otp, [], api_options_otp_cases()}, + {api_options_ip, [], api_options_ip_cases()}, {api_op_with_timeout, [], api_op_with_timeout_cases()}, {socket_closure, [], socket_closure_cases()}, {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, @@ -595,12 +598,23 @@ api_basic_cases() -> ]. api_options_cases() -> + [ + {group, api_options_otp}, + {group, api_options_ip} + ]. + +api_options_otp_cases() -> [ api_opt_simple_otp_options, api_opt_simple_otp_rcvbuf_option, api_opt_simple_otp_controlling_process ]. +api_options_ip_cases() -> + [ + api_opt_ip_add_drop_membership + ]. + api_op_with_timeout_cases() -> [ api_to_connect_tcp4, @@ -3173,7 +3187,7 @@ api_opt_simple_otp_controlling_process(suite) -> api_opt_simple_otp_controlling_process(doc) -> []; api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(api_opt_simple_otp_controlling_process, fun() -> api_opt_simple_otp_controlling_process() end). @@ -3417,6 +3431,321 @@ api_opt_simple_otp_controlling_process() -> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests that the add_mambership and drop_membership ip options work. +%% We create one server and two clients. The server only send messages, +%% the clients only receives messages. +%% An UDP datagram is forbidden (RFC 1122) from having a source address +%% that is a multicast address (or a broadcast address). +%% So, the server create a socket "for sending" and the clients sockets +%% "for receiving". +%% Sending socket: Bound to the local address (and any port). +%% When sending, the dest will be the multicast address +%% and port of the receiving socket. +%% Receiving socket: Bound to the multicast address and port. +api_opt_ip_add_drop_membership(suite) -> + []; +api_opt_ip_add_drop_membership(doc) -> + ["OTP-15908 (ERL-980)"]; +api_opt_ip_add_drop_membership(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_ip_add_drop_membership, + fun() -> + has_ip_add_membership_support(), + has_ip_drop_membership_support(), + has_ip_multicast_support() + end, + fun() -> api_opt_ip_add_drop_membership() end). + + +api_opt_ip_add_drop_membership() -> + Set = fun(S, Key, Val) -> + socket:setopt(S, ip, Key, Val) + end, + AddMembership = fun(S, Val) -> Set(S, add_membership, Val) end, + DropMembership = fun(S, Val) -> Set(S, drop_membership, Val) end, + + ServerSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start", + cmd => fun(State) -> + {Tester, MSA} = ?SEV_AWAIT_START(), + {ok, State#{tester => Tester, msa => MSA}} + end}, + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = _State) -> + _MRef = erlang:monitor(process, Tester), + ok + end}, + + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LAddr = which_local_addr(Domain), + LSA = #{family => Domain, addr => LAddr}, + {ok, State#{local_sa => LSA}} + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make recv socket reuse addr", + cmd => fun(#{sock := Sock} = _State) -> + case socket:setopt(Sock, socket, reuseaddr, true) of + ok -> + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Failed set reuseaddr: " + "~n ~p", [Reason]), + ERROR + end + end}, + #{desc => "bind recv socket to multicast address", + cmd => fun(#{sock := Sock, msa := MSA} = State) -> + case socket:bind(Sock, MSA) of + {ok, Port} -> + ?SEV_IPRINT("bound to:" + "~n ~p", [Port]), + {ok, State#{msa => MSA#{port => Port}}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready (init)", + cmd => fun(#{tester := Tester}) -> + ?SEV_ANNOUNCE_READY(Tester, init), + ok + end}, + + %% The actual test + #{desc => "await continue (add_membership)", + cmd => fun(#{tester := Tester} = _State) -> + ?SEV_AWAIT_CONTINUE(Tester, tester, add_membership) + end}, + #{desc => "add membership", + cmd => fun(#{sock := Sock, + msa := #{addr := MAddr}, + local_sa := #{addr := Addr}} = State) -> + MReq = #{multiaddr => MAddr, + interface => Addr}, + ?SEV_IPRINT("try add membership to:" + "~n ~p", [MReq]), + case AddMembership(Sock, MReq) of + ok -> + ?SEV_IPRINT("membership added"), + {ok, State#{mreq => MReq}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Failed adding membership to: " + "~n ~p" + "~n Reason: ~p", + [MReq, Reason]), + ERROR + end + end}, + #{desc => "announce ready (add-membership)", + cmd => fun(#{tester := Tester}) -> + ?SEV_ANNOUNCE_READY(Tester, add_membership), + ok + end}, + + #{desc => "await continue (drop_membership)", + cmd => fun(#{tester := Tester} = _State) -> + ?SEV_AWAIT_CONTINUE(Tester, tester, drop_membership) + end}, + #{desc => "drop membership", + cmd => fun(#{sock := Sock, + mreq := MReq} = State) -> + ?SEV_IPRINT("try drop membership from:" + "~n ~p", [MReq]), + case DropMembership(Sock, MReq) of + ok -> + ?SEV_IPRINT("membership dropped"), + {ok, maps:remove(mreq, State)}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Failed drop membership from: " + "~n ~p" + "~n Reason: ~p", + [MReq, Reason]), + ERROR + end + end}, + #{desc => "announce ready (drop-membership)", + cmd => fun(#{tester := Tester}) -> + ?SEV_ANNOUNCE_READY(Tester, drop_membership), + ok + end}, + + + %% Termination + #{desc => "await terminate (from tester)", + cmd => fun(#{tester := Tester} = State) -> + case ?SEV_AWAIT_TERMINATE(Tester, tester) of + ok -> + {ok, maps:remove(tester, State)}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "close socket", + cmd => fun(#{sock := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(sock, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + + TesterSeq = + [ + %% *** Init part *** + #{desc => "monitor server", + cmd => fun(#{server := Server} = _State) -> + _MRef = erlang:monitor(process, Server), + ok + end}, + + %% Start the server + #{desc => "order server start", + cmd => fun(#{server := Pid, msa := MSA} = _State) -> + ?SEV_ANNOUNCE_START(Pid, MSA), + ok + end}, + #{desc => "await server ready (init)", + cmd => fun(#{server := Pid} = _State) -> + case ?SEV_AWAIT_READY(Pid, server, init) of + ok -> + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Start of server failed: " + "~n ~p", [Reason]), + ERROR + end + end}, + + + %% *** The actual test *** + #{desc => "order server to continue (add-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_ANNOUNCE_CONTINUE(Server, add_membership), + ok + end}, + #{desc => "await server ready (add-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_AWAIT_READY(Server, server, add_membership) + end}, + + #{desc => "order server to continue (drop-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_ANNOUNCE_CONTINUE(Server, drop_membership), + ok + end}, + #{desc => "await server ready (drop-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_AWAIT_READY(Server, server, drop_membership) + end}, + + ?SEV_SLEEP(?SECS(1)), + + %% *** Termination *** + #{desc => "order server terminate", + cmd => fun(#{server := Server} = _State) -> + ?SEV_ANNOUNCE_TERMINATE(Server), + ok + end}, + #{desc => "await server termination", + cmd => fun(#{server := Server} = State) -> + ?SEV_AWAIT_TERMINATION(Server), + {ok, maps:remove(server, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + + i("get multicast address"), + Domain = inet, + MAddr = which_ip_multicast_address(), + MSA = #{family => Domain, addr => MAddr}, + + i("start server evaluator"), + ServerInitState = #{domain => Domain}, + Server = ?SEV_START("server", ServerSeq, ServerInitState), + + i("start tester evaluator"), + TesterInitState = #{domain => Domain, + msa => MSA, + server => Server#ev.pid}, + Tester = ?SEV_START("tester", TesterSeq, TesterInitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester, Server]). + + + +which_ip_multicast_address() -> + which_multicast_address(inet). + +which_multicast_address(Domain) -> + case os:type() of + {unix, linux} -> + WhichMAddr = fun([_, _, MAddr]) -> MAddr end, + which_multicast_address2(Domain, WhichMAddr); + + {unix, sunos} -> + WhichMAddr = fun([_, MAddr, _]) -> MAddr end, + which_multicast_address2(Domain, WhichMAddr); + + Type -> + not_supported({multicast, Type}) + end. + +%% Note that the 'netstat -g' table looks different on linux and SunOS +%% Linux: IfName - RefCnt - Group +%% SunOS: IfName - Group - RefCnt + +which_multicast_address2(Domain, WhichMAddr) -> + IfName = which_local_host_ifname(Domain), + NetstatGroupsStr = os:cmd("netstat -g | grep " ++ IfName), + NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]), + NetstatGroups = [string:tokens(G, [$ ]) || G <- NetstatGroups0], + MAddrs = [WhichMAddr(NetstatGroup) || NetstatGroup <- + NetstatGroups], + which_multicast_address3(Domain, MAddrs). + +which_multicast_address3(_Domain, []) -> + not_supported({multicast, no_valid_addrs}); +which_multicast_address3(Domain, [MAddrStr|MAddrs]) -> + %% Even on linux some of these are not actually addresses, but + %% "host names", such as all-systems.mcast.net. But both + %% address strings, such as "224.0.0.251" and host name strings + %% gets translated into an address by the inet:inet:getaddr/2. + case inet:getaddr(MAddrStr, Domain) of + {ok, MAddr} -> + MAddr; + {error, _} -> + which_multicast_address3(Domain, MAddrs) + end. + +which_local_host_ifname(Domain) -> + case which_local_host_info(Domain) of + {ok, {Name, _Addr, _Flags}} -> + Name; + {error, Reason} -> + not_supported({multicast, Reason}) + end. + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% @@ -11304,7 +11633,7 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> LSA = #{family => Domain, addr => LAddr}, {ok, State#{local_sa => LSA}} end}, - #{desc => "create listen socket", + #{desc => "create socket", cmd => fun(#{domain := Domain} = State) -> case socket:open(Domain, dgram, udp) of {ok, Sock} -> @@ -17899,47 +18228,146 @@ local_host() -> end. + + %% This gets the local address (not 127.0...) %% We should really implement this using the (new) net module, %% but until that gets the necessary functionality... which_local_addr(Domain) -> - case inet:getifaddrs() of - {ok, IFL} -> - which_addr(Domain, IFL); + case which_local_host_info(Domain) of + {ok, {_Name, _Flags, Addr}} -> + Addr; {error, Reason} -> ?FAIL({inet, getifaddrs, Reason}) end. -which_addr(_Domain, []) -> +%% which_addr(_Domain, []) -> +%% ?FAIL(no_address); +%% which_addr(Domain, [{"lo" ++ _, _}|IFL]) -> +%% which_addr(Domain, IFL); +%% which_addr(Domain, [{"docker" ++ _, _}|IFL]) -> +%% which_addr(Domain, IFL); +%% which_addr(Domain, [{"br-" ++ _, _}|IFL]) -> +%% which_addr(Domain, IFL); +%% which_addr(Domain, [{_Name, IFO}|IFL]) -> +%% case which_addr2(Domain, IFO) of +%% {ok, Addr} -> +%% Addr; +%% {error, no_address} -> +%% which_addr(Domain, IFL) +%% end; +%% which_addr(Domain, [_|IFL]) -> +%% which_addr(Domain, IFL). + +%% which_addr2(_Domain, []) -> +%% {error, no_address}; +%% which_addr2(inet = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 4) -> +%% {ok, Addr}; +%% which_addr2(inet6 = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 8) -> +%% {ok, Addr}; +%% which_addr2(Domain, [_|IFO]) -> +%% which_addr2(Domain, IFO). + + +%% Returns the interface (name), flags and address (not 127...) +%% of the local host. +which_local_host_info(Domain) -> + case inet:getifaddrs() of + {ok, IFL} -> + which_local_host_info(Domain, IFL); + {error, _} = ERROR -> + ERROR + end. + +which_local_host_info(_Domain, []) -> ?FAIL(no_address); -which_addr(Domain, [{"lo" ++ _, _}|IFL]) -> - which_addr(Domain, IFL); -which_addr(Domain, [{_Name, IFO}|IFL]) -> - case which_addr2(Domain, IFO) of - {ok, Addr} -> - Addr; - {error, no_address} -> - which_addr(Domain, IFL) +which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{Name, IFO}|IFL]) -> + case which_local_host_info2(Domain, IFO) of + {ok, {Flags, Addr}} -> + {ok, {Name, Flags, Addr}}; + {error, _} -> + which_local_host_info(Domain, IFL) end; -which_addr(Domain, [_|IFL]) -> - which_addr(Domain, IFL). +which_local_host_info(Domain, [_|IFL]) -> + which_local_host_info(Domain, IFL). + +which_local_host_info2(Domain, IFO) -> + case lists:keysearch(flags, 1, IFO) of + {value, {flags, Flags}} -> + which_local_host_info2(Domain, IFO, Flags); + false -> + {error, no_flags} + end. -which_addr2(_Domain, []) -> +which_local_host_info2(_Domain, [], _Flags) -> {error, no_address}; -which_addr2(inet = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 4) -> - {ok, Addr}; -which_addr2(inet6 = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 8) -> - {ok, Addr}; -which_addr2(Domain, [_|IFO]) -> - which_addr2(Domain, IFO). +which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags) + when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> + {ok, {Flags, Addr}}; +which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags) + when (size(Addr) =:= 8) andalso + (element(1, Addr) =/= 0) andalso + (element(1, Addr) =/= 16#fe80) -> + {ok, {Flags, Addr}}; +which_local_host_info2(Domain, [_|IFO], Flags) -> + which_local_host_info2(Domain, IFO, Flags). + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Here are all the *general* test case condition functions. + +%% We also need (be able) to figure out the the multicast address, +%% which we only support for some platforms (linux and sunos). +%% We don't do that here, but since we can only do that (find a +%% multicast address) for specific platforms, we check that we are +%% on of those platforms here. +has_ip_multicast_support() -> + case os:type() of + {unix, OsName} when (OsName =:= linux) orelse + (OsName =:= sunos) -> + case which_local_host_info(inet) of + {ok, {_Name, Flags, _Addr}} -> + case lists:member(multicast, Flags) of + true -> + ok; + false -> + not_supported(multicast) + end; + {error, Reason} -> + not_supported({multicast, Reason}) + end; + Type -> + not_supported({multicast, Type}) + end. +has_ip_add_membership_support() -> + has_socket_option_ip_support(add_membership). +has_ip_drop_membership_support() -> + has_socket_option_ip_support(drop_membership). +has_socket_option_ip_support(Opt) -> + has_socket_option_support(ip, Opt). + +has_socket_option_support(Level, Option) -> + case socket:supports(options, Level, Option) of + true -> + ok; + false -> + not_supported({options, Level, Option}) + end. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Here are all the *general* test vase condition functions. %% The idea is that this function shall test if the test host has %% support for IPv6. If not, there is no point in running IPv6 tests. @@ -17957,6 +18385,9 @@ has_support_ipv6() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +not_supported(What) -> + skip({not_supported, What}). + not_yet_implemented() -> skip("not yet implemented"). From dd9a4d6f559cac28fd74dac0ff62d27bfed66e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 17 May 2019 19:24:29 +0200 Subject: [PATCH 52/73] Always fallback to source when we can't parse AST This commit fixes a bug in Dialyzer where it would assume all Erlang AST can be converted back to valid Erlang code. A case where this was is no true was already documented in the source code, in relation to opaque types, but this can also be true when it comes to other BEAM languages. --- lib/dialyzer/src/dialyzer.erl | 48 +++++++++++++++-------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl index d4fe064edda..c1bc5ff5973 100644 --- a/lib/dialyzer/src/dialyzer.erl +++ b/lib/dialyzer/src/dialyzer.erl @@ -605,11 +605,9 @@ ordinal(N) when is_integer(N) -> io_lib:format("~wth", [N]). %% Functions that parse type strings, literal strings, and contract %% strings. Return strings formatted by erl_pp. -%% If lib/hipe/cerl/erl_types.erl is compiled with DEBUG=true, -%% the contents of opaque types are showed inside brackets. -%% Since erl_parse:parse_form() cannot handle the bracket syntax, -%% no indentation is done. -%%-define(DEBUG , true). +%% Note we always have to catch any error when trying to parse +%% the syntax because other BEAM languages may not emit an +%% Erlang AST that transforms into valid Erlang Source Code. -define(IND, 10). @@ -620,13 +618,15 @@ con(M, F, Src, I) -> sig(Src, false) -> Src; sig(Src, true) -> - Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])), - {ok, Tokens, _EndLocation} = erl_scan:string(Str), - exec(fun() -> - {ok, {attribute, _, spec, {_MFA, Types}}} = - erl_parse:parse_form(Tokens), - indentation(?IND) ++ pp_spec(Types) - end, Src). + try + Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])), + {ok, Tokens, _EndLocation} = erl_scan:string(Str), + {ok, {attribute, _, spec, {_MFA, Types}}} = + erl_parse:parse_form(Tokens), + indentation(?IND) ++ pp_spec(Types) + catch + _:_ -> Src + end. %% Argument(list)s are a mix of types and Erlang code. Note: sometimes %% (contract_range, call_without_opaque, opaque_type_test), the initial @@ -681,21 +681,15 @@ ts(Src) -> [C1|Src1] = Src, % $< (product) or $( (arglist) [C2|RevSrc2] = lists:reverse(Src1), Src2 = lists:reverse(RevSrc2), - exec(fun() -> - Types = parse_types_and_literals(Src2), - CommaInd = [$, | Ind], - (indentation(?IND-1) ++ - [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++ - [C2]) - end, Src). - --ifdef(DEBUG). -exec(F, R) -> - try F() catch _:_ -> R end. --else. -exec(F, _) -> - F(). --endif. + try + Types = parse_types_and_literals(Src2), + CommaInd = [$, | Ind], + (indentation(?IND-1) ++ + [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++ + [C2]) + catch + _:_ -> Src + end. indentation(I) -> [$\n | lists:duplicate(I, $\s)]. From 4c7bf834f532b682c92c77a4e4fe171002ee9d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Thu, 27 Jun 2019 14:24:33 +0200 Subject: [PATCH 53/73] inets: Return error if URI has no scheme (httpc) This commit fixes a regression and changes httpc to return {error, no_scheme} when the request URI has no scheme e.g. "//foobar". --- lib/inets/src/http_client/httpc.erl | 8 ++++---- lib/inets/test/httpc_SUITE.erl | 13 ++++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index 24a205ced92..9967488f611 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -317,7 +317,7 @@ store_cookies(SetCookieHeaders, Url, Profile) {error, Bad, _} -> {error, {parse_failed, Bad}}; URI -> - Scheme = scheme_to_atom(maps:get(scheme, URI, '')), + Scheme = scheme_to_atom(maps:get(scheme, URI, undefined)), Host = maps:get(host, URI, ""), Port = maps:get(port, URI, default_port(Scheme)), Path = uri_string:recompose(#{path => maps:get(path, URI, "")}), @@ -536,7 +536,7 @@ handle_request(Method, Url, BracketedHost = proplists:get_value(ipv6_host_with_brackets, Options), - Scheme = scheme_to_atom(maps:get(scheme, URI, '')), + Scheme = scheme_to_atom(maps:get(scheme, URI, undefined)), Userinfo = maps:get(userinfo, URI, ""), Host = http_util:maybe_add_brackets(maps:get(host, URI, ""), BracketedHost), Port = maps:get(port, URI, default_port(Scheme)), @@ -591,8 +591,8 @@ scheme_to_atom("http") -> http; scheme_to_atom("https") -> https; -scheme_to_atom('') -> - ''; +scheme_to_atom(undefined) -> + throw({error, {no_scheme}}); scheme_to_atom(Scheme) -> throw({error, {bad_scheme, Scheme}}). diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index d4b33ae2c68..1d37e718473 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -106,7 +106,8 @@ real_requests()-> streaming_error, inet_opts, invalid_headers, - invalid_body + invalid_body, + no_scheme ]. real_requests_esi() -> @@ -1231,6 +1232,16 @@ invalid_body(Config) -> ok end. + +%%------------------------------------------------------------------------- + +no_scheme(_Config) -> + {error,{bad_scheme,"ftp"}} = httpc:request("ftp://foobar"), + {error,{no_scheme}} = httpc:request("//foobar"), + {error,{no_scheme}} = httpc:request("foobar"), + ok. + + %%------------------------------------------------------------------------- remote_socket_close(Config) when is_list(Config) -> URL = url(group_name(Config), "/just_close.html", Config), From 6dd7f3010b360f655691b9f167963dd13ccca8d6 Mon Sep 17 00:00:00 2001 From: Dmitry Poroh Date: Fri, 28 Jun 2019 11:30:09 +0300 Subject: [PATCH 54/73] Infinite cycle fixed on try to change run queue (if it has already changed concurrently) --- erts/emulator/beam/erl_process.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index a60e117babd..1b296320967 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -2346,6 +2346,8 @@ erts_try_change_runq_proc(Process *p, ErtsRunQueue *rq) old_rqint); if (act_rqint == old_rqint) return !0; + + old_rqint = act_rqint; } } From a055766e0ca9d2b4a5007f00b007b087e06bc7a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Wed, 26 Jun 2019 09:26:41 +0200 Subject: [PATCH 55/73] erts: Fix integer overflow in list subtraction CMP_TERM returned an `Sint`, which overflowed the `int` used in erl_rbtree for storing the comparison, causing list subtraction to behave strangely. --- erts/emulator/beam/erl_bif_lists.c | 15 ++++++++++++++- lib/stdlib/test/lists_SUITE.erl | 11 +++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/erts/emulator/beam/erl_bif_lists.c b/erts/emulator/beam/erl_bif_lists.c index aaf262780f7..b69949f9ccf 100644 --- a/erts/emulator/beam/erl_bif_lists.c +++ b/erts/emulator/beam/erl_bif_lists.c @@ -244,12 +244,25 @@ typedef struct { #define ERTS_RBT_GET_LEFT(T) ((T)->left) #define ERTS_RBT_SET_LEFT(T, L) ((T)->left = (L)) #define ERTS_RBT_GET_KEY(T) ((T)->key) -#define ERTS_RBT_CMP_KEYS(KX, KY) CMP_TERM(KX, KY) +#define ERTS_RBT_CMP_KEYS(KX, KY) subtract_term_cmp((KX), (KY)) #define ERTS_RBT_WANT_LOOKUP_INSERT #define ERTS_RBT_WANT_LOOKUP #define ERTS_RBT_WANT_DELETE #define ERTS_RBT_UNDEF +/* erl_rbtree expects comparisons to return an int */ +static int subtract_term_cmp(Eterm a, Eterm b) { + Sint res = CMP_TERM(a, b); + + if (res < 0) { + return -1; + } else if (res > 0) { + return 1; + } + + return 0; +} + #include "erl_rbtree.h" static int subtract_continue(Process *p, ErtsSubtractContext *context); diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl index 984b51e7ae3..9a0fe4b5cad 100644 --- a/lib/stdlib/test/lists_SUITE.erl +++ b/lib/stdlib/test/lists_SUITE.erl @@ -2586,6 +2586,15 @@ subtract(Config) when is_list(Config) -> [1,2,3,4,5,6,7,8,9,9999,10000,20,21,22] = sub(lists:seq(1, 10000)++[20,21,22], lists:seq(10, 9998)), + %% ERL-986; an integer overflow relating to term comparison + %% caused subtraction to be inconsistent. + Ids = [2985095936,47540628,135460048,1266126295,240535295, + 115724671,161800351,4187206564,4178142725,234897063, + 14773162,6662515191,133150693,378034895,1874402262, + 3507611978,22850922,415521280,253360400,71683243], + + [] = id(Ids) -- id(Ids), + %% Floats/integers. [42.0,42.0] = sub([42.0,42,42.0], [42,42,42]), [1,2,3,4,43.0] = sub([1,2,3,4,5,42.0,43.0], [42.0,5]), @@ -2613,6 +2622,8 @@ subtract(Config) when is_list(Config) -> ok. +id(I) -> I. + sub_non_matching(A, B) -> A = sub(A, B). From c14e0eea80911e36fe45839af96bb9593c63bbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Wed, 26 Jun 2019 09:28:28 +0200 Subject: [PATCH 56/73] erts: Fix integer overflow in loader qsort expects the comparison function to return an int; returning an `Sint` may yield nonsensical results. --- erts/emulator/beam/beam_load.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index e61199a8fdb..725b8006f7b 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -4547,7 +4547,15 @@ typedef struct SortGenOpArg { static int genopargtermcompare(SortGenOpArg* a, SortGenOpArg* b) { - return CMP_TERM(a->term, b->term); + Sint res = CMP_TERM(a->term, b->term); + + if (res < 0) { + return -1; + } else if (res > 0) { + return 1; + } + + return 0; } static int From ab61a13a824339d69a4e3955a21be12cb804d960 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 1 Jul 2019 17:00:48 +0200 Subject: [PATCH 57/73] ssl: Enhance error handling Handle the ILLEGAL_PARAMETER alert that may be returned from ssl_alert:decode/3 for gracefull shutdown, try of ...catch will/should not handle this case it is only handles the case that TM should not happen! --- lib/ssl/src/tls_connection.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 7cc2adfda1c..8e850b48a47 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -335,7 +335,9 @@ handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName, handle_alerts(Alerts, {next_state, StateName, State}); [] -> ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, empty_alert), - Version, StateName, State) + Version, StateName, State); + #alert{} = Alert -> + ssl_connection:handle_own_alert(Alert, Version, StateName, State) catch _:_ -> ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error), @@ -1162,7 +1164,6 @@ encode_handshake(Handshake, Version, ConnectionStates0, Hist0) -> encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) -> tls_record:encode_change_cipher_spec(Version, ConnectionStates). --spec decode_alerts(binary()) -> list(). decode_alerts(Bin) -> ssl_alert:decode(Bin). From 41bc2fccb1aa97e34e3cfc349c0b4b5d997b5256 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 2 Jul 2019 13:44:08 +0200 Subject: [PATCH 58/73] Prepare release --- erts/doc/src/notes.xml | 48 ++++++++++++++++++++++++++++++++++ erts/vsn.mk | 2 +- lib/dialyzer/doc/src/notes.xml | 16 ++++++++++++ lib/dialyzer/vsn.mk | 2 +- lib/inets/doc/src/notes.xml | 18 ++++++++++++- lib/inets/vsn.mk | 2 +- lib/ssl/doc/src/notes.xml | 31 ++++++++++++++++++++++ lib/ssl/vsn.mk | 2 +- make/otp_version_tickets | 16 +++++++----- 9 files changed, 126 insertions(+), 11 deletions(-) diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 128def3934a..13208fb7f6a 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,54 @@

This document describes the changes made to the ERTS application.

+
Erts 10.4.4 + +
Fixed Bugs and Malfunctions + + +

+ An invalid value test caused the socket:setopt(Socket, + ip, add_membership, ip_mreq()) to fail with badarg. The + same for drop_membership.

+

+ Own Id: OTP-15908 Aux Id: ERL-980

+
+ +

+ Fixed bug causing VM crash when doing textual dump of a + process containing an unhandled monitor down signal. + Textual process dumps can be done with + erlang:system_info(procs), trace feature + process_dump, Erlang shell break menu and a + crashdump. Bug exist since OTP 21.0.

+

+ Own Id: OTP-15909 Aux Id: ERL-979

+
+ +

lists:subtract/2 would produce incorrect + results for some inputs on 64-bit platforms.

+

+ Own Id: OTP-15938 Aux Id: ERL-986

+
+ +

Fixed a bug in the loader that was similar to + OTP-15938, yielding incorrect code for some inputs + on 64-bit platforms.

+

+ Own Id: OTP-15939

+
+ +

+ Fixed bug causing scheduler threads in rare cases to + block spinnning indefinitely. Bug exists since OTP 21.0.

+

+ Own Id: OTP-15941 Aux Id: PR-2313

+
+
+
+ +
+
Erts 10.4.3
Fixed Bugs and Malfunctions diff --git a/erts/vsn.mk b/erts/vsn.mk index 40a9685e9d3..f06fd085407 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 10.4.3 +VSN = 10.4.4 # Port number 4365 in 4.2 # Port number 4366 in 4.3 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index 0930f79840b..b72453aac7d 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,22 @@

This document describes the changes made to the Dialyzer application.

+
Dialyzer 4.0.2 + +
Fixed Bugs and Malfunctions + + +

Make sure Dialyzer does not crash if the formatting + of results fails. Instead of crashing, an unformatted + version of the results is returned.

+

+ Own Id: OTP-15922 Aux Id: PR-2240, ERL-949

+
+
+
+ +
+
Dialyzer 4.0.1
Fixed Bugs and Malfunctions diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 466bbfd0f23..7a44daf6832 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 4.0.1 +DIALYZER_VSN = 4.0.2 diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 03bd1d80422..45533c4f4b7 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,23 @@ notes.xml -
Inets 7.0.8 +
Inets 7.0.9 + +
Fixed Bugs and Malfunctions + + +

+ Fix a regression in http client that causes a crash when + request URI has no scheme.

+

+ Own Id: OTP-15930 Aux Id: ERL-969

+
+
+
+ +
+ +
Inets 7.0.8
Fixed Bugs and Malfunctions diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 5dbec9e7b39..d9482046187 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 7.0.8 +INETS_VSN = 7.0.9 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 29bf5fc4e73..bb41b7e9eac 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,37 @@

This document describes the changes made to the SSL application.

+
SSL 9.3.4 + +
Fixed Bugs and Malfunctions + + +

+ Fix handling of certificate decoding problems in TLS 1.3 + similarly as in TLS 1.2.

+

+ Own Id: OTP-15900

+
+ +

+ Hibernation now works as expected in all cases, was + accidently broken by optimization efforts.

+

+ Own Id: OTP-15910

+
+ +

+ Fix interoperability problems with openssl when the TLS + 1.3 server is configured wirh the option + signature_algs_cert.

+

+ Own Id: OTP-15913

+
+
+
+ +
+
SSL 9.3.3
Fixed Bugs and Malfunctions diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 01dee392f53..df38aea017b 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.3.3 +SSL_VSN = 9.3.4 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index fd9b36720a6..b741526c88d 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1,6 +1,10 @@ -OTP-15805 -OTP-15819 -OTP-15867 -OTP-15879 -OTP-15887 -OTP-15888 +OTP-15900 +OTP-15908 +OTP-15909 +OTP-15910 +OTP-15913 +OTP-15922 +OTP-15930 +OTP-15938 +OTP-15939 +OTP-15941 From 7999631c63998cffc07bbcc91dd86cbe709dde5f Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 2 Jul 2019 13:44:10 +0200 Subject: [PATCH 59/73] Updated OTP version --- OTP_VERSION | 2 +- otp_versions.table | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OTP_VERSION b/OTP_VERSION index 758704512b5..8869803b66f 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0.4 +22.0.5 diff --git a/otp_versions.table b/otp_versions.table index 956a5968772..43a41780b24 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.0.5 : dialyzer-4.0.2 erts-10.4.4 inets-7.0.9 ssl-9.3.4 # asn1-5.0.9 common_test-1.17.3 compiler-7.4.2 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 jinterface-1.10 kernel-6.4.1 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.4 : erts-10.4.3 kernel-6.4.1 ssl-9.3.3 # asn1-5.0.9 common_test-1.17.3 compiler-7.4.2 crypto-4.5.1 debugger-4.2.7 dialyzer-4.0.1 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.3 : compiler-7.4.2 dialyzer-4.0.1 erts-10.4.2 ssl-9.3.2 stdlib-3.9.2 # asn1-5.0.9 common_test-1.17.3 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.2 : compiler-7.4.1 crypto-4.5.1 erts-10.4.1 stdlib-3.9.1 # asn1-5.0.9 common_test-1.17.3 debugger-4.2.7 dialyzer-4.0 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3.1 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : From 3dd5ab9473f888ceb8f2ae6d71f51cd92de83f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Fri, 28 Jun 2019 08:25:00 +0200 Subject: [PATCH 60/73] beam_ssa_opt: Do not apply tuple_size optimization outside guards Rewriting `tuple_size` to `is_tuple` + `tuple_size` will cause it not to throw an exception, either crashing the compiler or the emulator when the code runs. --- lib/compiler/src/beam_ssa_opt.erl | 66 ++++++++++++++++++------------- lib/compiler/test/match_SUITE.erl | 21 +++++++++- 2 files changed, 58 insertions(+), 29 deletions(-) diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl index 90c0d3cf16e..229edc6a1dd 100644 --- a/lib/compiler/src/beam_ssa_opt.erl +++ b/lib/compiler/src/beam_ssa_opt.erl @@ -904,8 +904,7 @@ cse_suitable(#b_set{}) -> false. }). ssa_opt_float({#st{ssa=Linear0,cnt=Count0}=St, FuncDb}) -> - NonGuards0 = float_non_guards(Linear0), - NonGuards = gb_sets:from_list(NonGuards0), + NonGuards = non_guards(Linear0), Blocks = maps:from_list(Linear0), Fs = #fs{non_guards=NonGuards,bs=Blocks}, {Linear,Count} = float_opt(Linear0, Count0, Fs), @@ -916,15 +915,6 @@ float_blk_is_in_guard(#b_blk{last=#b_br{fail=F}}, #fs{non_guards=NonGuards}) -> float_blk_is_in_guard(#b_blk{}, #fs{}) -> false. -float_non_guards([{L,#b_blk{is=Is}}|Bs]) -> - case Is of - [#b_set{op=landingpad}|_] -> - [L|float_non_guards(Bs)]; - _ -> - float_non_guards(Bs) - end; -float_non_guards([]) -> [?BADARG_BLOCK]. - float_opt([{L,Blk}|Bs0], Count0, Fs) -> case float_blk_is_in_guard(Blk, Fs) of true -> @@ -1774,35 +1764,44 @@ opt_bs_put_split_int_1(Int, L, R) -> %%% ssa_opt_tuple_size({#st{ssa=Linear0,cnt=Count0}=St, FuncDb}) -> - {Linear,Count} = opt_tup_size(Linear0, Count0, []), + %% This optimization is only safe in guards, as prefixing tuple_size with + %% an is_tuple check prevents it from throwing an exception. + NonGuards = non_guards(Linear0), + {Linear,Count} = opt_tup_size(Linear0, NonGuards, Count0, []), {St#st{ssa=Linear,cnt=Count}, FuncDb}. -opt_tup_size([{L,#b_blk{is=Is,last=Last}=Blk}|Bs], Count0, Acc0) -> +opt_tup_size([{L,#b_blk{is=Is,last=Last}=Blk}|Bs], NonGuards, Count0, Acc0) -> case {Is,Last} of {[#b_set{op={bif,'=:='},dst=Bool,args=[#b_var{}=Tup,#b_literal{val=Arity}]}], #b_br{bool=Bool}} when is_integer(Arity), Arity >= 0 -> - {Acc,Count} = opt_tup_size_1(Tup, L, Count0, Acc0), - opt_tup_size(Bs, Count, [{L,Blk}|Acc]); + {Acc,Count} = opt_tup_size_1(Tup, L, NonGuards, Count0, Acc0), + opt_tup_size(Bs, NonGuards, Count, [{L,Blk}|Acc]); {_,_} -> - opt_tup_size(Bs, Count0, [{L,Blk}|Acc0]) + opt_tup_size(Bs, NonGuards, Count0, [{L,Blk}|Acc0]) end; -opt_tup_size([], Count, Acc) -> +opt_tup_size([], _NonGuards, Count, Acc) -> {reverse(Acc),Count}. -opt_tup_size_1(Size, EqL, Count0, [{L,Blk0}|Acc]) -> - case Blk0 of - #b_blk{is=Is0,last=#b_br{bool=Bool,succ=EqL,fail=Fail}} -> - case opt_tup_size_is(Is0, Bool, Size, []) of - none -> +opt_tup_size_1(Size, EqL, NonGuards, Count0, [{L,Blk0}|Acc]) -> + #b_blk{is=Is0,last=Last} = Blk0, + case Last of + #b_br{bool=Bool,succ=EqL,fail=Fail} -> + case gb_sets:is_member(Fail, NonGuards) of + true -> {[{L,Blk0}|Acc],Count0}; - {PreIs,TupleSizeIs,Tuple} -> - opt_tup_size_2(PreIs, TupleSizeIs, L, EqL, - Tuple, Fail, Count0, Acc) + false -> + case opt_tup_size_is(Is0, Bool, Size, []) of + none -> + {[{L,Blk0}|Acc],Count0}; + {PreIs,TupleSizeIs,Tuple} -> + opt_tup_size_2(PreIs, TupleSizeIs, L, EqL, + Tuple, Fail, Count0, Acc) + end end; - #b_blk{} -> + _ -> {[{L,Blk0}|Acc],Count0} end; -opt_tup_size_1(_, _, Count, Acc) -> +opt_tup_size_1(_, _, _, Count, Acc) -> {Acc,Count}. opt_tup_size_2(PreIs, TupleSizeIs, PreL, EqL, Tuple, Fail, Count0, Acc) -> @@ -2241,6 +2240,19 @@ gcd(A, B) -> X -> gcd(B, X) end. +non_guards(Linear) -> + gb_sets:from_list(non_guards_1(Linear)). + +non_guards_1([{L,#b_blk{is=Is}}|Bs]) -> + case Is of + [#b_set{op=landingpad}|_] -> + [L | non_guards_1(Bs)]; + _ -> + non_guards_1(Bs) + end; +non_guards_1([]) -> + [?BADARG_BLOCK]. + rel2fam(S0) -> S1 = sofs:relation(S0), S = sofs:rel2fam(S1), diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index aac9de278d2..bc74ec4984c 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -25,7 +25,8 @@ match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1, selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1, coverage/1,grab_bag/1,literal_binary/1, - unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1]). + unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1, + tuple_size_in_try/1]). -include_lib("common_test/include/ct.hrl"). @@ -41,7 +42,8 @@ groups() -> shortcut_boolean,letify_guard,selectify,deselectify, underscore,match_map,map_vars_used,coverage, grab_bag,literal_binary,unary_op,eq_types, - match_after_return,match_right_tuple]}]. + match_after_return,match_right_tuple, + tuple_size_in_try]}]. init_per_suite(Config) -> @@ -922,4 +924,19 @@ match_right_tuple_1(T) -> force_succ_regs(_A, B) -> B. +tuple_size_in_try(Config) when is_list(Config) -> + %% The tuple_size optimization was applied outside of guards, causing + %% either the emulator or compiler to crash. + ok = tsit(gurka), + ok = tsit(gaffel). + +tsit(A) -> + try + id(ignored), + 1 = tuple_size(A), + error + catch + _:_ -> ok + end. + id(I) -> I. From a8461ffed773c4ff80779c16a3637ba3d2e915fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Wed, 3 Jul 2019 15:07:15 +0200 Subject: [PATCH 61/73] beam_ssa_bsm: Leave ?BADARG_BLOCK alone when cloning fail path --- lib/compiler/src/beam_ssa_bsm.erl | 6 +++++- lib/compiler/test/bs_match_SUITE.erl | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/compiler/src/beam_ssa_bsm.erl b/lib/compiler/src/beam_ssa_bsm.erl index 382e6f635e5..1ac9e6a3bba 100644 --- a/lib/compiler/src/beam_ssa_bsm.erl +++ b/lib/compiler/src/beam_ssa_bsm.erl @@ -683,8 +683,12 @@ aca_copy_successors(Lbl0, Blocks0, Counter0) -> Lbl = maps:get(Lbl0, BRs), {Lbl, Blocks, Counter}. +aca_cs_build_brs([?BADARG_BLOCK=Lbl | Path], Counter, Acc) -> + %% ?BADARG_BLOCK is a marker and not an actual block, so renaming it will + %% break exception handling. + aca_cs_build_brs(Path, Counter, Acc#{ Lbl => Lbl }); aca_cs_build_brs([Lbl | Path], Counter0, Acc) -> - aca_cs_build_brs(Path, Counter0 + 1, maps:put(Lbl, Counter0, Acc)); + aca_cs_build_brs(Path, Counter0 + 1, Acc#{ Lbl => Counter0 }); aca_cs_build_brs([], Counter, Acc) -> {Acc, Counter}. diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index d97f49c56e5..145a50f4ada 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -44,7 +44,8 @@ beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1, expression_before_match/1,erl_689/1,restore_on_call/1, restore_after_catch/1,matches_on_parameter/1,big_positions/1, - matching_meets_apply/1,bs_start_match2_defs/1]). + matching_meets_apply/1,bs_start_match2_defs/1, + exceptions_after_match_failure/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -80,7 +81,8 @@ groups() -> beam_bsm,guard,is_ascii,non_opt_eq, expression_before_match,erl_689,restore_on_call, matches_on_parameter,big_positions, - matching_meets_apply,bs_start_match2_defs]}]. + matching_meets_apply,bs_start_match2_defs, + exceptions_after_match_failure]}]. init_per_suite(Config) -> @@ -2005,4 +2007,17 @@ do_matching_meets_apply(_Bin, {Handler, State}) -> %% Another case of the above. Handler:abs(State). +%% Exception handling was broken on the failure path of bs_start_match as +%% beam_ssa_bsm accidentally cloned and renamed the ?BADARG_BLOCK. +exceptions_after_match_failure(_Config) -> + {'EXIT', {badarith, _}} = (catch do_exceptions_after_match_failure(atom)), + ok = do_exceptions_after_match_failure(<<0, 1, "gurka">>), + ok = do_exceptions_after_match_failure(2.0). + +do_exceptions_after_match_failure(<<_A, _B, "gurka">>) -> + ok; +do_exceptions_after_match_failure(Other) -> + Other / 2.0, + ok. + id(I) -> I. From 8831684baddc575b1e8ea0aedfca72636fcc1332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Fri, 5 Jul 2019 13:02:36 +0200 Subject: [PATCH 62/73] hipe: Disable compilation on encountering try/catch code_SUITE:upgrade would consistently fail in the HiPE case because two clauses were mixed up. Disabling it altogether may seem a bit harsh but we don't have the resources to fix it at the moment. --- lib/hipe/doc/src/hipe_app.xml | 4 +++ lib/hipe/icode/hipe_beam_to_icode.erl | 41 ++++++++++----------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml index 61d92fdffe1..5ac445ac584 100644 --- a/lib/hipe/doc/src/hipe_app.xml +++ b/lib/hipe/doc/src/hipe_app.xml @@ -66,6 +66,10 @@

The HiPE compiler will crash on modules containing binary matching.

+ try/catch +

The HiPE compiler will crash on modules containing 'try' or + 'catch'.

+
Stack traces

Stack traces returned from diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index 8e7e56b6c43..995c961e096 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -557,32 +557,21 @@ trans_fun([{move,Src,Dst}|Instructions], Env) -> Dst1 = mk_var(Dst), Src1 = trans_arg(Src), [hipe_icode:mk_move(Dst1,Src1) | trans_fun(Instructions,Env)]; -%%--- catch --- ITS PROCESSING IS POSTPONED -trans_fun([{'catch',N,{_,EndLabel}}|Instructions], Env) -> - NewContLbl = mk_label(new), - [{'catch',N,EndLabel},NewContLbl | trans_fun(Instructions,Env)]; -%%--- catch_end --- ITS PROCESSING IS POSTPONED -trans_fun([{catch_end,_N}=I|Instructions], Env) -> - [I | trans_fun(Instructions,Env)]; -%%--- try --- ITS PROCESSING IS POSTPONED -trans_fun([{'try',N,{_,EndLabel}}|Instructions], Env) -> - NewContLbl = mk_label(new), - [{'try',N,EndLabel},NewContLbl | trans_fun(Instructions,Env)]; -%%--- try_end --- -trans_fun([{try_end,_N}|Instructions], Env) -> - [hipe_icode:mk_end_try() | trans_fun(Instructions,Env)]; -%%--- try_case --- ITS PROCESSING IS POSTPONED -trans_fun([{try_case,_N}=I|Instructions], Env) -> - [I | trans_fun(Instructions,Env)]; -%%--- try_case_end --- -trans_fun([{try_case_end,Arg}|Instructions], Env) -> - BadArg = trans_arg(Arg), - ErrVar = mk_var(new), - Vs = [mk_var(new)], - Atom = hipe_icode:mk_move(ErrVar,hipe_icode:mk_const(try_clause)), - Tuple = hipe_icode:mk_primop(Vs,mktuple,[ErrVar,BadArg]), - Fail = hipe_icode:mk_fail(Vs,error), - [Atom,Tuple,Fail | trans_fun(Instructions,Env)]; +%% +%% try/catch -- THESE ARE KNOWN TO MISCOMPILE, SEE OTP-15949 +%% +trans_fun([{'catch'=Name,_,_}|_], _Env) -> + nyi(Name); +trans_fun([{catch_end=Name,_}|_], _Env) -> + nyi(Name); +trans_fun([{'try'=Name,_,_}|_], _Env) -> + nyi(Name); +trans_fun([{try_end=Name,_}|_], _Env) -> + nyi(Name); +trans_fun([{try_case=Name,_}|_], _Env) -> + nyi(Name); +trans_fun([{try_case_end=Name,_}|_], _Env) -> + nyi(Name); %%--- raise --- trans_fun([{raise,{f,0},[Reg1,Reg2],{x,0}}|Instructions], Env) -> V1 = trans_arg(Reg1), From 28e6c67f1f099fc9a7f959c1489c2ceb51e3439b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Fri, 5 Jul 2019 14:41:22 +0200 Subject: [PATCH 63/73] dialyzer: Remove native code compilation --- lib/dialyzer/src/dialyzer_cl.erl | 107 ------------------------------- 1 file changed, 107 deletions(-) diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index f887f661bdf..5e680062fb3 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -320,12 +320,6 @@ report_analysis_start(#options{analysis_type = Type, end end. -report_native_comp(#options{report_mode = ReportMode}) -> - case ReportMode of - quiet -> ok; - _ -> io:format(" Compiling some key modules to native code...") - end. - report_elapsed_time(T1, T2, #options{report_mode = ReportMode}) -> case ReportMode of quiet -> ok; @@ -375,7 +369,6 @@ do_analysis(Options) -> do_analysis(Files, Options, Plt, PltInfo) -> assert_writable(Options#options.output_plt), - hipe_compile(Files, Options), report_analysis_start(Options), State0 = new_state(), State1 = init_output(State0, Options), @@ -484,106 +477,6 @@ expand_dependent_modules_1([Mod|Mods], Included, ModDeps) -> expand_dependent_modules_1([], Included, _ModDeps) -> Included. --define(MIN_PARALLELISM, 7). --define(MIN_FILES_FOR_NATIVE_COMPILE, 20). - --spec hipe_compile([file:filename()], #options{}) -> 'ok'. - -hipe_compile(Files, #options{erlang_mode = ErlangMode} = Options) -> - NoNative = (get(dialyzer_options_native) =:= false), - FewFiles = (length(Files) < ?MIN_FILES_FOR_NATIVE_COMPILE), - case NoNative orelse FewFiles orelse ErlangMode of - true -> ok; - false -> - case erlang:system_info(hipe_architecture) of - undefined -> ok; - _ -> - Mods = [lists, dict, digraph, digraph_utils, ets, - gb_sets, gb_trees, ordsets, sets, sofs, - cerl, erl_types, cerl_trees, erl_bif_types, - dialyzer_analysis_callgraph, dialyzer, dialyzer_behaviours, - dialyzer_codeserver, dialyzer_contracts, - dialyzer_coordinator, dialyzer_dataflow, dialyzer_dep, - dialyzer_plt, dialyzer_succ_typings, dialyzer_typesig, - dialyzer_worker], - report_native_comp(Options), - {T1, _} = statistics(wall_clock), - Cache = (get(dialyzer_options_native_cache) =/= false), - native_compile(Mods, Cache), - {T2, _} = statistics(wall_clock), - report_elapsed_time(T1, T2, Options) - end - end. - -native_compile(Mods, Cache) -> - case dialyzer_utils:parallelism() > ?MIN_PARALLELISM of - true -> - Parent = self(), - Pids = [spawn(fun () -> Parent ! {self(), hc(M, Cache)} end) || M <- Mods], - lists:foreach(fun (Pid) -> receive {Pid, Res} -> Res end end, Pids); - false -> - lists:foreach(fun (Mod) -> hc(Mod, Cache) end, Mods) - end. - -hc(Mod, Cache) -> - {module, Mod} = code:ensure_loaded(Mod), - case code:is_module_native(Mod) of - true -> ok; - false -> - %% io:format(" ~w", [Mod]), - case Cache of - false -> - {ok, Mod} = hipe:c(Mod), - ok; - true -> - hc_cache(Mod) - end - end. - -hc_cache(Mod) -> - CacheBase = cache_base_dir(), - %% Use HiPE architecture, version and erts checksum in directory name, - %% to avoid clashes between incompatible binaries. - HipeArchVersion = - lists:concat( - [erlang:system_info(hipe_architecture), "-", - hipe:version(), "-", - hipe:erts_checksum()]), - CacheDir = filename:join(CacheBase, HipeArchVersion), - OrigBeamFile = code:which(Mod), - {ok, {Mod, <>}} = beam_lib:md5(OrigBeamFile), - CachedBeamFile = filename:join(CacheDir, lists:concat([Mod, "-", Checksum, ".beam"])), - ok = filelib:ensure_dir(CachedBeamFile), - ModBin = - case filelib:is_file(CachedBeamFile) of - true -> - {ok, BinFromFile} = file:read_file(CachedBeamFile), - BinFromFile; - false -> - {ok, Mod, CompiledBin} = compile:file(OrigBeamFile, [from_beam, native, binary]), - ok = file:write_file(CachedBeamFile, CompiledBin), - CompiledBin - end, - code:unstick_dir(filename:dirname(OrigBeamFile)), - {module, Mod} = code:load_binary(Mod, CachedBeamFile, ModBin), - true = code:is_module_native(Mod), - ok. - -cache_base_dir() -> - %% http://standards.freedesktop.org/basedir-spec/basedir-spec-0.7.html - %% If XDG_CACHE_HOME is set to an absolute path, use it as base. - XdgCacheHome = os:getenv("XDG_CACHE_HOME"), - CacheHome = - case is_list(XdgCacheHome) andalso filename:pathtype(XdgCacheHome) =:= absolute of - true -> - XdgCacheHome; - false -> - %% Otherwise, the default is $HOME/.cache. - {ok, [[Home]]} = init:get_argument(home), - filename:join(Home, ".cache") - end, - filename:join([CacheHome, "dialyzer_hipe_cache"]). - new_state() -> #cl_state{}. From 91b25395276b2cb2467087133b57fbac795fde97 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 4 Jul 2019 18:05:44 +0200 Subject: [PATCH 64/73] Fix unstable tests process_SUITE:no_priority_inversion{,2} Sometimes processes have not had the time to spread from one scheduler. Force spread by using the undocumented 'scheduler' option. --- erts/emulator/test/process_SUITE.erl | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index a8bcfac84d8..cafab983ad7 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -2394,14 +2394,20 @@ garb_other_running(Config) when is_list(Config) -> no_priority_inversion(Config) when is_list(Config) -> Prio = process_flag(priority, max), - HTLs = lists:map(fun (_) -> + Master = self(), + Executing = make_ref(), + HTLs = lists:map(fun (Sched) -> spawn_opt(fun () -> + Master ! {self(), Executing}, tok_loop() end, - [{priority, high}, monitor, link]) + [{priority, high}, + {scheduler, Sched}, + monitor, + link]) end, - lists:seq(1, 2*erlang:system_info(schedulers))), - receive after 500 -> ok end, + lists:seq(1, erlang:system_info(schedulers_online))), + lists:foreach(fun ({P, _}) -> receive {P,Executing} -> ok end end, HTLs), LTL = spawn_opt(fun () -> tok_loop() end, @@ -2423,14 +2429,19 @@ no_priority_inversion(Config) when is_list(Config) -> no_priority_inversion2(Config) when is_list(Config) -> Prio = process_flag(priority, max), - MTLs = lists:map(fun (_) -> + Master = self(), + Executing = make_ref(), + MTLs = lists:map(fun (Sched) -> spawn_opt(fun () -> + Master ! {self(), Executing}, tok_loop() end, - [{priority, max}, monitor, link]) + [{priority, max}, + {scheduler, Sched}, + monitor, link]) end, - lists:seq(1, 2*erlang:system_info(schedulers))), - receive after 2000 -> ok end, + lists:seq(1, erlang:system_info(schedulers_online))), + lists:foreach(fun ({P, _}) -> receive {P,Executing} -> ok end end, MTLs), {PL, ML} = spawn_opt(fun () -> tok_loop() end, From 1651bd5f6053c73129a38b6df5a8a130d2564e5b Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 4 Jul 2019 20:12:00 +0200 Subject: [PATCH 65/73] Fix unstable node_container_SUITE:node_controller_refc test --- erts/emulator/test/node_container_SUITE.erl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index 8e9e3cb05a4..d77d442ef06 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -583,7 +583,17 @@ node_controller_refc(Config) when is_list(Config) -> wait_until(fun () -> not is_process_alive(P) end), lists:foreach(fun (Proc) -> garbage_collect(Proc) end, processes()), false = get_node_references({Node,Creation}), - false = get_dist_references(Node), + wait_until(fun () -> + case get_dist_references(Node) of + false -> + true; + [{{system,thread_progress_delete_timer}, + [{system,1}]}] -> + false; + Other -> + ct:fail(Other) + end + end), false = lists:member(Node, nodes(known)), nc_refc_check(node()), erts_debug:set_internal_state(node_tab_delayed_delete, -1), %% restore original value From 18a5032e06eebbb6870489bd6d89d495175297ec Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 5 Jul 2019 15:44:46 +0200 Subject: [PATCH 66/73] Fix unstable node_container_SUITE:magic_ref test --- erts/emulator/test/node_container_SUITE.erl | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index d77d442ef06..ad19fb7c085 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -894,7 +894,22 @@ magic_ref(Config) when is_list(Config) -> {'DOWN', Mon, process, Pid, _} -> ok end, - {Addr0, 2, true} = erts_debug:get_internal_state({magic_ref,MRef0}), + MaxTime = erlang:monotonic_time(millisecond) + 1000, + %% The DOWN signal is sent before heap is cleaned up, + %% so we might need to wait some time after the DOWN + %% signal has been received before the heap actually + %% has been cleaned up... + wait_until(fun () -> + case erts_debug:get_internal_state({magic_ref,MRef0}) of + {Addr0, 2, true} -> + true; + {Addr0, 3, true} -> + true = MaxTime >= erlang:monotonic_time(millisecond), + false; + Error -> + ct:fail(Error) + end + end), id(MRef0), id(MRef1), MRefExt = term_to_binary(erts_debug:set_internal_state(make, magic_ref)), From f9648e8f4aab57411c6002815b1fde43185b29c2 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 4 Jul 2019 17:40:16 +0200 Subject: [PATCH 67/73] Fix unstable test dump_SUITE:signal_abort Sometimes processes have not had the time to spread from one scheduler. Force spread by using the undocumented 'scheduler' option. --- erts/emulator/test/dump_SUITE.erl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/erts/emulator/test/dump_SUITE.erl b/erts/emulator/test/dump_SUITE.erl index d0237b78cc7..0aba2b874c7 100644 --- a/erts/emulator/test/dump_SUITE.erl +++ b/erts/emulator/test/dump_SUITE.erl @@ -65,12 +65,14 @@ signal_abort(Config) -> {ok, Node} = start_node(Config), - _P1 = spawn(Node, ?MODULE, load, []), - _P2 = spawn(Node, ?MODULE, load, []), - _P3 = spawn(Node, ?MODULE, load, []), - _P4 = spawn(Node, ?MODULE, load, []), - _P5 = spawn(Node, ?MODULE, load, []), - _P6 = spawn(Node, ?MODULE, load, []), + SO = rpc:call(Node, erlang, system_info, [schedulers_online]), + + _P1 = spawn_opt(Node, ?MODULE, load, [], [{scheduler, (0 rem SO) + 1}]), + _P2 = spawn_opt(Node, ?MODULE, load, [], [{scheduler, (1 rem SO) + 1}]), + _P3 = spawn_opt(Node, ?MODULE, load, [], [{scheduler, (2 rem SO) + 1}]), + _P4 = spawn_opt(Node, ?MODULE, load, [], [{scheduler, (3 rem SO) + 1}]), + _P5 = spawn_opt(Node, ?MODULE, load, [], [{scheduler, (4 rem SO) + 1}]), + _P6 = spawn_opt(Node, ?MODULE, load, [], [{scheduler, (5 rem SO) + 1}]), timer:sleep(500), From e20015186fa2372793650a98005faf88e6f6e0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Mon, 8 Jul 2019 14:37:50 +0200 Subject: [PATCH 68/73] compiler: Fix broken 'receive' in try/catch blocks This fix is rather ugly and tacked-on, but I'm not comfortable refactoring the pass in an emergency patch. --- lib/compiler/src/beam_ssa_pre_codegen.erl | 62 +++++++++++++++++++++-- lib/compiler/test/beam_ssa_SUITE.erl | 26 ++++++++++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index 9af72afca7b..a2e687930bb 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -156,7 +156,9 @@ passes(Opts) -> %% Allocate registers. ?PASS(linear_scan), ?PASS(frame_size), - ?PASS(turn_yregs)], + ?PASS(turn_yregs), + + ?PASS(assert_no_critical_edges)], [P || P <- Ps, P =/= ignore]. function(#b_function{anno=Anno,args=Args,bs=Blocks0,cnt=Count0}=F0, @@ -1321,10 +1323,11 @@ fix_receives_1([{L,Blk}|Ls], Blocks0, Count0) -> LoopExit = find_loop_exit(Rm, Blocks0), Defs0 = beam_ssa:def([L], Blocks0), CommonUsed = recv_common(Defs0, LoopExit, Blocks0), - {Blocks1,Count1} = recv_fix_common(CommonUsed, LoopExit, Rm, - Blocks0, Count0), + {Blocks1,Count1} = recv_crit_edges(Rm, LoopExit, Blocks0, Count0), + {Blocks2,Count2} = recv_fix_common(CommonUsed, LoopExit, Rm, + Blocks1, Count1), Defs = ordsets:subtract(Defs0, CommonUsed), - {Blocks,Count} = fix_receive(Rm, Defs, Blocks1, Count1), + {Blocks,Count} = fix_receive(Rm, Defs, Blocks2, Count2), fix_receives_1(Ls, Blocks, Count); #b_blk{} -> fix_receives_1(Ls, Blocks0, Count0) @@ -1341,6 +1344,57 @@ recv_common(Defs, Exit, Blocks) -> Def = ordsets:subtract(Defs, ExitDefs), ordsets:intersection(Def, ExitUsed). +%% recv_crit_edges([RemoveMessageLabel], LoopExit, +%% Blocks0, Count0) -> {Blocks,Count}. +%% +%% Adds dummy blocks on all conditional jumps to the exit block so that +%% recv_fix_common/5 can insert phi nodes without having to worry about +%% critical edges. + +recv_crit_edges(_Rms, none, Blocks0, Count0) -> + {Blocks0, Count0}; +recv_crit_edges(Rms, Exit, Blocks0, Count0) -> + Ls = beam_ssa:rpo(Rms, Blocks0), + rce_insert_edges(Ls, Exit, Count0, Blocks0). + +rce_insert_edges([L | Ls], Exit, Count0, Blocks0) -> + Successors = beam_ssa:successors(map_get(L, Blocks0)), + case member(Exit, Successors) of + true when Successors =/= [Exit] -> + {Blocks, Count} = rce_insert_edge(L, Exit, Count0, Blocks0), + rce_insert_edges(Ls, Exit, Count, Blocks); + _ -> + rce_insert_edges(Ls, Exit, Count0, Blocks0) + end; +rce_insert_edges([], _Exit, Count, Blocks) -> + {Blocks, Count}. + +rce_insert_edge(L, Exit, Count, Blocks0) -> + #b_blk{last=Last0} = FromBlk0 = map_get(L, Blocks0), + + ToExit = #b_br{bool=#b_literal{val=true},succ=Exit,fail=Exit}, + + FromBlk = FromBlk0#b_blk{last=rce_reroute_terminator(Last0, Exit, Count)}, + EdgeBlk = #b_blk{anno=#{},is=[],last=ToExit}, + + Blocks = Blocks0#{ Count => EdgeBlk, L => FromBlk }, + {Blocks, Count + 1}. + +rce_reroute_terminator(#b_br{succ=Exit}=Last, Exit, New) -> + rce_reroute_terminator(Last#b_br{succ=New}, Exit, New); +rce_reroute_terminator(#b_br{fail=Exit}=Last, Exit, New) -> + rce_reroute_terminator(Last#b_br{fail=New}, Exit, New); +rce_reroute_terminator(#b_br{}=Last, _Exit, _New) -> + Last; +rce_reroute_terminator(#b_switch{fail=Exit}=Last, Exit, New) -> + rce_reroute_terminator(Last#b_switch{fail=New}, Exit, New); +rce_reroute_terminator(#b_switch{list=List0}=Last, Exit, New) -> + List = [if + Lbl =:= Exit -> {Arg, New}; + Lbl =/= Exit -> {Arg, Lbl} + end || {Arg, Lbl} <- List0], + Last#b_switch{list=List}. + %% recv_fix_common([CommonVar], LoopExit, [RemoveMessageLabel], %% Blocks0, Count0) -> {Blocks,Count}. %% Handle variables alwys defined in a receive and used diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index a741ebbdf9b..256bb955596 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -190,6 +190,12 @@ recv(_Config) -> self() ! {[self(),r1],{2,99,<<"data">>}}, {Parent,r1,<<1:32,2:8,99:8,"data">>} = tricky_recv_4(), + %% Test tricky_recv_5/0. + self() ! 1, + a = tricky_recv_5(), + self() ! 2, + b = tricky_recv_5(), + ok. sync_wait_mon({Pid, Ref}, Timeout) -> @@ -295,6 +301,26 @@ tricky_recv_4() -> end, id({Pid,R,Request}). +%% beam_ssa_pre_codegen would accidentally create phi nodes on critical edges +%% when fixing up receives; the call to id/2 can either succeed or land in the +%% catch block, and we added a phi node to its immediate successor. +tricky_recv_5() -> + try + receive + X=1 -> + id(42), + a; + X=2 -> + b + end, + case X of + 1 -> a; + 2 -> b + end + catch + _:_ -> c + end. + maps(_Config) -> {'EXIT',{{badmatch,#{}},_}} = (catch maps_1(any)), ok. From 20e26498ff75c4689a68e11e28016ae5fe44d791 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 9 Jul 2019 09:52:19 +0200 Subject: [PATCH 69/73] Prepare release --- lib/compiler/doc/src/notes.xml | 29 +++++++++++++++++++++++++++++ lib/compiler/vsn.mk | 2 +- lib/dialyzer/doc/src/notes.xml | 20 ++++++++++++++++++++ lib/dialyzer/vsn.mk | 2 +- lib/hipe/doc/src/notes.xml | 20 ++++++++++++++++++++ lib/hipe/vsn.mk | 2 +- lib/ssl/doc/src/notes.xml | 16 ++++++++++++++++ lib/ssl/vsn.mk | 2 +- make/otp_version_tickets | 15 +++++---------- 9 files changed, 94 insertions(+), 14 deletions(-) diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index f0d869381be..209e40c0f5f 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,35 @@

This document describes the changes made to the Compiler application.

+
Compiler 7.4.3 + +
Fixed Bugs and Malfunctions + + +

Fixed an unsafe optimization when matching + tuple_size/1 outside of guards, which could crash + the emulator if the argument was not a tuple.

+

+ Own Id: OTP-15945

+
+ +

Fixed a rare bug that could cause the wrong kind of + exception to be thrown when a BIF failed in a function + that matched bitstrings.

+

+ Own Id: OTP-15946

+
+ +

Fixed a bug where receive statements inside try/catch + blocks could return incorrect results.

+

+ Own Id: OTP-15952

+
+
+
+ +
+
Compiler 7.4.2
Fixed Bugs and Malfunctions diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 508bbc902c0..c76777b191c 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.4.2 +COMPILER_VSN = 7.4.3 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index b72453aac7d..dad9fd18c7b 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,26 @@

This document describes the changes made to the Dialyzer application.

+
Dialyzer 4.0.3 + +
Fixed Bugs and Malfunctions + + +

The HiPE compiler would badly miscompile certain + try/catch expressions, so it will now refuse to compile + modules containing try or catch.

As a consequence + of this, dialyzer will no longer compile key + modules to native code.

+

+ *** POTENTIAL INCOMPATIBILITY ***

+

+ Own Id: OTP-15949

+
+
+
+ +
+
Dialyzer 4.0.2
Fixed Bugs and Malfunctions diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 7a44daf6832..a77c74c717e 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 4.0.2 +DIALYZER_VSN = 4.0.3 diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index a2e0766bb75..3fad2ac53a4 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -31,6 +31,26 @@

This document describes the changes made to HiPE.

+
Hipe 3.19.1 + +
Fixed Bugs and Malfunctions + + +

The HiPE compiler would badly miscompile certain + try/catch expressions, so it will now refuse to compile + modules containing try or catch.

As a consequence + of this, dialyzer will no longer compile key + modules to native code.

+

+ *** POTENTIAL INCOMPATIBILITY ***

+

+ Own Id: OTP-15949

+
+
+
+ +
+
Hipe 3.19
Fixed Bugs and Malfunctions diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index a91d92ca14a..3a22e07f57c 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.19 +HIPE_VSN = 3.19.1 diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index bb41b7e9eac..155bee5eded 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,22 @@

This document describes the changes made to the SSL application.

+
SSL 9.3.5 + +
Improvements and New Features + + +

+ Enhance error handling for erroneous alerts from the + peer.

+

+ Own Id: OTP-15943

+
+
+
+ +
+
SSL 9.3.4
Fixed Bugs and Malfunctions diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index df38aea017b..c9547cae369 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.3.4 +SSL_VSN = 9.3.5 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index b741526c88d..c3caa074a3b 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1,10 +1,5 @@ -OTP-15900 -OTP-15908 -OTP-15909 -OTP-15910 -OTP-15913 -OTP-15922 -OTP-15930 -OTP-15938 -OTP-15939 -OTP-15941 +OTP-15943 +OTP-15945 +OTP-15946 +OTP-15949 +OTP-15952 From fa5e2cae48323a391ff65512a972d6c9f4ba4119 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 9 Jul 2019 09:52:21 +0200 Subject: [PATCH 70/73] Updated OTP version --- OTP_VERSION | 2 +- otp_versions.table | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OTP_VERSION b/OTP_VERSION index 8869803b66f..596d8160fb9 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0.5 +22.0.6 diff --git a/otp_versions.table b/otp_versions.table index 43a41780b24..9cb857480c6 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.0.6 : compiler-7.4.3 dialyzer-4.0.3 hipe-3.19.1 ssl-9.3.5 # asn1-5.0.9 common_test-1.17.3 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 inets-7.0.9 jinterface-1.10 kernel-6.4.1 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.5 : dialyzer-4.0.2 erts-10.4.4 inets-7.0.9 ssl-9.3.4 # asn1-5.0.9 common_test-1.17.3 compiler-7.4.2 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 jinterface-1.10 kernel-6.4.1 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.4 : erts-10.4.3 kernel-6.4.1 ssl-9.3.3 # asn1-5.0.9 common_test-1.17.3 compiler-7.4.2 crypto-4.5.1 debugger-4.2.7 dialyzer-4.0.1 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.3 : compiler-7.4.2 dialyzer-4.0.1 erts-10.4.2 ssl-9.3.2 stdlib-3.9.2 # asn1-5.0.9 common_test-1.17.3 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 kernel-6.4 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : From 9ca0e82455297040069b8274649e7ddd28a5d65b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Wed, 10 Jul 2019 15:41:13 +0200 Subject: [PATCH 71/73] compiler: Fix compiler crash introduced by OTP-15952 An assertion in code generation would fail when the common exit block was ?BADARG_BLOCK, as some operations expect to always "fail" directly to that block (= throw an exception) and we had inserted a dummy block in between. Other operations could also get funny fail labels, jumping to blocks that immediately jumped to {f,0}, but these were all cleaned up by beam_jump, sweeping the bug under the rug. --- lib/compiler/src/beam_ssa_pre_codegen.erl | 6 +++++- lib/compiler/test/beam_ssa_SUITE.erl | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl index a2e687930bb..7ef604d4447 100644 --- a/lib/compiler/src/beam_ssa_pre_codegen.erl +++ b/lib/compiler/src/beam_ssa_pre_codegen.erl @@ -1472,10 +1472,14 @@ find_loop_exit([L1,L2|_Ls], Blocks) -> find_loop_exit_1(Path1, cerl_sets:from_list(Path2)); find_loop_exit(_, _) -> none. +find_loop_exit_1([?BADARG_BLOCK | T], OtherPath) -> + %% ?BADARG_BLOCK is a marker and not an actual block, so we can't consider + %% it to be a common block even if both paths cross it. + find_loop_exit_1(T, OtherPath); find_loop_exit_1([H|T], OtherPath) -> case cerl_sets:is_element(H, OtherPath) of true -> H; - false -> find_loop_exit_1(T, OtherPath) + false -> find_loop_exit_1(T, OtherPath) end; find_loop_exit_1([], _) -> none. diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index 256bb955596..dd1b7ddcd3b 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -196,6 +196,9 @@ recv(_Config) -> self() ! 2, b = tricky_recv_5(), + %% tricky_recv_6/0 is a compile-time error. + tricky_recv_6(), + ok. sync_wait_mon({Pid, Ref}, Timeout) -> @@ -321,6 +324,18 @@ tricky_recv_5() -> _:_ -> c end. +%% When fixing tricky_recv_5, we introduced a compiler crash when the common +%% exit block was ?BADARG_BLOCK and floats were in the picture. +tricky_recv_6() -> + RefA = make_ref(), + RefB = make_ref(), + receive + {RefA, Number} -> Number + 1.0; + {RefB, Number} -> Number + 2.0 + after 0 -> + ok + end. + maps(_Config) -> {'EXIT',{{badmatch,#{}},_}} = (catch maps_1(any)), ok. From 79adc5c28cd0c78af389ff5e8181abf8fbf17844 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 10 Jul 2019 18:05:13 +0200 Subject: [PATCH 72/73] Prepare release --- lib/compiler/doc/src/notes.xml | 15 +++++++++++++++ lib/compiler/vsn.mk | 2 +- make/otp_version_tickets | 6 +----- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index 209e40c0f5f..f11444137d9 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,21 @@

This document describes the changes made to the Compiler application.

+
Compiler 7.4.4 + +
Fixed Bugs and Malfunctions + + +

Fixed a compiler crash introduced in 22.0.6 + (OTP-15952).

+

+ Own Id: OTP-15953 Aux Id: ERL-999

+
+
+
+ +
+
Compiler 7.4.3
Fixed Bugs and Malfunctions diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index c76777b191c..7192ddca154 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.4.3 +COMPILER_VSN = 7.4.4 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index c3caa074a3b..9d97677ff45 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1,5 +1 @@ -OTP-15943 -OTP-15945 -OTP-15946 -OTP-15949 -OTP-15952 +OTP-15953 From 3967d28c05dae77db30b15e56eb4ececf4f1afef Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 10 Jul 2019 18:05:15 +0200 Subject: [PATCH 73/73] Updated OTP version --- OTP_VERSION | 2 +- otp_versions.table | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OTP_VERSION b/OTP_VERSION index 596d8160fb9..84a941394ae 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0.6 +22.0.7 diff --git a/otp_versions.table b/otp_versions.table index 9cb857480c6..022efd3ca03 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-22.0.7 : compiler-7.4.4 # asn1-5.0.9 common_test-1.17.3 crypto-4.5.1 debugger-4.2.7 dialyzer-4.0.3 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19.1 inets-7.0.9 jinterface-1.10 kernel-6.4.1 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 ssl-9.3.5 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.6 : compiler-7.4.3 dialyzer-4.0.3 hipe-3.19.1 ssl-9.3.5 # asn1-5.0.9 common_test-1.17.3 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 erts-10.4.4 et-1.6.4 eunit-2.3.7 ftp-1.0.2 inets-7.0.9 jinterface-1.10 kernel-6.4.1 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.5 : dialyzer-4.0.2 erts-10.4.4 inets-7.0.9 ssl-9.3.4 # asn1-5.0.9 common_test-1.17.3 compiler-7.4.2 crypto-4.5.1 debugger-4.2.7 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 jinterface-1.10 kernel-6.4.1 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 : OTP-22.0.4 : erts-10.4.3 kernel-6.4.1 ssl-9.3.3 # asn1-5.0.9 common_test-1.17.3 compiler-7.4.2 crypto-4.5.1 debugger-4.2.7 dialyzer-4.0.1 diameter-2.2.1 edoc-0.11 eldap-1.2.8 erl_docgen-0.9.1 erl_interface-3.12 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.19 inets-7.0.8 jinterface-1.10 megaco-3.18.5 mnesia-4.16 observer-2.9.1 odbc-2.12.4 os_mon-2.5 parsetools-2.1.8 public_key-1.6.7 reltool-0.8 runtime_tools-1.13.3 sasl-3.4 snmp-5.3 ssh-4.7.7 stdlib-3.9.2 syntax_tools-2.2 tftp-1.0.1 tools-3.2 wx-1.8.8 xmerl-1.3.21 :