From 4df8cf1f67a12d2c730e85ab4de64b6fd7557050 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
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?= <john@erlang.org>
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 <ingela@erlang.org>
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 <ingela@erlang.org>
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 <ingela@erlang.org>
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 <ingela@erlang.org>
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 <ingela@erlang.org>
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 <otp@erlang.org>
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 @@
   </header>
   <p>This document describes the changes made to the SSL application.</p>
 
+<section><title>SSL 9.3.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    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.</p>
+          <p>
+	    Own Id: OTP-15825 Aux Id: ERL-934, OTP-15823 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>SSL 9.3</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 <otp@erlang.org>
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?= <bjorn@erlang.org>
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(<<N:32>>, 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(<<N:32>>, 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(<<N:1>>, 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?= <bjorn@erlang.org>
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, <<A, B>>),
     ?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 <hans@erlang.org>
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?= <bjorn@erlang.org>
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?= <bjorn@erlang.org>
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?= <bjorn@erlang.org>
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?= <john@erlang.org>
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?= <bjorn@erlang.org>
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?= <bjorn@erlang.org>
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?= <bjorn@erlang.org>
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?= <john@erlang.org>
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
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index 9a2412e1f085d5da2ebdc62aaa4e274f297cc9f9..1f7f088a777f183113770950e265356b20655ea9 100644
GIT binary patch
diff --git a/bootstrap/bin/start_clean.boot b/bootstrap/bin/start_clean.boot
index 9a2412e1f085d5da2ebdc62aaa4e274f297cc9f9..1f7f088a777f183113770950e265356b20655ea9 100644
GIT binary patch
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
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
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam b/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam
index afba2693b4861077288a42853f66c49a52b117c2..e59340de4f39147d542a204005e055082ab48f4d 100644
GIT binary patch
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam b/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam
index f3dbfc42ffb2fee72f161d18b1c8fe03ba449feb..f6bd1b7a69c48ff9908329c44024c345e46abd2c 100644
GIT binary patch
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam b/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam
index f7c9c34c9abf7e672868e599545736e4558c8663..3de363dbb673b90349ef8cb82b900297d3bd4fca 100644
GIT binary patch
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_type.beam b/bootstrap/lib/compiler/ebin/beam_ssa_type.beam
index 029de3d4a504bfceea4abda51e2aad4f4a12c421..c13b25bac39ae42e33691b89bc614d72b0dc45ba 100644
GIT binary patch
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
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
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
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index c5ea3ee70f4cd49c2b95ea60e84063dd4817d62e..62838ed7712b2055d4598aaba85d480f2fbe2d61 100644
GIT binary patch
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
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
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
diff --git a/bootstrap/lib/stdlib/ebin/queue.beam b/bootstrap/lib/stdlib/ebin/queue.beam
index 24b85821884f2034343983f4f5cb8a34ef9c47d7..94728e30cc032079133747f334c8730d13b80c1e 100644
GIT binary patch
diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam
index e6d68ea84e4e8b5448a2006355d07c389c24ba75..5d1d66892b856bdf7bb319bb7cdc2f1407b77a79 100644
GIT binary patch

From 8bdcb96c3c33afd7f85fc2953970b6709f04a74a Mon Sep 17 00:00:00 2001
From: Hans Bolinder <hasse@erlang.org>
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 <otp@erlang.org>
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 @@
   </header>
   <p>This document describes the changes made to the ERTS application.</p>
 
+<section><title>Erts 10.4.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>In nested use of <c>try</c>/<c>catch</c>, rethrowing
+	    an exception using <c>erlang:raise/3</c> with a different
+	    class would not always be able to change the class of the
+	    exception.</p>
+          <p>
+	    Own Id: OTP-15834 Aux Id: ERIERL-367 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Erts 10.4</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   <p>This document describes the changes made to the Compiler
     application.</p>
 
+<section><title>Compiler 7.4.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>The type optimization pass of the compiler could hang
+	    or loop for a long time when analyzing a
+	    <c>setelement/3</c> call with a varible position.</p>
+          <p>
+	    Own Id: OTP-15828 Aux Id: ERL-948 </p>
+        </item>
+        <item>
+	    <p>Certain complex receive statements would result in an
+	    internal compiler failure.</p>
+          <p>
+	    Own Id: OTP-15832 Aux Id: ERL-950 </p>
+        </item>
+        <item>
+	    <p>Fixed an unsafe type optimization.</p>
+          <p>
+	    Own Id: OTP-15838</p>
+        </item>
+        <item>
+	    <p>Fixed a crash when optimizing compiler-generated
+	    exceptions (like badmatch) whose offending term was a
+	    constructed binary.</p>
+          <p>
+	    Own Id: OTP-15839 Aux Id: ERL-954 </p>
+        </item>
+        <item>
+	    <p>Fixed a bad optimization related to the <c>++/2</c>
+	    operator, where the compiler assumed that it always
+	    produced a list (<c>[] ++ RHS</c> returns <c>RHS</c>
+	    verbatim, even if it's not a list).</p>
+          <p>
+	    Own Id: OTP-15841</p>
+        </item>
+        <item>
+	    <p>An <c>is_binary/1</c> test followed by
+	    <c>is_bitstring/1</c> (or vice versa) could fail because
+	    of an usafe optimization.</p>
+          <p>
+	    Own Id: OTP-15845</p>
+        </item>
+        <item>
+	    <p>A Core Erlang module where the last clause in a
+	    <c>case</c> matched a map would fail to load.</p>
+          <p>
+	    Own Id: OTP-15846 Aux Id: ERL-955 </p>
+        </item>
+        <item>
+	    <p>Fixed a bug that could cause the compiler to crash
+	    when compiling complex nested case expressions.</p>
+          <p>
+	    Own Id: OTP-15848 Aux Id: ERL-956 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Compiler 7.4</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to the Crypto application.</p>
 
+<section><title>Crypto 4.5.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    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.</p>
+          <p>
+	    Own Id: OTP-15829</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Crypto 4.5</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to the STDLIB application.</p>
 
+<section><title>STDLIB 3.9.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p> Fix a bug that could cause a failure when formatting
+	    binaries using the control sequences <c>p</c> or <c>P</c>
+	    and limiting the output with the option
+	    <c>chars_limit</c>. </p>
+          <p>
+	    Own Id: OTP-15847 Aux Id: ERL-957 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>STDLIB 3.9</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 <otp@erlang.org>
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 <hasse@erlang.org>
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 <sverker@erlang.org>
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 <ingela@erlang.org>
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 <sverker@erlang.org>
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 <ingela@erlang.org>
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 <ingela@erlang.org>
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?= <john@erlang.org>
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 = <<Bin/binary,1:1>>,
+    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?= <john@erlang.org>
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 <sverker@erlang.org>
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 <hasse@erlang.org>
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?= <peterdmv@erlang.org>
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 <otp@erlang.org>
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 @@
   </header>
   <p>This document describes the changes made to the ERTS application.</p>
 
+<section><title>Erts 10.4.2</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    Fixed <c>process_info(Pid,reductions)</c> to not
+	    categorically increase reduction count of the measured
+	    process <c>Pid</c>. 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.</p>
+          <p>
+	    Own Id: OTP-15865 Aux Id: ERL-964 </p>
+        </item>
+        <item>
+	    <p>Fixed an incorrect load-time optimization that could
+	    cause a crash when extracting deeply nested tuple
+	    elements.</p>
+          <p>
+	    Own Id: OTP-15871 Aux Id: ERIERL-374 </p>
+        </item>
+        <item>
+          <p>
+	    Fix bug causing VM crash when pressing P for "proc info"
+	    in Erlang shell break menu. Bug exists since OTP 22.0.</p>
+          <p>
+	    Own Id: OTP-15873 Aux Id: ERL-965 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Erts 10.4.1</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   <p>This document describes the changes made to the Compiler
     application.</p>
 
+<section><title>Compiler 7.4.2</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>Fixed an incorrect type determination for constructed
+	    binaries, which could cause <c>is_binary</c> checks to
+	    succeed when they shouldn't have.</p>
+          <p>
+	    Own Id: OTP-15872</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Compiler 7.4.1</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   <p>This document describes the changes made to the Dialyzer
     application.</p>
 
+<section><title>Dialyzer 4.0.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p> Fix a bug that caused a crash when indenting a
+	    Dialyzer warning mentioning more than one record field.
+	    </p>
+          <p>
+	    Own Id: OTP-15861 Aux Id: ERL-953 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Dialyzer 4.0</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to the SSL application.</p>
 
+<section><title>SSL 9.3.2</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    Returned "alert error string" is now same as logged alert
+	    string</p>
+          <p>
+	    Own Id: OTP-15844</p>
+        </item>
+        <item>
+          <p>
+	    Fix returned extension map fields to follow the
+	    documentation.</p>
+          <p>
+	    Own Id: OTP-15862 Aux Id: ERL-951 </p>
+        </item>
+        <item>
+          <p>
+	    Avoid DTLS crash due to missing gen_server return value
+	    in DTLS packet demux process.</p>
+          <p>
+	    Own Id: OTP-15864 Aux Id: ERL-962 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>SSL 9.3.1</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to the STDLIB application.</p>
 
+<section><title>STDLIB 3.9.2</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p> Fix a bug that could cause a loop when formatting
+	    terms using the control sequences <c>p</c> or <c>P</c>
+	    and limiting the output with the option
+	    <c>chars_limit</c>. </p>
+          <p>
+	    Own Id: OTP-15875 Aux Id: ERL-967 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>STDLIB 3.9.1</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 <otp@erlang.org>
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 <ingela@erlang.org>
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?= <peterdmv@erlang.org>
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),
+    <<?UINT16(SigAlg)>> = <<?BYTE(Hash),?BYTE(Sign)>>,
+    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?= <peterdmv@erlang.org>
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 <rickard@erlang.org>
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?= <peterdmv@erlang.org>
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?= <peterdmv@erlang.org>
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?= <peterdmv@erlang.org>
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 <otp@erlang.org>
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 @@
   </header>
   <p>This document describes the changes made to the ERTS application.</p>
 
+<section><title>Erts 10.4.3</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>Fixed a buffer overflow when
+	    <c>binary_to_existing_atom/2</c> and
+	    <c>list_to_existing_atom/2</c> was used with the
+	    <c>latin1</c> encoding.</p>
+          <p>
+	    Own Id: OTP-15819 Aux Id: ERL-944 </p>
+        </item>
+        <item>
+          <p>
+	    The runtime system disconnected a connection if it
+	    received an <c>exit/2</c> 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.</p>
+          <p>
+	    Own Id: OTP-15867 Aux Id: ERIERL-373 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Erts 10.4.2</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to the Kernel application.</p>
 
+<section><title>Kernel 6.4.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p><c>user</c>/<c>user_drv</c> 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 <c>io:format/2</c>, such as in an
+	    escript.</p>
+          <p>
+	    Own Id: OTP-15805</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Kernel 6.4</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to the SSL application.</p>
 
+<section><title>SSL 9.3.3</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    Correct handshake handling, might cause strange symptoms
+	    such as ASN.1 certificate decoding issues.</p>
+          <p>
+	    Own Id: OTP-15879 Aux Id: ERL-968 </p>
+        </item>
+        <item>
+          <p>
+	    Fix handling of the signature_algorithms_cert extension
+	    in the ClientHello handshake message.</p>
+          <p>
+	    Own Id: OTP-15887 Aux Id: ERL-973 </p>
+        </item>
+        <item>
+          <p>
+	    Handle new ClientHello extensions when handshake is
+	    paused by the {handshake, hello} ssl option.</p>
+          <p>
+	    Own Id: OTP-15888 Aux Id: ERL-975 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>SSL 9.3.2</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 <otp@erlang.org>
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 <bmk@erlang.org>
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 <ingela@erlang.org>
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?= <peterdmv@erlang.org>
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?= <peterdmv@erlang.org>
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 <sverker@erlang.org>
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 <bmk@erlang.org>
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?= <jose.valim@plataformatec.com.br>
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?= <peterdmv@erlang.org>
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 <poroh1981@yandex.ru>
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?= <john@erlang.org>
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?= <john@erlang.org>
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 <ingela@erlang.org>
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 <otp@erlang.org>
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 @@
   </header>
   <p>This document describes the changes made to the ERTS application.</p>
 
+<section><title>Erts 10.4.4</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    An invalid value test caused the socket:setopt(Socket,
+	    ip, add_membership, ip_mreq()) to fail with badarg. The
+	    same for drop_membership.</p>
+          <p>
+	    Own Id: OTP-15908 Aux Id: ERL-980 </p>
+        </item>
+        <item>
+          <p>
+	    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
+	    <c>erlang:system_info(procs)</c>, trace feature
+	    <c>process_dump</c>, Erlang shell break menu and a
+	    crashdump. Bug exist since OTP 21.0.</p>
+          <p>
+	    Own Id: OTP-15909 Aux Id: ERL-979 </p>
+        </item>
+        <item>
+	    <p><c>lists:subtract/2</c> would produce incorrect
+	    results for some inputs on 64-bit platforms.</p>
+          <p>
+	    Own Id: OTP-15938 Aux Id: ERL-986 </p>
+        </item>
+        <item>
+	    <p>Fixed a bug in the loader that was similar to
+	    <c>OTP-15938</c>, yielding incorrect code for some inputs
+	    on 64-bit platforms.</p>
+          <p>
+	    Own Id: OTP-15939</p>
+        </item>
+        <item>
+          <p>
+	    Fixed bug causing scheduler threads in rare cases to
+	    block spinnning indefinitely. Bug exists since OTP 21.0.</p>
+          <p>
+	    Own Id: OTP-15941 Aux Id: PR-2313 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Erts 10.4.3</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   <p>This document describes the changes made to the Dialyzer
     application.</p>
 
+<section><title>Dialyzer 4.0.2</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p> Make sure Dialyzer does not crash if the formatting
+	    of results fails. Instead of crashing, an unformatted
+	    version of the results is returned. </p>
+          <p>
+	    Own Id: OTP-15922 Aux Id: PR-2240, ERL-949 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Dialyzer 4.0.1</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
     <file>notes.xml</file>
   </header>
   
-  <section><title>Inets 7.0.8</title>
+  <section><title>Inets 7.0.9</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    Fix a regression in http client that causes a crash when
+	    request URI has no scheme.</p>
+          <p>
+	    Own Id: OTP-15930 Aux Id: ERL-969 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
+<section><title>Inets 7.0.8</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
       <list>
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 @@
   </header>
   <p>This document describes the changes made to the SSL application.</p>
 
+<section><title>SSL 9.3.4</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+          <p>
+	    Fix handling of certificate decoding problems in TLS 1.3
+	    similarly as in TLS 1.2.</p>
+          <p>
+	    Own Id: OTP-15900</p>
+        </item>
+        <item>
+          <p>
+	    Hibernation now works as expected in all cases, was
+	    accidently broken by optimization efforts.</p>
+          <p>
+	    Own Id: OTP-15910</p>
+        </item>
+        <item>
+          <p>
+	    Fix interoperability problems with openssl when the TLS
+	    1.3 server is configured wirh the option
+	    signature_algs_cert.</p>
+          <p>
+	    Own Id: OTP-15913</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>SSL 9.3.3</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 <otp@erlang.org>
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?= <john@erlang.org>
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?= <john@erlang.org>
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?= <john@erlang.org>
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 @@
       <item><p>The HiPE compiler will crash on modules containing binary
       matching.</p>
       </item>
+      <tag>try/catch</tag>
+      <item><p>The HiPE compiler will crash on modules containing 'try' or
+      'catch'.</p>
+      </item>
 
       <tag>Stack traces</tag>
       <item><p>Stack traces returned from <seealso marker="erts:erlang#get_stacktrace/0">
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?= <john@erlang.org>
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, <<Checksum:128>>}} = 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 <rickard@erlang.org>
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 <rickard@erlang.org>
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 <rickard@erlang.org>
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 <rickard@erlang.org>
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?= <john@erlang.org>
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 <otp@erlang.org>
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 @@
   <p>This document describes the changes made to the Compiler
     application.</p>
 
+<section><title>Compiler 7.4.3</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>Fixed an unsafe optimization when matching
+	    <c>tuple_size/1</c> outside of guards, which could crash
+	    the emulator if the argument was not a tuple.</p>
+          <p>
+	    Own Id: OTP-15945</p>
+        </item>
+        <item>
+	    <p>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.</p>
+          <p>
+	    Own Id: OTP-15946</p>
+        </item>
+        <item>
+	    <p>Fixed a bug where receive statements inside try/catch
+	    blocks could return incorrect results.</p>
+          <p>
+	    Own Id: OTP-15952</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Compiler 7.4.2</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   <p>This document describes the changes made to the Dialyzer
     application.</p>
 
+<section><title>Dialyzer 4.0.3</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>The HiPE compiler would badly miscompile certain
+	    try/catch expressions, so it will now refuse to compile
+	    modules containing try or catch.</p> <p>As a consequence
+	    of this, <c>dialyzer</c> will no longer compile key
+	    modules to native code.</p>
+          <p>
+	    *** POTENTIAL INCOMPATIBILITY ***</p>
+          <p>
+	    Own Id: OTP-15949</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Dialyzer 4.0.2</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to HiPE.</p>
 
+<section><title>Hipe 3.19.1</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>The HiPE compiler would badly miscompile certain
+	    try/catch expressions, so it will now refuse to compile
+	    modules containing try or catch.</p> <p>As a consequence
+	    of this, <c>dialyzer</c> will no longer compile key
+	    modules to native code.</p>
+          <p>
+	    *** POTENTIAL INCOMPATIBILITY ***</p>
+          <p>
+	    Own Id: OTP-15949</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Hipe 3.19</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 @@
   </header>
   <p>This document describes the changes made to the SSL application.</p>
 
+<section><title>SSL 9.3.5</title>
+
+    <section><title>Improvements and New Features</title>
+      <list>
+        <item>
+          <p>
+	    Enhance error handling for erroneous alerts from the
+	    peer.</p>
+          <p>
+	    Own Id: OTP-15943</p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>SSL 9.3.4</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 <otp@erlang.org>
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?= <john@erlang.org>
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 <otp@erlang.org>
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 @@
   <p>This document describes the changes made to the Compiler
     application.</p>
 
+<section><title>Compiler 7.4.4</title>
+
+    <section><title>Fixed Bugs and Malfunctions</title>
+      <list>
+        <item>
+	    <p>Fixed a compiler crash introduced in <c>22.0.6</c>
+	    (OTP-15952).</p>
+          <p>
+	    Own Id: OTP-15953 Aux Id: ERL-999 </p>
+        </item>
+      </list>
+    </section>
+
+</section>
+
 <section><title>Compiler 7.4.3</title>
 
     <section><title>Fixed Bugs and Malfunctions</title>
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 <otp@erlang.org>
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 :
