diff options
95 files changed, 3312 insertions, 718 deletions
diff --git a/OTP_VERSION b/OTP_VERSION index 9664138791..9854364f85 100644 --- a/OTP_VERSION +++ b/OTP_VERSION @@ -1 +1 @@ -22.0-rc3 +23.0-rc0 diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index c0be715678..f88d255296 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -1090,7 +1090,7 @@ typedef struct { </func> <func> - <name since="OTP @OTP-15011@"><ret>int</ret> + <name since="OTP 22.0"><ret>int</ret> <nametext>enif_compare_pids(const ErlNifPid *pid1, const ErlNifPid *pid2) </nametext></name> <fsummary>Compare two pids.</fsummary> @@ -1890,7 +1890,7 @@ enif_inspect_iovec(env, max_elements, term, &tail, &iovec); </func> <func> - <name since="OTP @OTP-15011@"><ret>int</ret> + <name since="OTP 22.0"><ret>int</ret> <nametext>enif_is_pid_undefined(const ErlNifPid* pid)</nametext></name> <fsummary>Determine if pid is undefined.</fsummary> <desc> @@ -2247,7 +2247,7 @@ enif_inspect_iovec(env, max_elements, term, &tail, &iovec); </func> <func> - <name since="OTP @OTP-15362@"><ret>ERL_NIF_TERM</ret> + <name since="OTP 22.0"><ret>ERL_NIF_TERM</ret> <nametext>enif_make_monitor_term(ErlNifEnv* env, const ErlNifMonitor* mon)</nametext></name> <fsummary>Make monitor term from the given monitor identifier.</fsummary> <desc> @@ -3306,7 +3306,7 @@ if (retval & ERL_NIF_SELECT_STOP_CALLED) { </func> <func> - <name since="OTP @OTP-15011@"><ret>void</ret> + <name since="OTP 22.0"><ret>void</ret> <nametext>enif_set_pid_undefined(ErlNifPid* pid)</nametext></name> <fsummary>Set pid as undefined.</fsummary> <desc> @@ -3369,7 +3369,7 @@ if (retval & ERL_NIF_SELECT_STOP_CALLED) { </func> <func> - <name since="OTP @OTP-15640@"><ret>ErlNifTermType</ret> + <name since="OTP 22.0"><ret>ErlNifTermType</ret> <nametext>enif_term_type(ErlNifEnv *env, ERL_NIF_TERM term)</nametext> </name> <fsummary>Determine the type of a term.</fsummary> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 2b444ccf01..a879cce840 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -1297,7 +1297,7 @@ end</code> </func> <func> - <name name="dist_ctrl_get_opt" arity="2" clause_i="1" since="OTP @OTP-15617@"/> + <name name="dist_ctrl_get_opt" arity="2" clause_i="1" since="OTP 22.0"/> <fsummary>Get value of the get_size option on a distribution channel</fsummary> <desc> <p>Returns the value of the <c>get_size</c> option on the distribution channel @@ -1428,7 +1428,7 @@ end</code> </func> <func> - <name name="dist_ctrl_set_opt" arity="3" clause_i="1" since="OTP @OTP-15617@"/> + <name name="dist_ctrl_set_opt" arity="3" clause_i="1" since="OTP 22.0"/> <fsummary>Set value of the get_size option on a distribution channel</fsummary> <desc> <p>Sets the value of the <c>get_size</c> option on the distribution channel diff --git a/erts/doc/src/net.xml b/erts/doc/src/net.xml index b9e2cffce9..6fbc37076c 100644 --- a/erts/doc/src/net.xml +++ b/erts/doc/src/net.xml @@ -29,7 +29,7 @@ <rev></rev> <file>net.xml</file> </header> - <module since="OTP @OTP-14831@">net</module> + <module since="OTP 22.0">net</module> <modulesummary>Network interface.</modulesummary> <description> <p>This module provides an API for the network interface.</p> @@ -72,8 +72,8 @@ </func> <func> - <name name="getnameinfo" arity="1" since="OTP @OTP-14831@"/> - <name name="getnameinfo" arity="2" since="OTP @OTP-14831@"/> + <name name="getnameinfo" arity="1" since="OTP 22.0"/> + <name name="getnameinfo" arity="2" since="OTP 22.0"/> <fsummary>Address-to-name transaltion.</fsummary> <desc> <p>Address-to-name translation in a protocol-independant manner.</p> @@ -84,10 +84,10 @@ </func> <func> - <name name="getaddrinfo" arity="1" since="OTP @OTP-14831@"/> - <name name="getaddrinfo" arity="2" clause_i="1" since="OTP @OTP-14831@"/> - <name name="getaddrinfo" arity="2" clause_i="2" since="OTP @OTP-14831@"/> - <name name="getaddrinfo" arity="2" clause_i="3" since="OTP @OTP-14831@"/> + <name name="getaddrinfo" arity="1" since="OTP 22.0"/> + <name name="getaddrinfo" arity="2" clause_i="1" since="OTP 22.0"/> + <name name="getaddrinfo" arity="2" clause_i="2" since="OTP 22.0"/> + <name name="getaddrinfo" arity="2" clause_i="3" since="OTP 22.0"/> <fsummary>Network address and service transation.</fsummary> <desc> <p>Network address and service translation.</p> @@ -100,7 +100,7 @@ </func> <func> - <name name="if_name2index" arity="1" since="OTP @OTP-14831@"/> + <name name="if_name2index" arity="1" since="OTP 22.0"/> <fsummary>Mappings between network interface names and indexes.</fsummary> <desc> <p>Mappings between network interface names and indexes.</p> @@ -108,7 +108,7 @@ </func> <func> - <name name="if_index2name" arity="1" since="OTP @OTP-14831@"/> + <name name="if_index2name" arity="1" since="OTP 22.0"/> <fsummary>Mappings between network interface index and names.</fsummary> <desc> <p>Mappings between network interface index and names.</p> @@ -116,7 +116,7 @@ </func> <func> - <name name="if_names" arity="0" since="OTP @OTP-14831@"/> + <name name="if_names" arity="0" since="OTP 22.0"/> <fsummary>Get network interface names and indexes.</fsummary> <desc> <p>Get network interface names and indexes.</p> diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index da470b51ec..aad7e27f80 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,507 @@ </header> <p>This document describes the changes made to the ERTS application.</p> +<section><title>Erts 10.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Do not allocate new bitstring/binary when an empty binary + is appended.</p> + <p> + Own Id: OTP-15535 Aux Id: PR-2055 </p> + </item> + <item> + <p> + Document that <c>process_info(_, current_function)</c> + can return <c>{current_function, undefined}</c> in case + of execution of native code.</p> + <p> + Own Id: OTP-15543 Aux Id: PR-2089 </p> + </item> + <item> + <p> + Fixed bug in <c>ets:select</c>, <c>ets:match</c> and + friends which could cause the table to remain fixated (as + if <c>ets:safe_fixtable</c> had been called) after the + call returned. This could happen for <c>protected</c> + tables if another concurrent running process transferred + table ownership to the process during its + ets:select/match call. Ownership can be transferred using + either <c>ets:give_away</c> or the <c>heir</c> table + option.</p> + <p> + Own Id: OTP-15672</p> + </item> + <item> + <p>Fixed a Windows-specific bug in <c>file:list_dir/1</c> + that caused it to misbehave on network shares.</p> + <p> + Own Id: OTP-15693</p> + </item> + <item> + <p> + Fixed bug when calling <c>enif_whereis_*</c> from NIF + resource destructor. Symptoms could be emulator crash or + hanging scheduler threads.</p> + <p> + Own Id: OTP-15694 Aux Id: ERL-863 </p> + </item> + <item> + <p>Fixed a bug in the error case of <c>apply/3</c>, where + the exception would erroneously have an empty argument + list in some cases.</p> + <p> + Own Id: OTP-15698</p> + </item> + <item> + <p>A bug has been fixed in the <c>maps</c> implementation + that could cause a crash or memory usage to grow until + the machine ran out of memory. This could happen when + inserting a new key-value pair with a key <c>K1</c> + containing a binary <c>B1</c> into a map <c>M</c> having + a key <c>K2</c> with a binary <c>B2</c> if the following + conditions were met:</p> <list> <item><c>B1 =/= + B2</c></item> <item><c>size(B1) >= 4294967296</c></item> + <item><c>size(B2) >= 4294967296</c></item> + <item><c>size(M) >= 32</c></item> <item><c>(size(B1) rem + 4294967296) == (size(B2) rem 4294967296)</c></item> + <item>the first <c>(size(B1) rem 4294967296)</c> bytes + are the same both in <c>B1</c> and <c>B2</c></item> + <item>substituting <c>B1</c> in <c>K1</c> with <c>B2</c> + would create a term with the same value as + <c>K2</c></item> </list> <p>The root cause of the problem + is that the <c>maps</c> implementation only hashed the + first <c>(X rem 4294967296)</c> bytes of binaries so that + different binaries could get the same hash value + independently of the hash seed.</p> + <p> + Own Id: OTP-15707</p> + </item> + <item> + <p> + <c>term_to_binary()</c> and distributed sends will now + throw a <c>system_limit</c> exception instead of + producing erroneous results when trying to encode a + binary larger than 4 GB.</p> + <p> + Own Id: OTP-15708</p> + </item> + <item> + <p> + The vxworks configure has been updated to respect the + environment CFLAGS.</p> + <p> + Own Id: OTP-15773</p> + </item> + <item> + <p> + Fix configure to not enable PGO (profile guided + optimizations) when linking of the PGO binary fails. For + instance this happens when there is no gcov lib + installed.</p> + <p> + Own Id: OTP-15788</p> + </item> + <item> + <p> + Fix bug on OpenBSD where sockets using <c>active, + true</c> or <c>active, N</c> could cause the system to + live lock. The bug was introduced in erts-10.2 + (OTP-21.2).</p> + <p> + Own Id: OTP-15791</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add support for Erlang Distribution protocol to split the + payload of large signals into several fragments. This + allows other processes to communicate uninterrupted + during the transmission of these signals.</p> + <p> + Own Id: OTP-13397</p> + </item> + <item> + <p> + A simple socket API is provided through the socket + module. This is a low level API that does *not* replace + gen_[tcp|udp|sctp]. It is intended to *eventually* + replace the inet driver, but not the high level + gen-modules (gen_tcp, gen_udp and gen_sctp). It also + provides a basic API that facilitates the implementation + of other protocols, that is TCP, UDP and SCTP. </p> + <p> + Known issues are; No support for the Windows OS + (currently).</p> + <p> + Own Id: OTP-14831</p> + </item> + <item> + <p>Added NIF functions <seealso + marker="erl_nif#enif_set_pid_undefined"><c>enif_set_pid_undefined</c></seealso>, + <seealso + marker="erl_nif#enif_is_pid_undefined"><c>enif_is_pid_undefined</c></seealso> + and <seealso + marker="erl_nif#enif_compare_pids"><c>enif_compare_pids</c></seealso>.</p> + <p> + Own Id: OTP-15011 Aux Id: PR-2147 </p> + </item> + <item> + <p>Underutilized memory segments (carriers) can now move + between all allocator instances, rather than just between + instances of the same type, which greatly reduces memory + usage in some scenarios. </p> + <p> + Own Id: OTP-15063</p> + </item> + <item> + <p>The emulator will now mark free blocks in pooled + carriers with <c>madvise(2) + MADV_FREE</c> (or similar), + letting the OS reclaim the associated physical memory if + necessary.</p> + <p> + Own Id: OTP-15075</p> + </item> + <item> + <p> + New <c>ERL_NIF_SELECT_CANCEL</c> feature added to + <c>enif_select</c> in order to cancel (or "deselect") a + read or write event on a previously selected file + descriptor.</p> + <p> + Own Id: OTP-15095</p> + </item> + <item> + <p> + ETS option <c>write_concurrency</c> now also affects and + improves the scalability of <c>ordered_set</c> tables. + The implementation is based on a data structure called + contention adapting search tree, where the lock + granularity adapts to the actual amount of concurrency + exploited by the applications in runtime.</p> + <p> + Own Id: OTP-15128</p> + </item> + <item> + <p> + Build configuration of the <c>crypto</c> application has + been moved from the <c>erts</c> application into the + <c>crypto</c> application.</p> + <p> + Own Id: OTP-15129</p> + </item> + <item> + <p>Anonymous functions that don't capture environment are + now created at load-time instead of in run-time.</p> + <p> + Own Id: OTP-15195 Aux Id: PR-1812 </p> + </item> + <item> + <p> + Optimize updates of maps with identical keys and values. + E.g. in the example below the original Map will be reused + as the return of the update.</p> + <p> + 1> Map = #{ a => b }. #{ a => b } 2> Map#{ a := b }.</p> + <p> + Own Id: OTP-15211 Aux Id: PR-1889 </p> + </item> + <item> + <p> + Optimize <c>binary:match/2</c> and + <c>binary:matches/2</c> to use memchr internally.</p> + <p> + Own Id: OTP-15238 Aux Id: PR-1803 </p> + </item> + <item> + <p> + The runtime system used to terminate when a message + larger than 2 Gb was passed over the distribution. The + send operation will now instead throw a + <c>system_limit</c> exception.</p> + <p> + Own Id: OTP-15261</p> + </item> + <item> + <p> + Change the first module called by erts to be named + erl_init instead of otp_ring0. systools in sasl have been + updated to reflect this change.</p> + <p> + Own Id: OTP-15336 Aux Id: PR-1825 </p> + </item> + <item> + <p> + Minor adjustments made to build system for parallel + configure.</p> + <p> + Own Id: OTP-15340 Aux Id: OTP-14625 </p> + </item> + <item> + <p> + Two new NIF interface functions <c>enif_select_read</c> + and <c>enif_select_write</c>. They are similar to + existing <c>enif_select</c> but allow a custom event + message as an argument.</p> + <p> + Own Id: OTP-15349 Aux Id: PR-2084 </p> + </item> + <item> + <p>The embedded copy of <c>zlib</c> has been updated from + <c>1.2.8</c> to <c>1.2.11</c>.</p> + <p>Note that this copy is only used as a fallback when + the target platform doesn't provide any <c>zlib</c> + development libraries. If your system provides + <c>zlib</c> then it will be used even if it is older than + <c>1.2.11</c>.</p> + <p> + Own Id: OTP-15351 Aux Id: ERL-749 </p> + </item> + <item> + <p> + New NIF function <c>enif_make_monitor_term</c>.</p> + <p> + Own Id: OTP-15362 Aux Id: PR-2127 </p> + </item> + <item> + <p>Appending lists (The ++ operator) will now yield + properly on large inputs.</p> + <p> + Own Id: OTP-15427</p> + </item> + <item> + <p>The <c>length/1</c> BIF used to calculate the length + of the list in one go without yielding, even if the list + was very long. In OTP 22, <c>length/1</c> will yield when + called with long lists.</p> + <p> + Own Id: OTP-15439</p> + </item> + <item> + <p> + Processes sending messages are now punished with a + reduction cost based on message size. That is, a process + sending a large message will yield earlier than before.</p> + <p> + Own Id: OTP-15513 Aux Id: ERL-773 </p> + </item> + <item> + <p>The transitory emulator option <c>+ztma true</c> + (introduced in OTP 21.3) has been removed.</p> + <p> + Own Id: OTP-15581 Aux Id: OTP-15580 </p> + </item> + <item> + <p>In OTP 22, HiPE (the native code compiler) is not + fully functional. The reasons for this are:</p> + <p>There are new BEAM instructions for binary matching + that the HiPE native code compiler does not support.</p> + <p>The new optimizations in the Erlang compiler create + new combination of instructions that HiPE currently does + not handle correctly.</p> + <p>If erlc is invoked with the <c>+native</c> option, and + if any of the new binary matching instructions are used, + the compiler will issue a warning and produce a BEAM file + without native code.</p> + <p> + Own Id: OTP-15596</p> + </item> + <item> + <p> + The termination behaviour of processes has changed to + allow processes to yield while sending link exit/monitor + down signals.</p> + <p> + The erl crash dump has been expanded to now also include + processes that are termeinating but have not yet + terminated.</p> + <p> + Own Id: OTP-15610</p> + </item> + <item> + <p> + The dist messages EXIT, EXIT2 and MONITOR_DOWN have been + updated with new versions that send the reason term as + part of the payload of the message instead of as part of + the control message.</p> + <p> + The old versions are still present and can be used when + communicating with nodes that don't support the new + versions.</p> + <p> + Own Id: OTP-15611</p> + </item> + <item> + <p> + When sending messages, exit, exit2 and monitor down + distributed signals, the process sending will now yield + appropriately.</p> + <p> + This means that a terminating process will yield and + possibly be suspended on busy distribution entries while + they are terminating. This means that any memory held by + such processes will not be released until after all + exit/monitor down signals have been sent.</p> + <p> + Own Id: OTP-15612</p> + </item> + <item> + <p> + All external pids/ports/refs created by + erlang:list_to_pid/port/ref debug functions now compare + equal to any other pid/port/ref with the same number from + that node.</p> + <p> + Before this change they compared differently because the + node creation of the pid/port/ref did not compare equal + to any real pid/port/ref creation.</p> + <p> + This will mostly effect pids/ports/refs typed in the + shell.</p> + <p> + Own Id: OTP-15613</p> + </item> + <item> + <p> + The <c>persistent_term</c> functions <c>put/2</c> and + <c>erase/1</c> are now yielding.</p> + <p> + Own Id: OTP-15615</p> + </item> + <item> + <p> + A new <seealso + marker="erlang#dist_ctrl_set_opt/3"><c>erlang:dist_ctrl_set_opt(DHandle, + get_size, Value)</c></seealso> option has been added. + This option makes it possible to configure the + distribution channel identified by <c>DHandle</c> so that + <seealso + marker="erlang#dist_ctrl_get_data/1"><c>erlang:dist_ctrl_get_data(DHandle)</c></seealso> + also returns the size of the data to pass over the + channel.</p> + <p> + Own Id: OTP-15617</p> + </item> + <item> + <p>Previously, all ETS tables used centralized counter + variables to keep track of the number of items stored and + the amount of memory consumed. These counters can cause + scalability problems (especially on big NUMA systems). + This change adds an implementation of a decentralized + counter and modifies the implementation of ETS so that + ETS tables of type <c>ordered_set</c> with + <c>write_concurrency</c> enabled use the decentralized + counter. Experiments indicate that this change + substantially improves the scalability of ETS + <c>ordered_set</c> tables with <c>write_concurrency</c> + enabled in scenarios with frequent <c>ets:insert/2</c> + and <c>ets:delete/2</c> calls.</p> + <p> + Own Id: OTP-15623 Aux Id: PR-2190 </p> + </item> + <item> + <p>The <c>iolist_size/1</c> function is now yielding + which means that an Erlang/OTP system will be responsive + even if the applications running on the system frequently + call <c>iolist_size/1</c> with large iolists.</p> + <p> + Own Id: OTP-15631</p> + </item> + <item> + <p> + A simple test suite for the net module has been added.</p> + <p> + Own Id: OTP-15635</p> + </item> + <item> + <p>Added the NIF function <c>enif_term_type</c>, which + helps avoid long sequences of <c>enif_is_xyz</c> by + returning the type of the given term. This is especially + helpful for NIFs that serialize terms, such as JSON + encoders, where it can improve both performance and + readability.</p> + <p> + Own Id: OTP-15640</p> + </item> + <item> + <p>The last call optimization is now applied to BIFs. + When calling a BIF in the tail position of a function, + the return address and stack frame will now be discarded + before calling the BIF. As a consequence of this change, + the immediate caller of a tail-called BIF will no longer + be available in stack backtraces.</p> + <p> + Own Id: OTP-15674 Aux Id: PR-2177 </p> + </item> + <item> + <p> + Fix GC bug where distributed messages in a processes + mailbox would cause extra GCs. This can be very expensive + if there many messages in the mailbox.</p> + <p> + Own Id: OTP-15703</p> + </item> + <item> + <p>Internal documentation has now been added to the + <em>Erts</em> and <em>Compiler</em> applications.</p> + <p>The internal documents for <em>Erts</em> describe + miscellaneous interesting implementation details. Those + details can change at any time.</p> + <p>The internal documentation for <em>Compiler</em> + documents the API for the Core Erlang modules. While we + will not change those APIs without good reason, we don't + give the same guarantees about backward compatibility as + for the rest of the APIs in OTP.</p> + <p> + Own Id: OTP-15715</p> + </item> + <item> + <p>The performance of non-bignum integer arithmetic has + been improved.</p> + <p> + Own Id: OTP-15740</p> + </item> + <item> + <p> + The <c>-remsh</c> option to <c>erl</c> now automatically + adds the local systems hostname to the target node if no + nodename is given. e.g.</p> + <p> + <c> erl -name foo -remsh bar </c><br/> <c> erl -sname foo + -remsh bar </c></p> + <p> + Own Id: OTP-15794 Aux Id: PR-2219 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.3.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed more bugs in <c>process_info(reductions)</c> + causing it to sometimes behave non-monotonic. That is, a + subsequent call toward the same process could return a + lower reduction value.</p> + <p> + Own Id: OTP-15793 Aux Id: ERIERL-337, OTP-15709 </p> + </item> + </list> + </section> + +</section> + <section><title>Erts 10.3.4</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index f6195a65b2..343b61d4aa 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -29,7 +29,7 @@ <rev></rev> <file>socket.xml</file> </header> - <module since="OTP @OTP-14831@">socket</module> + <module since="OTP 22.0">socket</module> <modulesummary>Socket interface.</modulesummary> <description> <p>This module provides an API for the socket interface. @@ -256,8 +256,8 @@ <funcs> <func> - <name name="accept" arity="1" since="OTP @OTP-14831@"/> - <name name="accept" arity="2" since="OTP @OTP-14831@"/> + <name name="accept" arity="1" since="OTP 22.0"/> + <name name="accept" arity="2" since="OTP 22.0"/> <fsummary>Accept a connection on a socket.</fsummary> <desc> <p>Accept a connection on a socket.</p> @@ -269,7 +269,7 @@ </func> <func> - <name name="bind" arity="2" since="OTP @OTP-14831@"/> + <name name="bind" arity="2" since="OTP 22.0"/> <fsummary>Bind a name to a socket.</fsummary> <desc> <p>Bind a name to a socket.</p> @@ -282,7 +282,7 @@ </func> <func> - <name name="close" arity="1" since="OTP @OTP-14831@"/> + <name name="close" arity="1" since="OTP 22.0"/> <fsummary>Close a socket.</fsummary> <desc> <p>Closes the socket.</p> @@ -301,8 +301,8 @@ </func> <func> - <name name="connect" arity="2" since="OTP @OTP-14831@"/> - <name name="connect" arity="3" since="OTP @OTP-14831@"/> + <name name="connect" arity="2" since="OTP 22.0"/> + <name name="connect" arity="3" since="OTP 22.0"/> <fsummary>Initiate a connection on a socket.</fsummary> <desc> <p>This function connects the socket to the address @@ -311,13 +311,13 @@ </func> <func> - <name name="getopt" arity="3" clause_i="1" since="OTP @OTP-14831@"/> - <name name="getopt" arity="3" clause_i="2" since="OTP @OTP-14831@"/> - <name name="getopt" arity="3" clause_i="3" since="OTP @OTP-14831@"/> - <name name="getopt" arity="3" clause_i="4" since="OTP @OTP-14831@"/> - <name name="getopt" arity="3" clause_i="5" since="OTP @OTP-14831@"/> - <name name="getopt" arity="3" clause_i="6" since="OTP @OTP-14831@"/> - <name name="getopt" arity="3" clause_i="7" since="OTP @OTP-14831@"/> + <name name="getopt" arity="3" clause_i="1" since="OTP 22.0"/> + <name name="getopt" arity="3" clause_i="2" since="OTP 22.0"/> + <name name="getopt" arity="3" clause_i="3" since="OTP 22.0"/> + <name name="getopt" arity="3" clause_i="4" since="OTP 22.0"/> + <name name="getopt" arity="3" clause_i="5" since="OTP 22.0"/> + <name name="getopt" arity="3" clause_i="6" since="OTP 22.0"/> + <name name="getopt" arity="3" clause_i="7" since="OTP 22.0"/> <fsummary>Get an option on a socket.</fsummary> <desc> <p>Get an option on a socket.</p> @@ -337,7 +337,7 @@ </func> <func> - <name name="getopt" arity="3" clause_i="8" since="OTP @OTP-14831@"/> + <name name="getopt" arity="3" clause_i="8" since="OTP 22.0"/> <fsummary>Get an option on a socket.</fsummary> <desc> <p>Get an option on a socket.</p> @@ -359,8 +359,8 @@ </func> <func> - <name name="listen" arity="1" since="OTP @OTP-14831@"/> - <name name="listen" arity="2" since="OTP @OTP-14831@"/> + <name name="listen" arity="1" since="OTP 22.0"/> + <name name="listen" arity="2" since="OTP 22.0"/> <fsummary>Listen for connections on a socket.</fsummary> <desc> <p>Listen for connections on a socket.</p> @@ -368,9 +368,9 @@ </func> <func> - <name name="open" arity="2" since="OTP @OTP-14831@"/> - <name name="open" arity="3" since="OTP @OTP-14831@"/> - <name name="open" arity="4" since="OTP @OTP-14831@"/> + <name name="open" arity="2" since="OTP 22.0"/> + <name name="open" arity="3" since="OTP 22.0"/> + <name name="open" arity="4" since="OTP 22.0"/> <fsummary>Create an endpoint for communication.</fsummary> <desc> <p>Creates an endpoint (socket) for communication.</p> @@ -390,7 +390,7 @@ </func> <func> - <name name="peername" arity="1" since="OTP @OTP-14831@"/> + <name name="peername" arity="1" since="OTP 22.0"/> <fsummary>Get name of connected socket peer.</fsummary> <desc> <p>Returns the address of the peer connected to the socket.</p> @@ -398,11 +398,11 @@ </func> <func> - <name name="recv" arity="1" since="OTP @OTP-14831@"/> - <name name="recv" arity="2" since="OTP @OTP-14831@"/> - <name name="recv" arity="3" clause_i="1" since="OTP @OTP-14831@"/> - <name name="recv" arity="3" clause_i="2" since="OTP @OTP-14831@"/> - <name name="recv" arity="4" since="OTP @OTP-14831@"/> + <name name="recv" arity="1" since="OTP 22.0"/> + <name name="recv" arity="2" since="OTP 22.0"/> + <name name="recv" arity="3" clause_i="1" since="OTP 22.0"/> + <name name="recv" arity="3" clause_i="2" since="OTP 22.0"/> + <name name="recv" arity="4" since="OTP 22.0"/> <fsummary>Receive a message from a socket.</fsummary> <desc> <p>Receive a message from a socket.</p> @@ -413,12 +413,12 @@ </func> <func> - <name name="recvfrom" arity="1" since="OTP @OTP-14831@"/> - <name name="recvfrom" arity="2" since="OTP @OTP-14831@"/> - <name name="recvfrom" arity="3" clause_i="1" since="OTP @OTP-14831@"/> - <name name="recvfrom" arity="3" clause_i="2" since="OTP @OTP-14831@"/> - <name name="recvfrom" arity="3" clause_i="3" since="OTP @OTP-14831@"/> - <name name="recvfrom" arity="4" since="OTP @OTP-14831@"/> + <name name="recvfrom" arity="1" since="OTP 22.0"/> + <name name="recvfrom" arity="2" since="OTP 22.0"/> + <name name="recvfrom" arity="3" clause_i="1" since="OTP 22.0"/> + <name name="recvfrom" arity="3" clause_i="2" since="OTP 22.0"/> + <name name="recvfrom" arity="3" clause_i="3" since="OTP 22.0"/> + <name name="recvfrom" arity="4" since="OTP 22.0"/> <fsummary>Receive a message from a socket.</fsummary> <desc> <p>Receive a message from a socket.</p> @@ -437,12 +437,12 @@ </func> <func> - <name name="recvmsg" arity="1" since="OTP @OTP-14831@"/> - <name name="recvmsg" arity="2" clause_i="1" since="OTP @OTP-14831@"/> - <name name="recvmsg" arity="2" clause_i="2" since="OTP @OTP-14831@"/> - <name name="recvmsg" arity="3" clause_i="1" since="OTP @OTP-14831@"/> - <name name="recvmsg" arity="3" clause_i="2" since="OTP @OTP-14831@"/> - <name name="recvmsg" arity="5" since="OTP @OTP-14831@"/> + <name name="recvmsg" arity="1" since="OTP 22.0"/> + <name name="recvmsg" arity="2" clause_i="1" since="OTP 22.0"/> + <name name="recvmsg" arity="2" clause_i="2" since="OTP 22.0"/> + <name name="recvmsg" arity="3" clause_i="1" since="OTP 22.0"/> + <name name="recvmsg" arity="3" clause_i="2" since="OTP 22.0"/> + <name name="recvmsg" arity="5" since="OTP 22.0"/> <fsummary>Receive a message from a socket.</fsummary> <desc> <p>Receive a message from a socket.</p> @@ -473,10 +473,10 @@ </func> <func> - <name name="send" arity="2" since="OTP @OTP-14831@"/> - <name name="send" arity="3" clause_i="1" since="OTP @OTP-14831@"/> - <name name="send" arity="3" clause_i="2" since="OTP @OTP-14831@"/> - <name name="send" arity="4" since="OTP @OTP-14831@"/> + <name name="send" arity="2" since="OTP 22.0"/> + <name name="send" arity="3" clause_i="1" since="OTP 22.0"/> + <name name="send" arity="3" clause_i="2" since="OTP 22.0"/> + <name name="send" arity="4" since="OTP 22.0"/> <fsummary>Send a message on a socket.</fsummary> <desc> <p>Send a message on a connected socket.</p> @@ -484,10 +484,10 @@ </func> <func> - <name name="sendmsg" arity="2" since="OTP @OTP-14831@"/> - <name name="sendmsg" arity="3" clause_i="1" since="OTP @OTP-14831@"/> - <name name="sendmsg" arity="3" clause_i="2" since="OTP @OTP-14831@"/> - <name name="sendmsg" arity="4" since="OTP @OTP-14831@"/> + <name name="sendmsg" arity="2" since="OTP 22.0"/> + <name name="sendmsg" arity="3" clause_i="1" since="OTP 22.0"/> + <name name="sendmsg" arity="3" clause_i="2" since="OTP 22.0"/> + <name name="sendmsg" arity="4" since="OTP 22.0"/> <fsummary>Send a message on a socket.</fsummary> <desc> <p>Send a message on a socket. The destination, if needed @@ -508,10 +508,10 @@ </func> <func> - <name name="sendto" arity="3" since="OTP @OTP-14831@"/> - <name name="sendto" arity="4" clause_i="1" since="OTP @OTP-14831@"/> - <name name="sendto" arity="4" clause_i="2" since="OTP @OTP-14831@"/> - <name name="sendto" arity="5" since="OTP @OTP-14831@"/> + <name name="sendto" arity="3" since="OTP 22.0"/> + <name name="sendto" arity="4" clause_i="1" since="OTP 22.0"/> + <name name="sendto" arity="4" clause_i="2" since="OTP 22.0"/> + <name name="sendto" arity="5" since="OTP 22.0"/> <fsummary>Send a message on a socket.</fsummary> <desc> <p>Send a message on a socket, to the specified destination.</p> @@ -519,13 +519,13 @@ </func> <func> - <name name="setopt" arity="4" clause_i="1" since="OTP @OTP-14831@"/> - <name name="setopt" arity="4" clause_i="2" since="OTP @OTP-14831@"/> - <name name="setopt" arity="4" clause_i="3" since="OTP @OTP-14831@"/> - <name name="setopt" arity="4" clause_i="4" since="OTP @OTP-14831@"/> - <name name="setopt" arity="4" clause_i="5" since="OTP @OTP-14831@"/> - <name name="setopt" arity="4" clause_i="6" since="OTP @OTP-14831@"/> - <name name="setopt" arity="4" clause_i="7" since="OTP @OTP-14831@"/> + <name name="setopt" arity="4" clause_i="1" since="OTP 22.0"/> + <name name="setopt" arity="4" clause_i="2" since="OTP 22.0"/> + <name name="setopt" arity="4" clause_i="3" since="OTP 22.0"/> + <name name="setopt" arity="4" clause_i="4" since="OTP 22.0"/> + <name name="setopt" arity="4" clause_i="5" since="OTP 22.0"/> + <name name="setopt" arity="4" clause_i="6" since="OTP 22.0"/> + <name name="setopt" arity="4" clause_i="7" since="OTP 22.0"/> <fsummary>Set options on a socket.</fsummary> <desc> <p>Set options on a socket.</p> @@ -548,7 +548,7 @@ </func> <func> - <name name="setopt" arity="4" clause_i="8" since="OTP @OTP-14831@"/> + <name name="setopt" arity="4" clause_i="8" since="OTP 22.0"/> <fsummary>Set options on a socket.</fsummary> <desc> <p>Set options on a socket.</p> @@ -571,7 +571,7 @@ </func> <func> - <name name="shutdown" arity="2" since="OTP @OTP-14831@"/> + <name name="shutdown" arity="2" since="OTP 22.0"/> <fsummary>Shut down part of a full-duplex connection.</fsummary> <desc> <p>Shut down all or part of a full-duplex connection.</p> @@ -579,7 +579,7 @@ </func> <func> - <name name="sockname" arity="1" since="OTP @OTP-14831@"/> + <name name="sockname" arity="1" since="OTP 22.0"/> <fsummary>Get socket name.</fsummary> <desc> <p>Returns the current address to which the socket is bound.</p> @@ -587,25 +587,25 @@ </func> <func> - <name name="supports" arity="0" since="OTP @OTP-14831@"/> - <name name="supports" arity="1" clause_i="1" since="OTP @OTP-14831@"/> - <name name="supports" arity="1" clause_i="2" since="OTP @OTP-14831@"/> - <name name="supports" arity="1" clause_i="3" since="OTP @OTP-14831@"/> - <name name="supports" arity="1" clause_i="4" since="OTP @OTP-14831@"/> - <name name="supports" arity="2" clause_i="1" since="OTP @OTP-14831@"/> - <name name="supports" arity="2" clause_i="2" since="OTP @OTP-14831@"/> - <name name="supports" arity="2" clause_i="3" since="OTP @OTP-14831@"/> - <name name="supports" arity="2" clause_i="4" since="OTP @OTP-14831@"/> - <name name="supports" arity="2" clause_i="5" since="OTP @OTP-14831@"/> - <name name="supports" arity="2" clause_i="6" since="OTP @OTP-14831@"/> - <name name="supports" arity="2" clause_i="7" since="OTP @OTP-14831@"/> - <name name="supports" arity="3" clause_i="1" since="OTP @OTP-14831@"/> - <name name="supports" arity="3" clause_i="2" since="OTP @OTP-14831@"/> - <name name="supports" arity="3" clause_i="3" since="OTP @OTP-14831@"/> - <name name="supports" arity="3" clause_i="4" since="OTP @OTP-14831@"/> - <name name="supports" arity="3" clause_i="5" since="OTP @OTP-14831@"/> - <name name="supports" arity="3" clause_i="6" since="OTP @OTP-14831@"/> - <name name="supports" arity="3" clause_i="7" since="OTP @OTP-14831@"/> + <name name="supports" arity="0" since="OTP 22.0"/> + <name name="supports" arity="1" clause_i="1" since="OTP 22.0"/> + <name name="supports" arity="1" clause_i="2" since="OTP 22.0"/> + <name name="supports" arity="1" clause_i="3" since="OTP 22.0"/> + <name name="supports" arity="1" clause_i="4" since="OTP 22.0"/> + <name name="supports" arity="2" clause_i="1" since="OTP 22.0"/> + <name name="supports" arity="2" clause_i="2" since="OTP 22.0"/> + <name name="supports" arity="2" clause_i="3" since="OTP 22.0"/> + <name name="supports" arity="2" clause_i="4" since="OTP 22.0"/> + <name name="supports" arity="2" clause_i="5" since="OTP 22.0"/> + <name name="supports" arity="2" clause_i="6" since="OTP 22.0"/> + <name name="supports" arity="2" clause_i="7" since="OTP 22.0"/> + <name name="supports" arity="3" clause_i="1" since="OTP 22.0"/> + <name name="supports" arity="3" clause_i="2" since="OTP 22.0"/> + <name name="supports" arity="3" clause_i="3" since="OTP 22.0"/> + <name name="supports" arity="3" clause_i="4" since="OTP 22.0"/> + <name name="supports" arity="3" clause_i="5" since="OTP 22.0"/> + <name name="supports" arity="3" clause_i="6" since="OTP 22.0"/> + <name name="supports" arity="3" clause_i="7" since="OTP 22.0"/> <fsummary>Report info about what the platform supports.</fsummary> <desc> <p>This function intends to retreive information about what the diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c index 59b51fd15e..5a70509ffd 100644 --- a/erts/emulator/beam/atom.c +++ b/erts/emulator/beam/atom.c @@ -200,11 +200,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) { @@ -234,11 +238,11 @@ need_convertion: * 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; @@ -247,13 +251,16 @@ erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) erts_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) { @@ -277,7 +284,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 */ @@ -338,7 +345,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) @@ -348,7 +355,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); @@ -379,23 +386,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 ca920679c6..f51c5a8c62 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/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c index c921b66a7e..09757e473b 100644 --- a/erts/emulator/beam/erl_bif_guard.c +++ b/erts/emulator/beam/erl_bif_guard.c @@ -306,7 +306,7 @@ Eterm erts_trapping_length_1(Process* p, Eterm* args) * We reached the end of the list successfully. Bump reductions * and return result. */ - BUMP_REDS(p, saved_max_iter / 16); + BUMP_REDS(p, (saved_max_iter - max_iter) / 16); return make_small(i); } diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index cc389a093f..c250e8f683 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -69,7 +69,7 @@ * If you're not on the OTP team, you should use a placeholder like * erts-@MyName@ instead. */ -#define ERL_NIF_MIN_ERTS_VERSION "erts-@OTP-15095:OTP-15640@" +#define ERL_NIF_MIN_ERTS_VERSION "erts-10.4" /* * The emulator will refuse to load a nif-lib with a major version diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index 43975d1800..c5abd04e07 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -612,6 +612,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. diff --git a/erts/vsn.mk b/erts/vsn.mk index fafcdf3b28..224570fb09 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 10.3.4 +VSN = 10.4 # Port number 4365 in 4.2 # Port number 4366 in 4.3 diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index 22ca7840de..284a2b4ce5 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -32,6 +32,32 @@ <p>This document describes the changes made to the asn1 application.</p> +<section><title>Asn1 5.0.9</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + <item> + <p>Corrected problems with the following value + definitions:</p> <list> <item>value of SEQUENCE OF CHOICE + with extensions</item> <item>value of CHOICE with + extensions</item> <item>DEFAULT used with OCTET + STRING</item> </list> + <p> + Own Id: OTP-15697 Aux Id: PR-2159 </p> + </item> + </list> + </section> + +</section> + <section><title>Asn1 5.0.8</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index 69f1af28e8..018beda307 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1 +1 @@ -ASN1_VSN = 5.0.8 +ASN1_VSN = 5.0.9 diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml index ff9969ebc3..100be85cac 100644 --- a/lib/common_test/doc/src/ct_hooks.xml +++ b/lib/common_test/doc/src/ct_hooks.xml @@ -109,7 +109,7 @@ </func> <func> - <name since="OTP @OTP-14746@">Module:post_groups(SuiteName, GroupDefs) -> NewGroupDefs</name> + <name since="OTP 21.3.8">Module:post_groups(SuiteName, GroupDefs) -> NewGroupDefs</name> <fsummary>Called after groups/0.</fsummary> <type> <v>SuiteName = atom()</v> @@ -165,7 +165,7 @@ </func> <func> - <name since="OTP @OTP-14746@">Module:post_all(SuiteName, Return, GroupDefs) -> NewReturn</name> + <name since="OTP 21.3.8">Module:post_all(SuiteName, Return, GroupDefs) -> NewReturn</name> <fsummary>Called after all/0.</fsummary> <type> <v>SuiteName = atom()</v> @@ -787,5 +787,3 @@ </funcs> </erlref> - - diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index a68cc3cca7..a64818da7b 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -33,6 +33,95 @@ <file>notes.xml</file> </header> +<section><title>Common_Test 1.17.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Use <c>ssh</c> instead of <c>rsh</c> as the default + remote shell. </p> + <p> + Own Id: OTP-15633 Aux Id: PR-1787 </p> + </item> + </list> + </section> + +</section> + +<section><title>Common_Test 1.17.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The test result when a hook function fails is in general + the same as if the function that the hook is associated + with fails. For example, if <c>post_init_per_testcase</c> + fails the result is that the test case is skipped, as is + the case when <c>init_per_testcase</c> fails.This, + however, was earlier not true for timetrap timeouts or + other error situations where the process running the hook + function was killed. This is now corrected, so the error + handling should be the same no matter how the hook + function fails.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15717 Aux Id: ERIERL-334 </p> + </item> + <item> + <p> + In some rare cases, when two common_test nodes used the + same log directory, a timing problem could occur which + caused common_test to crash because it's log cache file + was unexpectedly empty. This is now corrected.</p> + <p> + Own Id: OTP-15758 Aux Id: ERIERL-342 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Two new common_test hook functions are introduced:</p> + <p> + <c>post_groups/2</c>, which is called after + <c>Suite:groups/0</c><br/> <c>post_all/3</c>, which is + called after <c>Suite:all/0</c></p> + <p> + These functions allow modifying the return values from + the <c>groups/0</c> and <c>all/0</c> functions, + respectively.</p> + <p> + A new term, <c>{testcase,TestCase,RepeatProperties}</c> + is now also allowed in the return from <c>all/0</c>. This + can be used for repeating a single test case a specific + number of times, or until it fails or succeeds once.</p> + <p> + Own Id: OTP-14746 Aux Id: ERIERL-143 </p> + </item> + </list> + </section> + +</section> + <section><title>Common_Test 1.17.1</title> <section><title>Improvements and New Features</title> diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index 14a3622a00..8dcb69c1c6 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1 +1 @@ -COMMON_TEST_VSN = 1.17.1 +COMMON_TEST_VSN = 1.17.3 diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index d45dfef8f3..275c6268fa 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,99 @@ <p>This document describes the changes made to the Compiler application.</p> +<section><title>Compiler 7.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p><c>record_info/2</c> is a pseudo-function that + requires literal arguments known at compile time. + Therefore, the following usage is illegal: <c>fun + record/info/2</c>. The compiler would crash when during + compilation of that kind of code. Corrected to issue a + compilation error.</p> + <p> + Own Id: OTP-15760 Aux Id: ERL-907 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The compiler has been rewritten to internally use an + intermediate representation based on Static Single + Assignment (SSA). The new intermediate representation + makes more optimizations possible.</p> + <p> + Most noticeable is that the binary matching optimizations + are now applicable in many more circumstances than + before.</p> + <p> + Another noticeable change is that type optimizations are + now applied across local function calls, and will remove + a lot more redundant type tests than before.</p> + <p> + Own Id: OTP-14894 Aux Id: ERL-714 </p> + </item> + <item> + <p>Funs are no longer created when they are only used + locally, greatly improving the performance of named funs + and "fun-wrapped" macros.</p> + <p> + Own Id: OTP-15273 Aux Id: ERL-639 </p> + </item> + <item> + <p>All compiler options that can be given in the source + file can now also be given in the option list or from the + command line for <c>erlc</c>.</p> + <p>Specifically, the option + <c>{nowarn_deprecated_function,MFAs}</c> was only + recognized when given in the file with the attribute + <c>-compile()</c>. The option + <c>{nowarn_unused_function,FAs}</c> was incorrectly + documented to only work in a file, but it also worked + when given in the option list.</p> + <p> + Own Id: OTP-15456</p> + </item> + <item> + <p> Do not allow function specifications for functions + residing in other modules. </p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15563 Aux Id: ERL-845, OTP-15562 </p> + </item> + <item> + <p>Internal documentation has now been added to the + <em>Erts</em> and <em>Compiler</em> applications.</p> + <p>The internal documents for <em>Erts</em> describe + miscellaneous interesting implementation details. Those + details can change at any time.</p> + <p>The internal documentation for <em>Compiler</em> + documents the API for the Core Erlang modules. While we + will not change those APIs without good reason, we don't + give the same guarantees about backward compatibility as + for the rest of the APIs in OTP.</p> + <p> + Own Id: OTP-15715</p> + </item> + <item> + <p> There are new compiler options <c>nowarn_removed</c> + and <c>{nowarn_removed,Items}</c> to suppress warnings + for functions and modules that have been removed from + OTP.</p> + <p> + Own Id: OTP-15749 Aux Id: ERL-904 </p> + </item> + </list> + </section> + +</section> + <section><title>Compiler 7.3.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index a523627384..494de072ff 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.3.2 +COMPILER_VSN = 7.4 diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index 195c9d029d..b69657bfa8 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,137 @@ </header> <p>This document describes the changes made to the Crypto application.</p> +<section><title>Crypto 4.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug in error return for <c>crypto:poly1305/2</c>. + It returned the atom <c>notsup</c> instead of the + exception <c>notsup</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15677</p> + </item> + <item> + <p> + The cipher chacha20 was introduced in OpenSSL 1.1.0. + However, it could in a very odd situation, fail for + versions less than OpenSSL 1.1.0d. It is therefore + disabled for those versions.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15678</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> A new <c>rand</c> module algorithm, <c>exro928ss</c> + (Xoroshiro928**), has been implemented. It has got a + really long period and good statistical quality for all + output bits, while still being only about 50% slower than + the default algorithm. </p><p> The same generator is also + used as a long period counter in a new <c>crypto</c> + plugin for the <c>rand</c> module, algorithm + <c>crypto_aes</c>. This plugin uses AES-256 to scramble + the counter which buries any detectable statistical + artifacts. Scrambling is done in chunks which are cached + to get good amortized speed (about half of the default + algorithm). </p> + <p> + Own Id: OTP-14461 Aux Id: PR-1857 </p> + </item> + <item> + <p> + Crypto's single C-file is split into multiple files. The + different coding styles in the different parts are + unified into a single style.</p> + <p> + Own Id: OTP-14732 Aux Id: PR-2068, PR-2095 </p> + </item> + <item> + <p> + Build configuration of the <c>crypto</c> application has + been moved from the <c>erts</c> application into the + <c>crypto</c> application.</p> + <p> + Own Id: OTP-15129</p> + </item> + <item> + <p> + Adds two hash functions <c>blake2b</c> and <c>blake2s</c> + (64 bit hash and 32 bit hash respectively). These are + modern and standard hash functions used in blockchains + and encrypted communication protocols. The hash functions + are available in OpenSSL since version 1.1.1.</p> + <p> + Own Id: OTP-15564 Aux Id: PR-2129 </p> + </item> + <item> + <p> + A new API is implemented in crypto. See the CRYPTO user's + guide, chapter <i>New and Old API</i> for more + information.</p> + <p> + The old api with the <c>crypto:block_*</c> and + <c>crypto:stream_*</c> interfaces are kept for + compatibility, but implemented with the new api. Please + note that since the error checking is more thorough, + there <i>might</i> be arguments with for example faulty + lengths that are no longer accepted.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15644 Aux Id: OTP-14732 , OTP-15451, PR-1857 + , PR-2068, PR-2095 </p> + </item> + <item> + <p> + The new hash_info/1 and cipher_info/1 functions returns + maps with information about the hash or cipher in the + argument.</p> + <p> + Own Id: OTP-15655 Aux Id: PR-2173, ERL-864, PR-2186 </p> + </item> + <item> + <p> + Obey additional OpenSSL configure flags when compiling + the C-part of the CRYPTO application: <c>no-bf</c>, + <c>no-blake2</c>, <c>no-chacha</c>, <c>no-cmac</c>, + <c>no-dh</c>, <c>no-dsa</c>, <c>no-md4</c>, + <c>no-poly1305</c>, <c>no-rc2</c>, <c>no-rc4</c> and + <c>no-rmd160</c>.</p> + <p> + Own Id: OTP-15683</p> + </item> + <item> + <p> + A new function <c>crypto:supports/1</c> is introduced. + The single argument takes an atom as argument: + <c>hashes</c>, <c>public_keys</c>, <c>ciphers</c>, + <c>macs</c>, <c>curves</c> or <c>rsa_opts</c>. The return + value is a list of supported algorithms.</p> + <p> + The difference with the existing <c>crypto:supports/0</c> + is, apart from the argument and the return value, that + the old function reports what is supported by the old + api, and the new function reports algorithms in the new + api.</p> + <p> + Own Id: OTP-15771</p> + </item> + </list> + </section> + +</section> + <section><title>Crypto 4.4.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index 0a3d9f45e4..72a51bfec9 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 4.4.2 +CRYPTO_VSN = 4.5 diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml index 395b69973d..795b46d467 100644 --- a/lib/debugger/doc/src/notes.xml +++ b/lib/debugger/doc/src/notes.xml @@ -33,6 +33,23 @@ <p>This document describes the changes made to the Debugger application.</p> +<section><title>Debugger 4.2.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + <section><title>Debugger 4.2.6</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk index a3cbb497f8..daecc7594c 100644 --- a/lib/debugger/vsn.mk +++ b/lib/debugger/vsn.mk @@ -1 +1 @@ -DEBUGGER_VSN = 4.2.6 +DEBUGGER_VSN = 4.2.7 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index bc422c43a0..dd0a2bfd7d 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,52 @@ <p>This document describes the changes made to the Dialyzer application.</p> +<section><title>Dialyzer 4.0</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> By default Dialyzer inserts line breaks in types, + contracts, and Erlang Code when formatting results. Use + the new <c>--no_indentation</c> option to get the old + behavior of not inserting line breaks. </p> + <p> + Own Id: OTP-15135</p> + </item> + <item> + <p> Use bit syntax in warnings instead of Core Erlang + syntax, for readability. </p> + <p> + Own Id: OTP-15752</p> + </item> + <item> + <p> The format of the raw analysis result tagged with + <c>fun_app_args</c> is changed to <c>{fun_app_args, + [ArgNs, Args, Type]}</c>. </p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15779</p> + </item> + </list> + </section> + +</section> + <section><title>Dialyzer 3.3.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 7221993963..95984c7c85 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 3.3.2 +DIALYZER_VSN = 4.0 diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml index 145856bcaa..48bc5d9c74 100644 --- a/lib/edoc/doc/src/notes.xml +++ b/lib/edoc/doc/src/notes.xml @@ -32,6 +32,20 @@ <p>This document describes the changes made to the EDoc application.</p> +<section><title>Edoc 0.11</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Correct links in the documentation. </p> + <p> + Own Id: OTP-15761</p> + </item> + </list> + </section> + +</section> + <section><title>Edoc 0.10</title> <section><title>Improvements and New Features</title> diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk index b6e1422623..3510fdfccf 100644 --- a/lib/edoc/vsn.mk +++ b/lib/edoc/vsn.mk @@ -1 +1 @@ -EDOC_VSN = 0.10 +EDOC_VSN = 0.11 diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml index bf9358c4d1..946db5b93d 100644 --- a/lib/eldap/doc/src/notes.xml +++ b/lib/eldap/doc/src/notes.xml @@ -31,6 +31,42 @@ </header> <p>This document describes the changes made to the Eldap application.</p> +<section><title>Eldap 1.2.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix dialyzer warnings in eldap when not matching the + return value of ssl:close/1.</p> + <p> + Own Id: OTP-15775</p> + </item> + </list> + </section> + +</section> + +<section><title>Eldap 1.2.7</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Back port of bug fix ERL-893 from OTP-22 and document + enhancements that will solve dialyzer warnings for users + of the ssl application.</p> + <p> + This change also affects public_key, eldap (and inet + doc).</p> + <p> + Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215 </p> + </item> + </list> + </section> + +</section> + <section><title>Eldap 1.2.6</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk index 6d541e4689..8f969e6945 100644 --- a/lib/eldap/vsn.mk +++ b/lib/eldap/vsn.mk @@ -1 +1 @@ -ELDAP_VSN = 1.2.6 +ELDAP_VSN = 1.2.8 diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml index 54f0a36b27..f25361a202 100644 --- a/lib/erl_docgen/doc/src/notes.xml +++ b/lib/erl_docgen/doc/src/notes.xml @@ -31,7 +31,24 @@ </header> <p>This document describes the changes made to the <em>erl_docgen</em> application.</p> - <section><title>Erl_Docgen 0.9</title> + <section><title>Erl_Docgen 0.9.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Docgen 0.9</title> <section><title>Improvements and New Features</title> <list> diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk index 6321f229dd..fece2456c1 100644 --- a/lib/erl_docgen/vsn.mk +++ b/lib/erl_docgen/vsn.mk @@ -1 +1 @@ -ERL_DOCGEN_VSN = 0.9 +ERL_DOCGEN_VSN = 0.9.1 diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml index 7808bfd94f..70af5642da 100644 --- a/lib/erl_interface/doc/src/ei.xml +++ b/lib/erl_interface/doc/src/ei.xml @@ -183,7 +183,7 @@ typedef enum { </func> <func> - <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name> + <name since="OTP 22.0"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name> <fsummary>Decode a bitstring.</fsummary> <desc> <p>Decodes a bit string from the binary format.</p> @@ -498,9 +498,9 @@ typedef enum { </func> <func> - <name since="OTP @OTP-15712@"><ret>int</ret> + <name since="OTP 22.0"><ret>int</ret> <nametext>ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits)</nametext></name> - <name since="OTP @OTP-15712@"><ret>int</ret> + <name since="OTP 22.0"><ret>int</ret> <nametext>ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits)</nametext></name> <fsummary>Encode a bitstring.</fsummary> <desc> @@ -849,30 +849,48 @@ ei_encode_tuple_header(buf, &i, 0);</pre> </type> <desc> <marker id="ei_set_compat_rel"></marker> - <p>By default, the <c>ei</c> library is only guaranteed - to be compatible with other Erlang/OTP components from the same - release as the <c>ei</c> library itself. For example, - <c>ei</c> from - Erlang/OTP R10 is not compatible with an Erlang emulator - from Erlang/OTP R9 by default.</p> - <p>A call to <c>ei_set_compat_rel(release_number)</c> sets - the <c>ei</c> library in compatibility mode of release - <c>release_number</c>. Valid range of - <c>release_number</c> - is <c>[7, current release]</c>. This makes it possible to - communicate with Erlang/OTP components from earlier releases.</p> + <p>In general, the <c>ei</c> library is guaranteed + to be compatible with other Erlang/OTP components that are 2 major + releases older or newer than the <c>ei</c> library itself.</p> + <p>Sometimes an exception to the above rule has to be made to make new + features (or even bug fixes) possible. A call to + <c>ei_set_compat_rel(release_number)</c> sets + the <c>ei</c> library in compatibility mode of OTP release + <c>release_number</c>.</p> + <p>The only useful value for <c>release_number</c> is currently + <c>21</c>. This will only be useful and have an effect if <em>bit + strings</em> or <em>export funs</em> are received from a connected + node. Before OTP 22, bit strings and export funs were not supported by + <c>ei</c>. They were instead encoded using an undocumented fallback + tuple format when sent from the emulator to <c>ei</c>:</p> + <taglist> + <tag><c>Bit string</c></tag> + <item><p>The term <c><<42, 1:1>></c> was encoded as + <c>{<<42, 128>>, 1}</c>. The first element of the tuple is a + binary and the second element denotes how many bits of the last bytes + are part of the bit string. In this example only the most significant + bit of the last byte (128) is part of the bit string.</p> + </item> + <tag><c>Export fun</c></tag> + <item><p>The term <c>fun lists:map/2</c> was encoded as + <c>{lists,map}</c>. A tuple with the module, function and a missing + arity.</p> + </item> + </taglist> + <p>If <c>ei_set_compat_rel(21)</c> is <em>not</em> called then a connected + emulator will send bit strings and export funs correctly encoded. The + functions <seealso marker="#ei_decode_bitstring"><c>ei_decode_bitstring</c></seealso> + and <seealso marker="#ei_decode_fun"><c>ei_decode_fun</c></seealso> + has to be used to decode such terms. Calling + <c>ei_set_compat_rel(21)</c> should only be done as a workaround to + keep an old implementation alive, which expects to receive the + undocumented tuple formats for bit strings and/or export funs. + </p> <note> <p>If this function is called, it can only be called once and must be called before any other functions in the <c>ei</c> library are called.</p> </note> - <warning> - <p>You can run into trouble if this feature is used - carelessly. Always ensure that all communicating - components are either from the same Erlang/OTP release, or - from release X and release Y where all components - from release Y are in compatibility mode of release X.</p> - </warning> </desc> </func> diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml index fc6a1bb548..c47f0d2bd1 100644 --- a/lib/erl_interface/doc/src/notes.xml +++ b/lib/erl_interface/doc/src/notes.xml @@ -31,6 +31,148 @@ </header> <p>This document describes the changes made to the Erl_interface application.</p> +<section><title>Erl_Interface 3.12</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The vxworks configure has been updated to respect the + environment CFLAGS.</p> + <p> + Own Id: OTP-15773</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor adjustments made to build system for parallel + configure.</p> + <p> + Own Id: OTP-15340 Aux Id: OTP-14625 </p> + </item> + <item> + <p> + The limited support for VxWorks is deprecated as of OTP + 22, and will be removed in OTP 23.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15621</p> + </item> + <item> + <p>The old legacy <c>erl_interface</c> library (functions + with prefix <c>erl_</c>) is deprecated as of OTP 22, and + will be removed in OTP 23. This does not apply to the + <c>ei</c> library. Reasonably new <c>gcc</c> compilers + will issue deprecation warnings. In order to disable + these warnings, define the macro + <c>EI_NO_DEPR_WARN</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15622</p> + </item> + <item> + <p>Added support to receive, decode, encode and send both + bit strings and export funs (<c>fun M:F/A</c>).</p> + <p>New functions <c>ei_decode_bitstring</c> and + <c>ei_encode_bitstring</c> have been added in order to + decode and encode bit strings where the number of bits is + not necessary divisible by 8 (a whole number of bytes). + The existing functions <c>ei_decode_fun</c> and + <c>ei_encode_fun</c> can now also handle export funs.</p> + <p>Before this change, bit strings and export funs sent + to an erl_interface c-node were encoded using an + undocumented fallback tuple format. For bit strings + <c>{Binary,BitsInLastByte}</c> and for export funs + <c>{M,F}</c>. Existing c-node implementations expecting + these tuples must be changed to instead use + <c>ei_decode_bitstring</c> and <c>ei_decode_fun</c>. As a + temporary solution you can also build erl_interface with + macro <c>EI_COMPAT=21</c> or call + <c>ei_set_compat_rel(21)</c> to receive the old fallback + tuples.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15712 Aux Id: OTP-15774 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.11.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + <c>erl_interface</c>/<c>ei</c> refused to use node names + with an alive name (the part of the node name preceding + the @ sign) longer than 63 characters and a host name + longer than 64 characters. The total amount of characters + allowed in a node name (alivename@hostname) was thus + limited to 128 characters. These limits applied both to + the own node name as well as node names of other nodes. + Ordinary Erlang nodes limit the node name length to 256 + characters, which meant that you could not communicate + with certain Erlang nodes due to their node name used.</p> + <p> + <c>erl_interface</c>/<c>ei</c> now allow the total amount + of characters in a node name to be up to 256 characters. + These characters may be distributed between alive name + and host name in whatever way needed. That is, the + maximum amount of characters in the alive name may be 254 + and the maximum amount of characters in the host name may + be 254, but in total the node name must not exceed 256 + characters.</p> + <p> + Own Id: OTP-15781 Aux Id: ERIERL-356 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.11.2.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + <c>erl_interface</c>/<c>ei</c> refused to use node names + with an alive name (the part of the node name preceding + the @ sign) longer than 63 characters and a host name + longer than 64 characters. The total amount of characters + allowed in a node name (alivename@hostname) was thus + limited to 128 characters. These limits applied both to + the own node name as well as node names of other nodes. + Ordinary Erlang nodes limit the node name length to 256 + characters, which meant that you could not communicate + with certain Erlang nodes due to their node name used.</p> + <p> + <c>erl_interface</c>/<c>ei</c> now allow the total amount + of characters in a node name to be up to 256 characters. + These characters may be distributed between alive name + and host name in whatever way needed. That is, the + maximum amount of characters in the alive name may be 254 + and the maximum amount of characters in the host name may + be 254, but in total the node name must not exceed 256 + characters.</p> + <p> + Own Id: OTP-15781 Aux Id: ERIERL-356 </p> + </item> + </list> + </section> + +</section> + <section><title>Erl_Interface 3.11.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk index 5e63f75ab5..cc72ed639a 100644 --- a/lib/erl_interface/vsn.mk +++ b/lib/erl_interface/vsn.mk @@ -1,2 +1,2 @@ -EI_VSN = 3.11.2 +EI_VSN = 3.12 ERL_INTERFACE_VSN = $(EI_VSN) diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index 9a803cb9df..a2e0766bb7 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -31,6 +31,52 @@ </header> <p>This document describes the changes made to HiPE.</p> +<section><title>Hipe 3.19</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add function <c>hipe:erllvm_is_supported</c> to check for + the presences of a suitable version of the LLVM tool + chain as well as supported hardware architecture. The old + <c>hipe:llvm_support_available</c> has been removed.</p> + <p> + Own Id: OTP-15385 Aux Id: PR-1986 </p> + </item> + <item> + <p> + Fix hipe LLVM for FreeBSD and other non-linux unix to use + /tmp/ instead of /dev/shm/.</p> + <p> + Own Id: OTP-15386 Aux Id: PR-1963 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>In OTP 22, HiPE (the native code compiler) is not + fully functional. The reasons for this are:</p> + <p>There are new BEAM instructions for binary matching + that the HiPE native code compiler does not support.</p> + <p>The new optimizations in the Erlang compiler create + new combination of instructions that HiPE currently does + not handle correctly.</p> + <p>If erlc is invoked with the <c>+native</c> option, and + if any of the new binary matching instructions are used, + the compiler will issue a warning and produce a BEAM file + without native code.</p> + <p> + Own Id: OTP-15596</p> + </item> + </list> + </section> + +</section> + <section><title>Hipe 3.18.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index 39565d721f..a91d92ca14 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.18.3 +HIPE_VSN = 3.19 diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 2710ea2f2f..03bd1d8042 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,24 @@ <file>notes.xml</file> </header> - <section><title>Inets 7.0.7</title> + <section><title>Inets 7.0.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 7.0.7</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index fd248e793a..5dbec9e7b3 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 7.0.7 +INETS_VSN = 7.0.8 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml index e4bfddcd17..e79ada47f1 100644 --- a/lib/jinterface/doc/src/notes.xml +++ b/lib/jinterface/doc/src/notes.xml @@ -31,6 +31,42 @@ </header> <p>This document describes the changes made to the Jinterface application.</p> +<section><title>Jinterface 1.10</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Added support to receive export funs (<c>fun + M:F/A</c>).</p> + <p>Before this change, export funs sent to a jinterface + node were encoded using an undocumented fallback tuple + format <c>{M,F}</c>. Existing jinterface implementations + expecting these tuples must be changed to instead use the + existing <c>OtpErlangExternalFun</c> class.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15774 Aux Id: OTP-15712 </p> + </item> + </list> + </section> + +</section> + <section><title>Jinterface 1.9.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk index a8dc815145..95c7c95726 100644 --- a/lib/jinterface/vsn.mk +++ b/lib/jinterface/vsn.mk @@ -1 +1 @@ -JINTERFACE_VSN = 1.9.1 +JINTERFACE_VSN = 1.10 diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 61bd598145..6f68a67174 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,104 @@ </header> <p>This document describes the changes made to the Kernel application.</p> +<section><title>Kernel 6.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix so that when multiple <c>-sname</c> or <c>-name</c> + are given to <c>erl</c> the first one is chosen. Before + this fix distribution was not started at all when + multiple name options were given.</p> + <p> + Own Id: OTP-15786 Aux Id: ERL-918 </p> + </item> + <item> + <p> + Fix <c>inet_res</c> configuration pointing to + non-existing files to work again. This was broken in + KERNEL-6.3 (OTP-21.3).</p> + <p> + Own Id: OTP-15806</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A simple socket API is provided through the socket + module. This is a low level API that does *not* replace + gen_[tcp|udp|sctp]. It is intended to *eventually* + replace the inet driver, but not the high level + gen-modules (gen_tcp, gen_udp and gen_sctp). It also + provides a basic API that facilitates the implementation + of other protocols, that is TCP, UDP and SCTP. </p> + <p> + Known issues are; No support for the Windows OS + (currently).</p> + <p> + Own Id: OTP-14831</p> + </item> + <item> + <p> + Improved the documentation for the linger option.</p> + <p> + Own Id: OTP-15491 Aux Id: PR-2019 </p> + </item> + <item> + <p> Global no longer tries more than once when connecting + to other nodes. </p> + <p> + Own Id: OTP-15607 Aux Id: ERIERL-280 </p> + </item> + <item> + <p> + The dist messages EXIT, EXIT2 and MONITOR_DOWN have been + updated with new versions that send the reason term as + part of the payload of the message instead of as part of + the control message.</p> + <p> + The old versions are still present and can be used when + communicating with nodes that don't support the new + versions.</p> + <p> + Own Id: OTP-15611</p> + </item> + <item> + <p> + Kernel configuration parameter <c>start_distribution = + boolean()</c> is added. If set to <c>false</c>, the + system is started with all distribution functionality + disabled. Defaults to <c>true</c>.</p> + <p> + Own Id: OTP-15668 Aux Id: PR-2088 </p> + </item> + <item> + <p> + In OTP-21.3, a warning was introduced for duplicated + applications/keys in configuration. This warning would be + displayed both when the configuration was given as a file + on system start, and during runtime via + <c>application:set_env/1,2</c>.</p> + <p> + The warning is now changed to a <c>badarg</c> exception + in <c>application:set_env/1,2</c>. If the faulty + configuration is given in a configuration file on system + start, the startup will fail.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15692 Aux Id: PR-2170 </p> + </item> + </list> + </section> + +</section> + <section><title>Kernel 6.3.1</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 aca3247c8f..cd0397a98c 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -19,23 +19,15 @@ %% %% We allow upgrade from, and downgrade to all previous %% versions from the following OTP releases: -%% - OTP 20 %% - OTP 21 +%% - OTP 22 %% %% We also allow upgrade from, and downgrade to all %% versions that have branched off from the above %% stated previous versions. %% {"%VSN%", - [{<<"^5\\.3$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^6\\.0$">>,[restart_new_emulator]}, + [{<<"^6\\.0$">>,[restart_new_emulator]}, {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.1$">>,[restart_new_emulator]}, @@ -45,16 +37,9 @@ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.3$">>,[restart_new_emulator]}, - {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], - [{<<"^5\\.3$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^6\\.0$">>,[restart_new_emulator]}, + {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, + {<<"^6\\.3\\.1(?:\\.[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]}, {<<"^6\\.1$">>,[restart_new_emulator]}, @@ -64,4 +49,5 @@ {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^6\\.3$">>,[restart_new_emulator]}, - {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}. + {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, + {<<"^6\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index b1ae513223..765e890157 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 6.3.1 +KERNEL_VSN = 6.4 diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml index b697c3f631..6f33ae390c 100644 --- a/lib/megaco/doc/src/notes.xml +++ b/lib/megaco/doc/src/notes.xml @@ -37,7 +37,30 @@ section is the version number of Megaco.</p> - <section><title>Megaco 3.18.4</title> + <section><title>Megaco 3.18.5</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor updates to build system necessary due to move of + configuration of <c>crypto</c> application.</p> + <p> + Own Id: OTP-15262 Aux Id: OTP-15129 </p> + </item> + <item> + <p> + Minor adjustments made to build system for parallel + configure.</p> + <p> + Own Id: OTP-15340 Aux Id: OTP-14625 </p> + </item> + </list> + </section> + +</section> + +<section><title>Megaco 3.18.4</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk index f4c82c537a..843a3dccc5 100644 --- a/lib/megaco/vsn.mk +++ b/lib/megaco/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = megaco -MEGACO_VSN = 3.18.4 +MEGACO_VSN = 3.18.5 PRE_VSN = APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)" diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 01d1666b8d..2d38e4d01c 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,51 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.</p> - <section><title>Mnesia 4.15.6</title> + <section><title>Mnesia 4.16</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Optimize mnesia:read/1 if data have been written in the + same transaction.</p> + <p> + Own Id: OTP-15550 Aux Id: PR-2029 </p> + </item> + <item> + <p> + Fixed bugs in table index plugin handling.</p> + <p> + Own Id: OTP-15689 Aux Id: PR-1695 ERL-556 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Optimized dumping of tables with plugin backends.</p> + <p> + Own Id: OTP-15588 Aux Id: PR-2102 </p> + </item> + <item> + <p> + Include stacktrace in exception if a dirty activity + errors, thus if user have matched on the error thrown it + may not match any more.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15804 Aux Id: PR-2216 </p> + </item> + </list> + </section> + +</section> + +<section><title>Mnesia 4.15.6</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 781a4830a0..aa5d9adb6d 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.15.6 +MNESIA_VSN = 4.16 diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml index 2d914f8c61..f05e58dc21 100644 --- a/lib/observer/doc/src/notes.xml +++ b/lib/observer/doc/src/notes.xml @@ -32,6 +32,23 @@ <p>This document describes the changes made to the Observer application.</p> +<section><title>Observer 2.9.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + <section><title>Observer 2.9</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk index 0e9c8b302c..c16c43f942 100644 --- a/lib/observer/vsn.mk +++ b/lib/observer/vsn.mk @@ -1 +1 @@ -OBSERVER_VSN = 2.9 +OBSERVER_VSN = 2.9.1 diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml index 696fcaa479..8d708162e4 100644 --- a/lib/odbc/doc/src/notes.xml +++ b/lib/odbc/doc/src/notes.xml @@ -32,7 +32,23 @@ <p>This document describes the changes made to the odbc application. </p> - <section><title>ODBC 2.12.3</title> + <section><title>ODBC 2.12.4</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor adjustments made to build system for parallel + configure.</p> + <p> + Own Id: OTP-15340 Aux Id: OTP-14625 </p> + </item> + </list> + </section> + +</section> + +<section><title>ODBC 2.12.3</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk index ff023e666b..df6db09f2f 100644 --- a/lib/odbc/vsn.mk +++ b/lib/odbc/vsn.mk @@ -1 +1 @@ -ODBC_VSN = 2.12.3 +ODBC_VSN = 2.12.4 diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml index 64e9f281e3..1f169263e9 100644 --- a/lib/os_mon/doc/src/notes.xml +++ b/lib/os_mon/doc/src/notes.xml @@ -31,6 +31,35 @@ </header> <p>This document describes the changes made to the OS_Mon application.</p> +<section><title>Os_Mon 2.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix typespec of <c>cpu_sup:util()</c>.</p> + <p> + Own Id: OTP-15770 Aux Id: PR-2208 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The application otp_mibs has been removed from OTP. Some + of its components (mibs) have been moved to other apps + (snmp), or removed completely (os_mon).</p> + <p> + Own Id: OTP-14984 Aux Id: OTP-15329 </p> + </item> + </list> + </section> + +</section> + <section><title>Os_Mon 2.4.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk index 9713f6bc6b..845443d329 100644 --- a/lib/os_mon/vsn.mk +++ b/lib/os_mon/vsn.mk @@ -1 +1 @@ -OS_MON_VSN = 2.4.7 +OS_MON_VSN = 2.5 diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index f6bc0dc797..d13c9a520a 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -35,6 +35,78 @@ <file>notes.xml</file> </header> +<section><title>Public_Key 1.6.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + RSA options passed to crypto for encrypt and decrypt with + public or private key.</p> + <p> + Own Id: OTP-15754 Aux Id: ERL-878 </p> + </item> + <item> + <p> + Fix dialyzer warnings caused by a faulty type + specification for digest_type().</p> + <p> + This change updates digest_type() and the functions + operating with this argument type to accept both 'sha1' + and 'sha' as digest_type().</p> + <p> + Own Id: OTP-15776</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add possibility to read PEM files encrypted with old PEM + encryption using AES-256</p> + <p> + Own Id: OTP-13726</p> + </item> + <item> + <p> + Relax decoding of certificates to so that "harmless" + third party encoding errors may be accepted but not + created by the public_key application. This adds + acceptance of using an incorrect three character country + code, the PKIX standard use two character country codes. + It is also accepted that the country code is utf8 encoded + but the specification says it should be ASCII.</p> + <p> + Own Id: OTP-15687 Aux Id: PR-2162 </p> + </item> + </list> + </section> + +</section> + +<section><title>Public_Key 1.6.6</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Back port of bug fix ERL-893 from OTP-22 and document + enhancements that will solve dialyzer warnings for users + of the ssl application.</p> + <p> + This change also affects public_key, eldap (and inet + doc).</p> + <p> + Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215 </p> + </item> + </list> + </section> + +</section> + <section><title>Public_Key 1.6.5</title> <section><title>Improvements and New Features</title> diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index 11c06fb158..a5e4ec8d5a 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.6.5 +PUBLIC_KEY_VSN = 1.6.7 diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml index 165ae6db6a..ee00b6086d 100644 --- a/lib/reltool/doc/src/notes.xml +++ b/lib/reltool/doc/src/notes.xml @@ -38,7 +38,40 @@ thus constitutes one section in this document. The title of each section is the version number of Reltool.</p> - <section><title>Reltool 0.7.8</title> + <section><title>Reltool 0.8</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A new element, <c>Opts</c>, can now be included in a + <c>rel</c> tuple in the reltool release specific + configuration format: {rel, Name, Vsn, RelApps, Opts}.</p> + <p> + This supports the use of <c>{rel, Name, Vsn, RelApps, + [{load_dot_erlang, false}]}</c> to prevent the boot + script from running the <c>.erlang</c> file.</p> + <p> + The incompatibilities are as follows:</p> + <p> + * The return from <c>reltool:get_config/1</c> and + <c>reltool:get_config/3</c> includes the new <c>rel</c> + tuple for all releases where the <c>load_dot_erlang</c> + option is set to <c>false</c>.<br/> * The return from + <c>reltool:get_config/3</c> includes the new <c>rel</c> + tuple for ALL releases if the <c>InclDefs</c> parameter + is set to <c>true</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15571</p> + </item> + </list> + </section> + +</section> + +<section><title>Reltool 0.7.8</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk index a649a3e0c0..c5aacfba38 100644 --- a/lib/reltool/vsn.mk +++ b/lib/reltool/vsn.mk @@ -1 +1 @@ -RELTOOL_VSN = 0.7.8 +RELTOOL_VSN = 0.8 diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index 58a2a66c4b..1b94c3e6d9 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -32,6 +32,22 @@ <p>This document describes the changes made to the Runtime_Tools application.</p> +<section><title>Runtime_Tools 1.13.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Minor updates to build system necessary due to move of + configuration of <c>crypto</c> application.</p> + <p> + Own Id: OTP-15262 Aux Id: OTP-15129 </p> + </item> + </list> + </section> + +</section> + <section><title>Runtime_Tools 1.13.2</title> <section><title>Improvements and New Features</title> diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index fa2f338ec2..3f38574be4 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.13.2 +RUNTIME_TOOLS_VSN = 1.13.3 diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml index 982c874117..a1ae404776 100644 --- a/lib/sasl/doc/src/notes.xml +++ b/lib/sasl/doc/src/notes.xml @@ -31,6 +31,23 @@ </header> <p>This document describes the changes made to the SASL application.</p> +<section><title>SASL 3.4</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Change the first module called by erts to be named + erl_init instead of otp_ring0. systools in sasl have been + updated to reflect this change.</p> + <p> + Own Id: OTP-15336 Aux Id: PR-1825 </p> + </item> + </list> + </section> + +</section> + <section><title>SASL 3.3</title> <section><title>Improvements and New Features</title> diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src index 26127eae84..22a9027b7c 100644 --- a/lib/sasl/src/sasl.appup.src +++ b/lib/sasl/src/sasl.appup.src @@ -19,27 +19,21 @@ %% %% We allow upgrade from, and downgrade to all previous %% versions from the following OTP releases: -%% - OTP 20 %% - OTP 21 +%% - OTP 22 %% %% We also allow upgrade from, and downgrade to all %% versions that have branched off from the above %% stated previous versions. %% {"%VSN%", - [{<<"^3\\.0\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.2$">>,[restart_new_emulator]}, + [{<<"^3\\.2$">>,[restart_new_emulator]}, {<<"^3\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}], - [{<<"^3\\.0\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.2$">>,[restart_new_emulator]}, + {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.3$">>,[restart_new_emulator]}, + {<<"^3\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], + [{<<"^3\\.2$">>,[restart_new_emulator]}, {<<"^3\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}. + {<<"^3\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, + {<<"^3\\.3$">>,[restart_new_emulator]}, + {<<"^3\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}. diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index c1f80752a7..8838b514da 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 3.3 +SASL_VSN = 3.4 diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index a6c3d57148..780e0cae76 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -34,7 +34,32 @@ </header> - <section><title>SNMP 5.2.12</title> + <section><title>SNMP 5.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The application otp_mibs has been removed from OTP. Some + of its components (mibs) have been moved to other apps + (snmp), or removed completely (os_mon).</p> + <p> + Own Id: OTP-14984 Aux Id: OTP-15329 </p> + </item> + <item> + <p> + [snmp|agent] Add a get-mechanism callback module (and a + corresponding behaviour). The agent calls this module to + handle each get (get, get-next and get-bulk) request.</p> + <p> + Own Id: OTP-15691 Aux Id: ERIERL-324 </p> + </item> + </list> + </section> + +</section> + +<section><title>SNMP 5.2.12</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 78990c48f2..60f20c7c3f 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,21 @@ <file>notes.xml</file> </header> +<section><title>Ssh 4.7.7</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + SSH uses the new crypto API.</p> + <p> + Own Id: OTP-15673</p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 4.7.6</title> <section><title>Improvements and New Features</title> diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src index 7449405d20..2193c14611 100644 --- a/lib/ssh/src/ssh.app.src +++ b/lib/ssh/src/ssh.app.src @@ -44,7 +44,7 @@ {env, []}, {mod, {ssh_app, []}}, {runtime_dependencies, [ - "crypto-@OTP-15644@", + "crypto-4.5", "erts-9.0", "kernel-5.3", "public_key-1.6.1", diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 837da27ab0..bb87dd388c 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,4 +1,4 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.7.6 +SSH_VSN = 4.7.7 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index f0231da2ad..5fdcf15b5f 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -27,6 +27,115 @@ </header> <p>This document describes the changes made to the SSL application.</p> +<section><title>SSL 9.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The distribution handshake with TLS distribution + (<c>inet_tls_dist</c>) does now utilize the socket option + <c>{nodelay, true}</c>, which decreases the distribution + setup time significantly.</p> + <p> + Own Id: OTP-14792</p> + </item> + <item> + <p> + Correct shutdown reason to avoid an incorrect crash + report</p> + <p> + Own Id: OTP-15710 Aux Id: ERL-893 </p> + </item> + <item> + <p> + Enhance documentation and type specifications.</p> + <p> + Own Id: OTP-15746 Aux Id: ERIERL-333 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + TLS-1.0, TLS-1.1 and DTLS-1.0 are now considered legacy + and not supported by default</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14865</p> + </item> + <item> + <p> + Use new logger API in ssl. Introduce log levels and + verbose debug logging for SSL.</p> + <p> + Own Id: OTP-15055</p> + </item> + <item> + <p> + Add new API function str_to_suite/1, cipher_suites/3 + (list cipher suites as rfc or OpenSSL name strings) and + suite_to_openssl_str/1</p> + <p> + Own Id: OTP-15483 Aux Id: ERL-924 </p> + </item> + <item> + <p> + Basic support for TLS 1.3 Server for experimental use. + The client is not yet functional, for more information + see the Standards Compliance chapter of the User's Guide.</p> + <p> + Own Id: OTP-15591</p> + </item> + <item> + <p> + Add support for PSK CCM ciphers from RFC 6655</p> + <p> + Own Id: OTP-15626</p> + </item> + </list> + </section> + +</section> + +<section><title>SSL 9.2.3</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-15802 Aux Id: ERL-934 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Back port of bug fix ERL-893 from OTP-22 and document + enhancements that will solve dialyzer warnings for users + of the ssl application.</p> + <p> + This change also affects public_key, eldap (and inet + doc).</p> + <p> + Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215 </p> + </item> + </list> + </section> + +</section> + <section><title>SSL 9.2.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index fa9da25f0c..6af65e09f2 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -987,7 +987,7 @@ cipher_suites(Base, Version) -> [ssl_cipher_format:suite_bin_to_map(Suite) || Suite <- supported_suites(Base, Version)]. %%-------------------------------------------------------------------- --spec cipher_suites(Supported, Version, rfc | openssl) -> string() when +-spec cipher_suites(Supported, Version, rfc | openssl) -> [string()] when Supported :: default | all | anonymous, Version :: protocol_version(). diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 872a557e67..a05858221a 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -171,21 +171,19 @@ next_record(#state{protocol_buffers = connection_states = ConnectionStates, ssl_options = #ssl_options{padding_check = Check}} = State) -> next_record(State, CipherTexts, ConnectionStates, Check); -next_record(#state{user_data_buffer = {_,0,_}, - protocol_buffers = #protocol_buffers{tls_cipher_texts = []}, - protocol_specific = #{active_n_toggle := true, - active_n := N} = ProtocolSpec, +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) -> + } = State) -> case tls_socket:setopts(Transport, Socket, [{active, N}]) of ok -> - {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}}; + {no_record, State#state{protocol_specific = ProtocolSpec#{active_n_toggle => false}}}; _ -> - self() ! {CloseTag, Socket}, - {no_record, State} - end; + self() ! {CloseTag, Socket}, + {no_record, State} + end; next_record(State) -> {no_record, State}. diff --git a/lib/ssl/test/inet_crypto_dist.erl b/lib/ssl/test/inet_crypto_dist.erl index 5aafaac983..63c19d9438 100644 --- a/lib/ssl/test/inet_crypto_dist.erl +++ b/lib/ssl/test/inet_crypto_dist.erl @@ -29,14 +29,8 @@ -define(DRIVER, inet_tcp). -define(FAMILY, inet). --define(PROTOCOL, inet_crypto_dist_v1). --define(DEFAULT_BLOCK_CRYPTO, aes_128_gcm). --define(DEFAULT_HASH_ALGORITHM, sha256). --define(DEFAULT_REKEY_INTERVAL, 32768). - -export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). --export([is_supported/0]). %% Generalized dist API, for sibling IPv6 module inet6_crypto_dist -export([gen_listen/2, gen_accept/2, gen_accept_connection/6, @@ -52,20 +46,136 @@ -include_lib("kernel/include/dist.hrl"). -include_lib("kernel/include/dist_util.hrl"). -%% Test if crypto has got enough capabilities for this module to run +-define(PACKET_SIZE, 65536). +-define(BUFFER_SIZE, (?PACKET_SIZE bsl 4)). + +%% ------------------------------------------------------------------------- + +-record(params, + {socket, + dist_handle, + hmac_algorithm = sha256, + aead_cipher = aes_gcm, + rekey_key, + iv = 12, + key = 16, + tag_len = 16, + rekey_interval = 262144 + }). + +params(Socket) -> + #params{socket = Socket}. + + +-record(key_pair, + {type = ecdh, + %% The curve choice greatly affects setup time, + %% we really want an Edwards curve but that would + %% require a very new openssl version. + %% Twisted brainpool curves (*t1) are faster than + %% non-twisted (*r1), 256 is much faster than 384, + %% and so on... +%%% params = brainpoolP384t1, + params = brainpoolP256t1, + public, + private}). + +-define(KEY_PAIR_LIFE_TIME, 3600000). % 1 hour +-define(KEY_PAIR_LIFE_COUNT, 256). % Number of connection setups + + +%% ------------------------------------------------------------------------- +%% Keep the node's public/private key pair in the process state +%% of a key pair server linked to the acceptor process. +%% Create the key pair the first time it is needed +%% so crypto gets time to start first. %% -is_supported() -> - try {crypto:cipher_info(?DEFAULT_BLOCK_CRYPTO), - crypto:hash_info(?DEFAULT_HASH_ALGORITHM)} - of - {#{block_size := _, iv_length := _, key_length := _}, - #{size := _}} -> - true - catch - error:undef -> - false + +start_key_pair_server() -> + monitor_dist_proc( + spawn_link( + fun () -> + register(?MODULE, self()), + key_pair_server() + end)). + +key_pair_server() -> + key_pair_server(undefined, undefined, undefined). +%% +key_pair_server(KeyPair) -> + key_pair_server( + KeyPair, + erlang:start_timer(?KEY_PAIR_LIFE_TIME, self(), discard), + ?KEY_PAIR_LIFE_COUNT). +%% +key_pair_server(_KeyPair, Timer, 0) -> + cancel_timer(Timer), + key_pair_server(); +key_pair_server(KeyPair, Timer, Count) -> + receive + {Pid, Tag, get_key_pair} -> + case KeyPair of + undefined -> + KeyPair_1 = generate_key_pair(), + Pid ! {Tag, KeyPair_1}, + key_pair_server(KeyPair_1); + #key_pair{} -> + Pid ! {Tag, KeyPair}, + key_pair_server(KeyPair, Timer, Count - 1) + end; + {Pid, Tag, get_new_key_pair} -> + cancel_timer(Timer), + KeyPair_1 = generate_key_pair(), + Pid ! {Tag, KeyPair_1}, + key_pair_server(KeyPair_1); + {timeout, Timer, discard} when is_reference(Timer) -> + key_pair_server() + end. + +generate_key_pair() -> + #key_pair{type = Type, params = Params} = #key_pair{}, + {Public, Private} = + crypto:generate_key(Type, Params), + #key_pair{public = Public, private = Private}. + +cancel_timer(undefined) -> + ok; +cancel_timer(Timer) -> + case erlang:cancel_timer(Timer) of + false -> + receive + {timeout, Timer, _} -> ok + end; + _RemainingTime -> + ok + end. + +get_key_pair() -> + call_key_pair_server(get_key_pair). + +get_new_key_pair() -> + call_key_pair_server(get_new_key_pair). + +call_key_pair_server(Request) -> + Pid = whereis(?MODULE), + Ref = erlang:monitor(process, Pid), + Pid ! {self(), Ref, Request}, + receive + {Ref, Reply} -> + erlang:demonitor(Ref, [flush]), + Reply; + {'DOWN', Ref, process, Pid, Reason} -> + error(Reason) end. +compute_shared_secret( + #key_pair{ + type = PublicKeyType, + params = PublicKeyParams, + private = PrivKey}, PubKey) -> + %% + crypto:compute_key(PublicKeyType, PubKey, PrivKey, PublicKeyParams). + %% ------------------------------------------------------------------------- %% Erlang distribution plugin structure explained to myself %% ------- @@ -80,7 +190,7 @@ is_supported() -> %% is not one or two processes, but one port - a gen_tcp socket %% %% When the VM is started with the argument "-proto_dist inet_crypto" -%% net_kernel registers the module inet_crypto_dist as distribution +%% net_kernel registers the module inet_crypto_dist acli,oams distribution %% module. net_kernel calls listen/1 to create a listen socket %% and then accept/1 with the listen socket as argument to spawn %% the Acceptor process, which is linked to net_kernel. Apparently @@ -159,6 +269,12 @@ is_supported() -> %% terminate with reason 'normal'. %% ------------------------------------------------------------------------- +-compile({inline, [socket_options/0]}). +socket_options() -> + [binary, {active, false}, {packet, 2}, {nodelay, true}, + {sndbuf, ?BUFFER_SIZE}, {recbuf, ?BUFFER_SIZE}, + {buffer, ?BUFFER_SIZE}]. + %% ------------------------------------------------------------------------- %% select/1 is called by net_kernel to ask if this distribution protocol %% is willing to handle Node @@ -195,7 +311,7 @@ listen(Name) -> gen_listen(Name, Driver) -> case inet_tcp_dist:gen_listen(Driver, Name) of {ok, {Socket, Address, Creation}} -> - inet:setopts(Socket, [binary, {nodelay, true}]), + inet:setopts(Socket, socket_options()), {ok, {Socket, Address#net_address{protocol = ?DIST_PROTO}, Creation}}; Other -> @@ -217,24 +333,24 @@ gen_accept(Listen, Driver) -> %% %% Spawn Acceptor process %% - Config = config(), monitor_dist_proc( spawn_opt( fun () -> - accept_loop(Listen, Driver, NetKernel, Config) + start_key_pair_server(), + accept_loop(Listen, Driver, NetKernel) end, [link, {priority, max}])). -accept_loop(Listen, Driver, NetKernel, Config) -> - case Driver:accept(Listen) of +accept_loop(Listen, Driver, NetKernel) -> + case Driver:accept(trace(Listen)) of {ok, Socket} -> wait_for_code_server(), Timeout = net_kernel:connecttime(), - DistCtrl = start_dist_ctrl(Socket, Config, Timeout), + DistCtrl = start_dist_ctrl(trace(Socket), Timeout), %% DistCtrl is a "socket" NetKernel ! - {accept, - self(), DistCtrl, Driver:family(), ?DIST_PROTO}, + trace({accept, + self(), DistCtrl, Driver:family(), ?DIST_PROTO}), receive {NetKernel, controller, Controller} -> call_dist_ctrl(DistCtrl, {controller, Controller, self()}), @@ -242,7 +358,7 @@ accept_loop(Listen, Driver, NetKernel, Config) -> {NetKernel, unsupported_protocol} -> exit(unsupported_protocol) end, - accept_loop(Listen, Driver, NetKernel, Config); + accept_loop(Listen, Driver, NetKernel); AcceptError -> exit({accept, AcceptError}) end. @@ -292,12 +408,13 @@ gen_accept_connection( fun() -> do_accept( Acceptor, DistCtrl, - MyNode, Allowed, SetupTime, Driver, NetKernel) + trace(MyNode), Allowed, SetupTime, Driver, NetKernel) end, [link, {priority, max}])). do_accept( Acceptor, DistCtrl, MyNode, Allowed, SetupTime, Driver, NetKernel) -> + %% receive {Acceptor, controller, Socket} -> Timer = dist_util:start_timer(SetupTime), @@ -337,40 +454,42 @@ gen_setup(Node, Type, MyNode, LongOrShortNames, SetupTime, Driver) -> -spec setup_fun(_,_,_,_,_,_,_) -> fun(() -> no_return()). setup_fun( Node, Type, MyNode, LongOrShortNames, SetupTime, Driver, NetKernel) -> + %% fun() -> do_setup( - Node, Type, MyNode, LongOrShortNames, SetupTime, + trace(Node), Type, MyNode, LongOrShortNames, SetupTime, Driver, NetKernel) end. -spec do_setup(_,_,_,_,_,_,_) -> no_return(). do_setup( Node, Type, MyNode, LongOrShortNames, SetupTime, Driver, NetKernel) -> + %% {Name, Address} = split_node(Driver, Node, LongOrShortNames), ErlEpmd = net_kernel:epmd_module(), {ARMod, ARFun} = get_address_resolver(ErlEpmd, Driver), Timer = trace(dist_util:start_timer(SetupTime)), case ARMod:ARFun(Name, Address, Driver:family()) of - {ok, Ip, TcpPort, Version} -> - do_setup_connect( - Node, Type, MyNode, Timer, Driver, NetKernel, - Ip, TcpPort, Version); + {ok, Ip, TcpPort, Version} -> + do_setup_connect( + Node, Type, MyNode, Timer, Driver, NetKernel, + Ip, TcpPort, Version); {ok, Ip} -> case ErlEpmd:port_please(Name, Ip) of {port, TcpPort, Version} -> do_setup_connect( Node, Type, MyNode, Timer, Driver, NetKernel, - Ip, TcpPort, Version); + Ip, TcpPort, trace(Version)); Other -> - ?shutdown2( - Node, - trace( - {port_please_failed, ErlEpmd, Name, Ip, Other})) + _ = trace( + {ErlEpmd, port_please, [Name, Ip], Other}), + ?shutdown(Node) end; Other -> - ?shutdown2( - Node, - trace({getaddr_failed, Driver, Address, Other})) + _ = trace( + {ARMod, ARFun, [Name, Address, Driver:family()], + Other}), + ?shutdown(Node) end. -spec do_setup_connect(_,_,_,_,_,_,_,_,_) -> no_return(). @@ -379,15 +498,15 @@ do_setup_connect( Node, Type, MyNode, Timer, Driver, NetKernel, Ip, TcpPort, Version) -> dist_util:reset_timer(Timer), - ConnectOpts = - trace( - connect_options( - [binary, {active, false}, {packet, 2}, {nodelay, true}])), + ConnectOpts = trace(connect_options(socket_options())), case Driver:connect(Ip, TcpPort, ConnectOpts) of {ok, Socket} -> - Config = config(), DistCtrl = - start_dist_ctrl(Socket, Config, net_kernel:connecttime()), + try start_dist_ctrl(Socket, net_kernel:connecttime()) + catch error : {dist_ctrl, _} = DistCtrlError -> + _ = trace(DistCtrlError), + ?shutdown(Node) + end, %% DistCtrl is a "socket" HSData = hs_data_common( @@ -401,8 +520,10 @@ do_setup_connect( request_type = Type}, dist_util:handshake_we_started(trace(HSData_1)); ConnectError -> - ?shutdown2(Node, - trace({connect_failed, Ip, TcpPort, ConnectError})) + _ = trace( + {Driver, connect, [Ip, TcpPort, ConnectOpts], + ConnectError}), + ?shutdown(Node) end. %% ------------------------------------------------------------------------- @@ -412,7 +533,7 @@ close(Socket) -> gen_close(Socket, ?DRIVER). gen_close(Socket, Driver) -> - trace(Driver:close(Socket)). + Driver:close(trace(Socket)). %% ------------------------------------------------------------------------- @@ -428,17 +549,23 @@ hs_data_common(NetKernel, MyNode, DistCtrl, Timer, Socket, Family) -> socket = DistCtrl, timer = Timer, %% - f_send = + f_send = % -> ok | {error, closed}=>?shutdown() fun (S, Packet) when S =:= DistCtrl -> - call_dist_ctrl(S, {send, Packet}) + try call_dist_ctrl(S, {send, Packet}) + catch error : {dist_ctrl, Reason} -> + _ = trace(Reason), + {error, closed} + end end, - f_recv = + f_recv = % -> {ok, List} | Other=>?shutdown() fun (S, 0, infinity) when S =:= DistCtrl -> - case call_dist_ctrl(S, recv) of + try call_dist_ctrl(S, recv) of {ok, Bin} when is_binary(Bin) -> {ok, binary_to_list(Bin)}; Error -> Error + catch error : {dist_ctrl, Reason} -> + {error, trace(Reason)} end end, f_setopts_pre_nodeup = @@ -453,9 +580,9 @@ hs_data_common(NetKernel, MyNode, DistCtrl, Timer, Socket, Family) -> fun (S) when S =:= DistCtrl -> {ok, S} %% DistCtrl is the distribution port end, - f_address = + f_address = % -> #net_address{} | ?shutdown() fun (S, Node) when S =:= DistCtrl -> - case call_dist_ctrl(S, peername) of + try call_dist_ctrl(S, peername) of {ok, Address} -> case dist_util:split_node(Node) of {node, _, Host} -> @@ -465,13 +592,23 @@ hs_data_common(NetKernel, MyNode, DistCtrl, Timer, Socket, Family) -> protocol = ?DIST_PROTO, family = Family}; _ -> - {error, no_node} - end + ?shutdown(Node) + end; + Error -> + _ = trace(Error), + ?shutdown(Node) + catch error : {dist_ctrl, Reason} -> + _ = trace(Reason), + ?shutdown(Node) end end, - f_handshake_complete = - fun (S, _Node, DistHandle) when S =:= DistCtrl -> - call_dist_ctrl(S, {handshake_complete, DistHandle}) + f_handshake_complete = % -> ok | ?shutdown() + fun (S, Node, DistHandle) when S =:= DistCtrl -> + try call_dist_ctrl(S, {handshake_complete, DistHandle}) + catch error : {dist_ctrl, Reason} -> + _ = trace(Reason), + ?shutdown(Node) + end end, %% %% mf_tick/1, mf_getstat/1, mf_setopts/2 and mf_getopts/2 @@ -481,7 +618,7 @@ hs_data_common(NetKernel, MyNode, DistCtrl, Timer, Socket, Family) -> fun (S) when S =:= DistCtrl -> S ! dist_tick end, - mf_getstat = + mf_getstat = % -> {ok, RecvCnt, SendCnt, SendPend} | Other=>ignore_it fun (S) when S =:= DistCtrl -> case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) @@ -489,7 +626,7 @@ hs_data_common(NetKernel, MyNode, DistCtrl, Timer, Socket, Family) -> {ok, Stat} -> split_stat(Stat, 0, 0, 0); Error -> - Error + trace(Error) end end, mf_setopts = @@ -596,25 +733,6 @@ nodelay() -> {nodelay, true} end. -config() -> - case init:get_argument(?DIST_NAME) of - error -> - error({missing_argument, ?DIST_NAME}); - {ok, [[String]]} -> - {ok, Tokens, _} = erl_scan:string(String ++ "."), - case erl_parse:parse_term(Tokens) of - {ok, #{secret := Secret} = Config} - when is_binary(Secret); is_list(Secret) -> - Config; - {ok, #{} = Config} -> - error({missing_secret, [{?DIST_NAME,Config}]}); - _ -> - error({bad_argument_value, [{?DIST_NAME,String}]}) - end; - {ok, Value} -> - error({malformed_argument, [{?DIST_NAME,Value}]}) - end. - %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% The DistCtrl process(es). @@ -625,40 +743,36 @@ config() -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% XXX Missing to "productified": -%%% * Cryptoanalysis by experts -%%% * Proof of usefulness -%%% * Unifying exit reasons using a death_row() function -%%% * Verification (and rejection) of other end's crypto parameters -%%% * OTP:ification (proc_lib?) -%%% * An application to belong to (crypto|kernel?) -%%% * Secret on file (cookie as default?), parameter handling -%%% * Restart and/or code reload policy +%%% * Cryptoanalysis by experts, this is crypto amateur work. +%%% * Is it useful over inet_tls_dist; i.e to not have to bother +%%% with certificates but instead manage a secret cluster cookie? +%%% * An application to belong to (kernel) +%%% * Restart and/or code reload policy (not needed in kernel) +%%% * Fitting into the epmd/Erlang distro protocol version framework +%%% (something needs to be created for multiple protocols, epmd, +%%% multiple address families, fallback to previous version, etc) -%% Debug client and server -test_config() -> - #{secret => <<"Secret Cluster Password 123456">>}. +%% Debug client and server test_server() -> - {ok, Listen} = gen_tcp:listen(0, [{packet, 2}, {active, false}, binary]), + {ok, Listen} = gen_tcp:listen(0, socket_options()), {ok, Port} = inet:port(Listen), io:format(?MODULE_STRING":test_client(~w).~n", [Port]), {ok, Socket} = gen_tcp:accept(Listen), test(Socket). test_client(Port) -> - {ok, Socket} = - gen_tcp:connect( - localhost, Port, [{packet, 2}, {active, false}, binary]), + {ok, Socket} = gen_tcp:connect(localhost, Port, socket_options()), test(Socket). test(Socket) -> - start_dist_ctrl(Socket, test_config(), 10000). + start_dist_ctrl(Socket, 10000). %% ------------------------------------------------------------------------- -start_dist_ctrl(Socket, Config, Timeout) -> - Protocol = ?PROTOCOL, +start_dist_ctrl(Socket, Timeout) -> + Secret = atom_to_binary(auth:get_cookie(), latin1), Controller = self(), Server = monitor_dist_proc( @@ -667,9 +781,9 @@ start_dist_ctrl(Socket, Config, Timeout) -> receive {?MODULE, From, start} -> {SendParams, RecvParams} = - init(Socket, Config, Protocol), + init(Socket, Secret), reply(From, self()), - handshake(SendParams, 0, RecvParams, 0, Controller) + handshake(SendParams, 1, RecvParams, 1, Controller) end end, [link, @@ -691,12 +805,13 @@ call_dist_ctrl(Server, Msg, Timeout) -> erlang:demonitor(Ref, [flush]), Res; {'DOWN', Ref, process, Server, Reason} -> - exit({?PROTOCOL, Reason}) - after Timeout -> - exit(Server, timeout), + error({dist_ctrl, Reason}) + after Timeout -> % Timeout < infinity is only used by start_dist_ctrl/2 receive {'DOWN', Ref, process, Server, _} -> - exit({?PROTOCOL, timeout}) + receive {Ref, _} -> ok after 0 -> ok end, + error({dist_ctrl, timeout}) + %% Server will be killed by link end end. @@ -706,21 +821,9 @@ reply({Ref, Pid}, Msg) -> %% ------------------------------------------------------------------------- --record(params, - {protocol, % Encryption protocol tag - socket, - dist_handle, - hash_algorithm, - block_crypto, - rekey_interval, - iv, - key, - tag_len}). - --define(TCP_ACTIVE, 64). --define(CHUNK_SIZE, (65536 - 512)). -%% The start chunk starts with zeros, so it seems logical to not have -%% a chunk type with value 0 +-define(TCP_ACTIVE, 16). +-define(CHUNK_SIZE, (?PACKET_SIZE - 512)). + -define(HANDSHAKE_CHUNK, 1). -define(DATA_CHUNK, 2). -define(TICK_CHUNK, 3). @@ -739,170 +842,189 @@ reply({Ref, Pid}, Msg) -> %% and waits for the other end's start message. So if the send %% blocks we have a deadlock. %% -%% The init message is unencrypted and contains the block cipher and hash -%% algorithms the sender will use, the IV and a key salt. Both sides' -%% key salt is used with the mutual secret as input to the hash algorithm -%% to create different encryption/decryption keys for both directions. +%% The init + start sequence tries to implement Password Encrypted +%% Key Exchange using a node public/private key pair and the +%% shared secret (the Cookie) to create session encryption keys +%% that can not be re-created if the shared secret is compromized, +%% which should create forward secrecy. You need both nodes' +%% key pairs and the shared secret to decrypt the traffic +%% between the nodes. +%% +%% All exchanged messages uses {packet, 2} i.e 16 bit size header. +%% +%% The init message contains a random number and encrypted: the public key +%% and two random numbers. The encryption is done with Key and IV hashed +%% from the unencrypted random number and the shared secret. +%% +%% The other node's public key is used with the own node's private +%% key to create a shared key that is hashed with one of the encrypted +%% random numbers from each side to create Key and IV for the session. %% -%% The start message is the first encrypted message and contains just -%% encrypted zeros the width of the key, with the header of the init -%% message as AAD data. Successfully decrypting this message -%% verifies that we have an encrypted channel. +%% The start message contains the two encrypted random numbers +%% this time encrypted with the session keys for verification +%% by the other side, plus the rekey interval. The rekey interval +%% is just there to get an early check for if the other side's +%% maximum rekey interal is acceptable, it is just an embryo +%% of some better check. Any side may rekey earlier but if the +%% rekey interval is exceeded the connection fails. %% %% Subsequent encrypted messages has the sequence number and the length -%% of the message as AAD data. These messages has got a message type -%% differentiating data from ticks. Ticks have a random size in an -%% attempt to make them less obvious to spot. +%% of the message as AAD data, and an incrementing IV. These messages +%% has got a message type that differentiates data from ticks and rekeys. +%% Ticks have a random size in an attempt to make them less obvious to spot. %% -%% The only reaction to errors is to crash noisily wich will bring +%% Rekeying is done by the sender that creates a new key pair and +%% a new shared secret from the other end's public key and with +%% this and the current key and iv hashes a new key and iv. +%% The new public key is sent to the other end that uses it +%% and its old private key to create the same new shared +%% secret and from that a new key and iv. +%% So the receiver keeps its private key, and the sender keeps +%% the receivers public key for the connection's life time. +%% While the sender generates a new key pair at every rekey, +%% which changes the shared secret at every rekey. +%% +%% The only reaction to errors is to crash noisily (?) wich will bring %% down the connection and hopefully produce something useful %% in the local log, but all the other end sees is a closed connection. %% ------------------------------------------------------------------------- -init(Socket, Config, Protocol) -> - Secret = maps:get(secret, Config), - HashAlgorithm = - maps:get(hash_algorithm, Config, ?DEFAULT_HASH_ALGORITHM), - BlockCrypto = - maps:get(block_crypto, Config, ?DEFAULT_BLOCK_CRYPTO), - RekeyInterval = - maps:get(rekey_interval, Config, ?DEFAULT_REKEY_INTERVAL), +init(Socket, Secret) -> + #key_pair{public = PubKey} = KeyPair = get_key_pair(), + Params = params(Socket), + {R2, R3, Msg} = init_msg(Params, PubKey, Secret), + ok = gen_tcp:send(Socket, Msg), + init_recv(Params, Secret, KeyPair, R2, R3). + +init_recv( + #params{socket = Socket, iv = IVLen} = Params, Secret, KeyPair, R2, R3) -> %% - SendParams = - init_params( - Socket, Protocol, HashAlgorithm, BlockCrypto, RekeyInterval), - send_init(SendParams, Secret). + {ok, InitMsg} = gen_tcp:recv(Socket, 0), + IVSaltLen = IVLen - 6, + try + case init_msg(Params, Secret, KeyPair, R2, R3, InitMsg) of + {#params{iv = <<IV2ASalt:IVSaltLen/binary, IV2ANo:48>>} = + SendParams, + RecvParams, SendStartMsg} -> + ok = gen_tcp:send(Socket, SendStartMsg), + {ok, RecvStartMsg} = gen_tcp:recv(Socket, 0), + #params{ + iv = <<IV2BSalt:IVSaltLen/binary, IV2BNo:48>>} = + RecvParams_1 = + start_msg(RecvParams, R2, R3, RecvStartMsg), + {SendParams#params{iv = {IV2ASalt, IV2ANo}}, + RecvParams_1#params{iv = {IV2BSalt, IV2BNo}}} + end + catch + error : Reason : Stacktrace-> + _ = trace({Reason, Stacktrace}), + exit(connection_closed) + end. -send_init( + + +init_msg( #params{ - protocol = Protocol, - socket = Socket, - block_crypto = BlockCrypto, - iv = IVLen, + hmac_algorithm = HmacAlgo, + aead_cipher = AeadCipher, key = KeyLen, - hash_algorithm = HashAlgorithm} = SendParams, - Secret) -> + iv = IVLen, + tag_len = TagLen}, PubKeyA, Secret) -> %% - ProtocolString = atom_to_binary(Protocol, utf8), - BlockCryptoString = atom_to_binary(BlockCrypto, utf8), - HashAlgorithmString = atom_to_binary(HashAlgorithm, utf8), - SendHeader = - <<ProtocolString/binary, 0, - HashAlgorithmString/binary, 0, - BlockCryptoString/binary, 0>>, - <<IV:IVLen/binary, KeySalt:KeyLen/binary>> = IV_KeySalt = - crypto:strong_rand_bytes(IVLen + KeyLen), - InitPacket = [SendHeader, IV_KeySalt], - ok = gen_tcp:send(Socket, InitPacket), - recv_init(SendParams#params{iv = IV, key = KeySalt}, Secret, SendHeader). - -recv_init( + RLen = KeyLen + IVLen, + <<R1A:RLen/binary, R2A:RLen/binary, R3A:RLen/binary>> = + crypto:strong_rand_bytes(3 * RLen), + {Key1A, IV1A} = hmac_key_iv(HmacAlgo, R1A, Secret, KeyLen, IVLen), + Plaintext = [R2A, R3A, PubKeyA], + MsgLen = byte_size(R1A) + TagLen + iolist_size(Plaintext), + AAD = [<<MsgLen:32>>, R1A], + {Ciphertext, Tag} = + crypto:block_encrypt(AeadCipher, Key1A, IV1A, {AAD, Plaintext, TagLen}), + Msg = [R1A, Tag, Ciphertext], + {R2A, R3A, Msg}. +%% +init_msg( #params{ - socket = Socket, - hash_algorithm = SendHashAlgorithm, - key = SendKeySalt} = SendParams, Secret, SendHeader) -> + hmac_algorithm = HmacAlgo, + aead_cipher = AeadCipher, + key = KeyLen, + iv = IVLen, + tag_len = TagLen, + rekey_interval = RekeyInterval} = Params, + Secret, KeyPair, R2A, R3A, Msg) -> %% - {ok, InitPacket} = gen_tcp:recv(Socket, 0), - [ProtocolString, Rest_1] = binary:split(InitPacket, <<0>>), - Protocol = binary_to_existing_atom(ProtocolString, utf8), - case Protocol of - ?PROTOCOL -> - [HashAlgorithmString, Rest_2] = binary:split(Rest_1, <<0>>), - HashAlgorithm = binary_to_existing_atom(HashAlgorithmString, utf8), - [BlockCryptoString, Rest_3] = binary:split(Rest_2, <<0>>), - BlockCrypto = binary_to_existing_atom(BlockCryptoString, utf8), - #params{ - hash_algorithm = RecvHashAlgorithm, - iv = RecvIVLen, - key = RecvKeyLen} = RecvParams = - init_params( - Socket, Protocol, HashAlgorithm, BlockCrypto, undefined), - <<RecvIV:RecvIVLen/binary, - RecvKeySalt:RecvKeyLen/binary>> = Rest_3, - SendKey = - hash_key(SendHashAlgorithm, SendKeySalt, [RecvKeySalt, Secret]), - RecvKey = - hash_key(RecvHashAlgorithm, RecvKeySalt, [SendKeySalt, Secret]), - SendParams_1 = SendParams#params{key = SendKey}, - RecvParams_1 = RecvParams#params{iv = RecvIV, key = RecvKey}, - RecvHeaderLen = byte_size(InitPacket) - RecvIVLen - RecvKeyLen, - <<RecvHeader:RecvHeaderLen/binary, _/binary>> = InitPacket, - send_start(SendParams_1, SendHeader), - RecvRekeyInterval = recv_start(RecvParams_1, RecvHeader), - {SendParams_1, - RecvParams_1#params{rekey_interval = RecvRekeyInterval}} + RLen = KeyLen + IVLen, + case Msg of + <<R1B:RLen/binary, Tag:TagLen/binary, Ciphertext/binary>> -> + {Key1B, IV1B} = hmac_key_iv(HmacAlgo, R1B, Secret, KeyLen, IVLen), + MsgLen = byte_size(Msg), + AAD = [<<MsgLen:32>>, R1B], + case + crypto:block_decrypt( + AeadCipher, Key1B, IV1B, {AAD, Ciphertext, Tag}) + of + <<R2B:RLen/binary, R3B:RLen/binary, PubKeyB/binary>> -> + SharedSecret = compute_shared_secret(KeyPair, PubKeyB), + %% + {Key2A, IV2A} = + hmac_key_iv( + HmacAlgo, SharedSecret, [R2A, R3B], KeyLen, IVLen), + SendParams = + Params#params{ + rekey_key = PubKeyB, + key = Key2A, iv = IV2A}, + %% + StartCleartext = [R2B, R3B, <<RekeyInterval:32>>], + StartMsgLen = TagLen + iolist_size(StartCleartext), + StartAAD = <<StartMsgLen:32>>, + {StartCiphertext, StartTag} = + crypto:block_encrypt( + AeadCipher, Key2A, IV2A, + {StartAAD, StartCleartext, TagLen}), + StartMsg = [StartTag, StartCiphertext], + %% + {Key2B, IV2B} = + hmac_key_iv( + HmacAlgo, SharedSecret, [R2B, R3A], KeyLen, IVLen), + RecvParams = + Params#params{ + rekey_key = KeyPair, + key = Key2B, iv = IV2B}, + %% + {SendParams, RecvParams, StartMsg} + end end. -send_start( +start_msg( #params{ - socket = Socket, - block_crypto = BlockCrypto, - rekey_interval= RekeyInterval, - iv = IV, - key = Key, - tag_len = TagLen}, AAD) -> + aead_cipher = AeadCipher, + key = Key2B, + iv = IV2B, + tag_len = TagLen, + rekey_interval = RekeyIntervalA} = RecvParams, R2A, R3A, Msg) -> %% - KeyLen = byte_size(Key), - Zeros = binary:copy(<<0>>, KeyLen), - {Ciphertext, CipherTag} = - crypto:block_encrypt( - crypto_cipher_name(BlockCrypto), - Key, IV, {AAD, [Zeros, <<RekeyInterval:32>>], TagLen}), - ok = gen_tcp:send(Socket, [Ciphertext, CipherTag]). - -recv_start( - #params{ - socket = Socket, - block_crypto = BlockCrypto, - iv = IV, - key = Key, - tag_len = TagLen}, AAD) -> - {ok, Packet} = gen_tcp:recv(Socket, 0), - KeyLen = byte_size(Key), - PacketLen = KeyLen + 4, - <<Ciphertext:PacketLen/binary, CipherTag:TagLen/binary>> = Packet, - Zeros = binary:copy(<<0>>, KeyLen), - case - crypto:block_decrypt( - crypto_cipher_name(BlockCrypto), - Key, IV, {AAD, Ciphertext, CipherTag}) - of - <<Zeros:KeyLen/binary, RekeyInterval:32>> - when 1 =< RekeyInterval -> - RekeyInterval; - _ -> - error(decrypt_error) - end. - -init_params(Socket, Protocol, HashAlgorithm, BlockCrypto, RekeyInterval) -> - #{block_size := 1, - iv_length := IVLen, - key_length := KeyLen} = crypto:cipher_info(BlockCrypto), - case crypto:hash_info(HashAlgorithm) of - #{size := HashSize} when HashSize >= KeyLen -> - #params{ - socket = Socket, - protocol = Protocol, - hash_algorithm = HashAlgorithm, - block_crypto = BlockCrypto, - rekey_interval = RekeyInterval, - iv = IVLen, - key = KeyLen, - tag_len = 16} - end. - -crypto_cipher_name(BlockCrypto) -> - case BlockCrypto of - aes_128_gcm -> aes_gcm; - aes_192_gcm -> aes_gcm; - aes_256_gcm -> aes_gcm + case Msg of + <<Tag:TagLen/binary, Ciphertext/binary>> -> + KeyLen = byte_size(Key2B), + IVLen = byte_size(IV2B), + RLen = KeyLen + IVLen, + MsgLen = byte_size(Msg), + AAD = <<MsgLen:32>>, + case + crypto:block_decrypt( + AeadCipher, Key2B, IV2B, {AAD, Ciphertext, Tag}) + of + <<R2A:RLen/binary, R3A:RLen/binary, RekeyIntervalB:32>> + when RekeyIntervalA =< (RekeyIntervalB bsl 2), + RekeyIntervalB =< (RekeyIntervalA bsl 2) -> + RecvParams#params{rekey_interval = RekeyIntervalB} + end end. -hash_key(HashAlgorithm, KeySalt, OtherSalt) -> - KeyLen = byte_size(KeySalt), - <<Key:KeyLen/binary, _/binary>> = - crypto:hash(HashAlgorithm, [KeySalt, OtherSalt]), - Key. +hmac_key_iv(HmacAlgo, MacKey, Data, KeyLen, IVLen) -> + <<Key:KeyLen/binary, IV:IVLen/binary>> = + crypto:hmac(HmacAlgo, MacKey, Data, KeyLen + IVLen), + {Key, IV}. %% ------------------------------------------------------------------------- %% net_kernel distribution handshake in progress @@ -918,7 +1040,6 @@ handshake( reply(From, Result), handshake(SendParams, SendSeq, RecvParams, RecvSeq, Controller_1); {?MODULE, From, {handshake_complete, DistHandle}} -> - reply(From, ok), InputHandler = monitor_dist_proc( spawn_opt( @@ -945,25 +1066,38 @@ handshake( ok = gen_tcp:controlling_process(Socket, InputHandler), ok = erlang:dist_ctrl_input_handler(DistHandle, InputHandler), InputHandler ! DistHandle, + crypto:rand_seed_alg(crypto_cache), + reply(From, ok), process_flag(priority, normal), erlang:dist_ctrl_get_data_notification(DistHandle), - crypto:rand_seed_alg(crypto_cache), output_handler( SendParams#params{dist_handle = DistHandle}, SendSeq); %% {?MODULE, From, {send, Data}} -> - {SendParams_1, SendSeq_1} = + case encrypt_and_send_chunk( - SendParams, SendSeq, [?HANDSHAKE_CHUNK, Data]), - reply(From, ok), - handshake( - SendParams_1, SendSeq_1, RecvParams, RecvSeq, Controller); + SendParams, SendSeq, [?HANDSHAKE_CHUNK, Data]) + of + {SendParams_1, SendSeq_1, ok} -> + reply(From, ok), + handshake( + SendParams_1, SendSeq_1, RecvParams, RecvSeq, + Controller); + {_, _, Error} -> + reply(From, {error, closed}), + death_row({send, trace(Error)}) + end; {?MODULE, From, recv} -> - {RecvParams_1, RecvSeq_1, Reply} = - recv_and_decrypt_chunk(RecvParams, RecvSeq), - reply(From, Reply), - handshake( - SendParams, SendSeq, RecvParams_1, RecvSeq_1, Controller); + case recv_and_decrypt_chunk(RecvParams, RecvSeq) of + {RecvParams_1, RecvSeq_1, {ok, _} = Reply} -> + reply(From, Reply), + handshake( + SendParams, SendSeq, RecvParams_1, RecvSeq_1, + Controller); + {_, _, Error} -> + reply(From, Error), + death_row({recv, trace(Error)}) + end; {?MODULE, From, peername} -> reply(From, inet:peername(Socket)), handshake(SendParams, SendSeq, RecvParams, RecvSeq, Controller); @@ -978,10 +1112,12 @@ recv_and_decrypt_chunk(#params{socket = Socket} = RecvParams, RecvSeq) -> case decrypt_chunk(RecvParams, RecvSeq, Chunk) of <<?HANDSHAKE_CHUNK, Cleartext/binary>> -> {RecvParams, RecvSeq + 1, {ok, Cleartext}}; + OtherChunk when is_binary(OtherChunk) -> + {RecvParams, RecvSeq + 1, {error, decrypt_error}}; #params{} = RecvParams_1 -> recv_and_decrypt_chunk(RecvParams_1, 0); - _ -> - error(decrypt_error) + error -> + {RecvParams, RecvSeq, {error, decrypt_error}} end; Error -> {RecvParams, RecvSeq, Error} @@ -1001,8 +1137,9 @@ output_handler(Params, Seq) -> output_handler_data(Params, Seq); dist_tick -> output_handler_tick(Params, Seq); - _Other -> + Other -> %% Ignore + _ = trace(Other), output_handler(Params, Seq) end end. @@ -1015,14 +1152,15 @@ output_handler_data(Params, Seq) -> output_handler_data(Params, Seq); dist_tick -> output_handler_data(Params, Seq); - _Other -> + Other -> %% Ignore + _ = trace(Other), output_handler_data(Params, Seq) end after 0 -> DistHandle = Params#params.dist_handle, Q = get_data(DistHandle, empty_q()), - {Params_1, Seq_1} = output_handler_send(Params, Seq, Q, true), + {Params_1, Seq_1} = output_handler_send(Params, Seq, Q), erlang:dist_ctrl_get_data_notification(DistHandle), output_handler(Params_1, Seq_1) end. @@ -1035,39 +1173,56 @@ output_handler_tick(Params, Seq) -> output_handler_data(Params, Seq); dist_tick -> output_handler_tick(Params, Seq); - _Other -> + Other -> %% Ignore + _ = trace(Other), output_handler_tick(Params, Seq) end after 0 -> - TickSize = 8 + rand:uniform(56), + TickSize = 7 + rand:uniform(56), TickData = binary:copy(<<0>>, TickSize), - {Params_1, Seq_1} = - encrypt_and_send_chunk(Params, Seq, [?TICK_CHUNK, TickData]), - output_handler(Params_1, Seq_1) + case + encrypt_and_send_chunk(Params, Seq, [?TICK_CHUNK, TickData]) + of + {Params_1, Seq_1, ok} -> + output_handler(Params_1, Seq_1); + {_, _, Error} -> + _ = trace(Error), + death_row() + end end. -output_handler_send( - #params{dist_handle = DistHandle} = Params, Seq, {_, Size, _} = Q, Retry) -> - %% +output_handler_send(Params, Seq, {_, Size, _} = Q) -> if ?CHUNK_SIZE < Size -> - {Cleartext, Q_1} = deq_iovec(?CHUNK_SIZE, Q), - {Params_1, Seq_1} = - encrypt_and_send_chunk(Params, Seq, [?DATA_CHUNK, Cleartext]), - output_handler_send(Params_1, Seq_1, Q_1, Retry); - Retry -> - Q_1 = get_data(DistHandle, Q), - output_handler_send(Params, Seq, Q_1, false); + output_handler_send(Params, Seq, Q, ?CHUNK_SIZE); true -> - {Cleartext, _} = deq_iovec(Size, Q), - encrypt_and_send_chunk(Params, Seq, [?DATA_CHUNK, Cleartext]) + case get_data(Params#params.dist_handle, Q) of + {_, 0, _} -> + {Params, Seq}; + {_, Size, _} = Q_1 -> % Got no more + output_handler_send(Params, Seq, Q_1, Size); + Q_1 -> + output_handler_send(Params, Seq, Q_1) + end + end. + +output_handler_send(Params, Seq, Q, Size) -> + {Cleartext, Q_1} = deq_iovec(Size, Q), + case + encrypt_and_send_chunk(Params, Seq, [?DATA_CHUNK, Cleartext]) + of + {Params_1, Seq_1, ok} -> + output_handler_send(Params_1, Seq_1, Q_1); + {_, _, Error} -> + _ = trace(Error), + death_row() end. %% ------------------------------------------------------------------------- %% Input handler process %% -%% Here is T 0 or infinity to steer if we should try to receive +%% Here is T = 0|infinity to steer if we should try to receive %% more data or not; start with infinity, and when we get some %% data try with 0 to see if more is waiting @@ -1086,11 +1241,12 @@ input_handler(#params{socket = Socket} = Params, Seq, Q, T) -> end, input_handler(Params, Seq, Q_1, infinity); {tcp, Socket, Chunk} -> - input_chunk(Params, Seq, Q, Chunk); + input_chunk(Params, Seq, Q, T, Chunk); {tcp_closed, Socket} -> - error(connection_closed); - _Other -> + exit(connection_closed); + Other -> %% Ignore... + _ = trace(Other), input_handler(Params, Seq, Q, T) end after T -> @@ -1098,16 +1254,20 @@ input_handler(#params{socket = Socket} = Params, Seq, Q, T) -> input_handler(Params, Seq, Q_1, infinity) end. -input_chunk(Params, Seq, Q, Chunk) -> +input_chunk(Params, Seq, Q, T, Chunk) -> case decrypt_chunk(Params, Seq, Chunk) of <<?DATA_CHUNK, Cleartext/binary>> -> input_handler(Params, Seq + 1, enq_binary(Cleartext, Q), 0); <<?TICK_CHUNK, _/binary>> -> - input_handler(Params, Seq + 1, Q, 0); + input_handler(Params, Seq + 1, Q, T); + OtherChunk when is_binary(OtherChunk) -> + _ = trace(invalid_chunk), + exit(connection_closed); #params{} = Params_1 -> - input_handler(Params_1, 0, Q, 0); - _ -> - error(decrypt_error) + input_handler(Params_1, 0, Q, T); + error -> + _ = trace(decrypt_error), + exit(connection_closed) end. %% ------------------------------------------------------------------------- @@ -1198,64 +1358,110 @@ deliver_data(DistHandle, Front, Size, Rear, Bin) -> encrypt_and_send_chunk( #params{ - socket = Socket, rekey_interval = Seq, - key = Key, iv = IV, hash_algorithm = HashAlgorithm} = Params, + socket = Socket, + rekey_interval = Seq, + rekey_key = PubKeyB, + key = Key, + iv = {IVSalt, IVNo}, + hmac_algorithm = HmacAlgo} = Params, Seq, Cleartext) -> %% KeyLen = byte_size(Key), - IVLen = byte_size(IV), - Chunk = <<IV_1:IVLen/binary, KeySalt:KeyLen/binary>> = - crypto:strong_rand_bytes(IVLen + KeyLen), - ok = gen_tcp:send(Socket, encrypt_chunk(Params, Seq, [?REKEY_CHUNK, Chunk])), - Key_1 = hash_key(HashAlgorithm, Key, KeySalt), - Params_1 = Params#params{key = Key_1, iv = IV_1}, - ok = gen_tcp:send(Socket, encrypt_chunk(Params_1, 0, Cleartext)), - {Params_1, 1}; + IVSaltLen = byte_size(IVSalt), + #key_pair{public = PubKeyA} = KeyPair = get_new_key_pair(), + case + gen_tcp:send( + Socket, encrypt_chunk(Params, Seq, [?REKEY_CHUNK, PubKeyA])) + of + ok -> + SharedSecret = compute_shared_secret(KeyPair, PubKeyB), + IV = <<(IVNo + Seq):48>>, + {Key_1, <<IVSalt_1:IVSaltLen/binary, IVNo_1:48>>} = + hmac_key_iv( + HmacAlgo, SharedSecret, [Key, IVSalt, IV], + KeyLen, IVSaltLen + 6), + Params_1 = Params#params{key = Key_1, iv = {IVSalt_1, IVNo_1}}, + Result = + gen_tcp:send(Socket, encrypt_chunk(Params_1, 0, Cleartext)), + {Params_1, 1, Result}; + SendError -> + {Params, Seq + 1, SendError} + end; encrypt_and_send_chunk(#params{socket = Socket} = Params, Seq, Cleartext) -> - ok = gen_tcp:send(Socket, encrypt_chunk(Params, Seq, Cleartext)), - {Params, Seq + 1}. + Result = gen_tcp:send(Socket, encrypt_chunk(Params, Seq, Cleartext)), + {Params, Seq + 1, Result}. encrypt_chunk( #params{ - block_crypto = BlockCrypto, - iv = IV, key = Key, tag_len = TagLen}, Seq, Cleartext) -> + aead_cipher = AeadCipher, + iv = {IVSalt, IVNo}, key = Key, tag_len = TagLen}, Seq, Cleartext) -> %% ChunkLen = iolist_size(Cleartext) + TagLen, AAD = <<Seq:32, ChunkLen:32>>, + IVBin = <<IVSalt/binary, (IVNo + Seq):48>>, {Ciphertext, CipherTag} = - crypto:block_encrypt( - crypto_cipher_name(BlockCrypto), Key, IV, {AAD, Cleartext, TagLen}), + crypto:block_encrypt(AeadCipher, Key, IVBin, {AAD, Cleartext, TagLen}), Chunk = [Ciphertext,CipherTag], Chunk. decrypt_chunk( #params{ - block_crypto = BlockCrypto, - iv = IV, key = Key, tag_len = TagLen} = Params, Seq, Chunk) -> + aead_cipher = AeadCipher, + iv = {IVSalt, IVNo}, key = Key, tag_len = TagLen} = Params, Seq, Chunk) -> %% ChunkLen = byte_size(Chunk), - true = TagLen =< ChunkLen, % Assert - AAD = <<Seq:32, ChunkLen:32>>, - CiphertextLen = ChunkLen - TagLen, - <<Ciphertext:CiphertextLen/binary, CipherTag:TagLen/binary>> = Chunk, - block_decrypt( - Params, Seq, crypto_cipher_name(BlockCrypto), - Key, IV, {AAD, Ciphertext, CipherTag}). + if + ChunkLen < TagLen -> + error; + true -> + AAD = <<Seq:32, ChunkLen:32>>, + IVBin = <<IVSalt/binary, (IVNo + Seq):48>>, + CiphertextLen = ChunkLen - TagLen, + case Chunk of + <<Ciphertext:CiphertextLen/binary, + CipherTag:TagLen/binary>> -> + block_decrypt( + Params, Seq, AeadCipher, Key, IVBin, + {AAD, Ciphertext, CipherTag}); + _ -> + error + end + end. block_decrypt( - #params{rekey_interval = Seq} = Params, Seq, CipherName, Key, IV, Data) -> + #params{ + rekey_key = #key_pair{public = PubKeyA} = KeyPair, + rekey_interval = RekeyInterval} = Params, + Seq, AeadCipher, Key, IV, Data) -> %% - KeyLen = byte_size(Key), - IVLen = byte_size(IV), - case crypto:block_decrypt(CipherName, Key, IV, Data) of - <<?REKEY_CHUNK, IV_1:IVLen/binary, KeySalt:KeyLen/binary>> -> - Key_1 = hash_key(Params#params.hash_algorithm, Key, KeySalt), - Params#params{iv = IV_1, key = Key_1}; - _ -> - error(decrypt_error) - end; -block_decrypt(_Params, _Seq, CipherName, Key, IV, Data) -> - crypto:block_decrypt(CipherName, Key, IV, Data). + case crypto:block_decrypt(AeadCipher, Key, IV, Data) of + <<?REKEY_CHUNK, Rest/binary>> -> + PubKeyLen = byte_size(PubKeyA), + case Rest of + <<PubKeyB:PubKeyLen/binary>> -> + SharedSecret = compute_shared_secret(KeyPair, PubKeyB), + KeyLen = byte_size(Key), + IVLen = byte_size(IV), + IVSaltLen = IVLen - 6, + {Key_1, <<IVSalt:IVSaltLen/binary, IVNo:48>>} = + hmac_key_iv( + Params#params.hmac_algorithm, + SharedSecret, [Key, IV], KeyLen, IVLen), + Params#params{iv = {IVSalt, IVNo}, key = Key_1}; + _ -> + error + end; + Chunk when is_binary(Chunk) -> + case Seq of + RekeyInterval -> + %% This was one chunk too many without rekeying + error; + _ -> + Chunk + end; + error -> + error + end. %% ------------------------------------------------------------------------- %% Queue of binaries i.e an iovec queue @@ -1289,34 +1495,46 @@ deq_iovec(GetSize, [Bin|Front], Size, Rear, Acc) -> %% ------------------------------------------------------------------------- +death_row() -> death_row(connection_closed). +%% +death_row(normal) -> death_row(connection_closed); +death_row(Reason) -> receive after 5000 -> exit(Reason) end. + +%% ------------------------------------------------------------------------- + %% Trace point trace(Term) -> Term. %% Keep an eye on this Pid (debug) +-ifndef(undefined). +monitor_dist_proc(Pid) -> + Pid. +-else. monitor_dist_proc(Pid) -> -%%% spawn( -%%% fun () -> -%%% MRef = erlang:monitor(process, Pid), -%%% receive -%%% {'DOWN', MRef, _, _, normal} -> -%%% error_logger:error_report( -%%% [dist_proc_died, -%%% {reason, normal}, -%%% {pid, Pid}]); -%%% {'DOWN', MRef, _, _, Reason} -> -%%% error_logger:info_report( -%%% [dist_proc_died, -%%% {reason, Reason}, -%%% {pid, Pid}]) -%%% end -%%% end), + spawn( + fun () -> + MRef = erlang:monitor(process, Pid), + receive + {'DOWN', MRef, _, _, normal} -> + error_logger:error_report( + [dist_proc_died, + {reason, normal}, + {pid, Pid}]); + {'DOWN', MRef, _, _, Reason} -> + error_logger:info_report( + [dist_proc_died, + {reason, Reason}, + {pid, Pid}]) + end + end), Pid. +-endif. dbg() -> dbg:stop(), dbg:tracer(), dbg:p(all, c), - dbg:tpl(?MODULE, cx), + dbg:tpl(?MODULE, trace, cx), dbg:tpl(erlang, dist_ctrl_get_data_notification, cx), dbg:tpl(erlang, dist_ctrl_get_data, cx), dbg:tpl(erlang, dist_ctrl_put_data, cx), diff --git a/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl b/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl index 907de1abe2..6ce34ce7fa 100644 --- a/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl +++ b/lib/ssl/test/openssl_server_cipher_suite_SUITE.erl @@ -185,7 +185,13 @@ init_per_group(GroupName, Config) -> true -> case ssl_test_lib:supports_ssl_tls_version(GroupName) of true -> - do_init_per_group(GroupName, Config); + case ssl_test_lib:check_sane_openssl_version(GroupName) of + true -> + ssl_test_lib:init_tls_version(GroupName, Config), + do_init_per_group(GroupName, Config); + false -> + {skip, openssl_does_not_support_version} + end; false -> {skip, {openssl_does_not_support, GroupName}} end; diff --git a/lib/ssl/test/ssl_dist_bench_SUITE.erl b/lib/ssl/test/ssl_dist_bench_SUITE.erl index 1fea6f6f72..67944c74d2 100644 --- a/lib/ssl/test/ssl_dist_bench_SUITE.erl +++ b/lib/ssl/test/ssl_dist_bench_SUITE.erl @@ -169,16 +169,10 @@ end_per_suite(Config) -> init_per_group(ssl, Config) -> [{ssl_dist, true}, {ssl_dist_prefix, "SSL"}|Config]; init_per_group(crypto, Config) -> - case inet_crypto_dist:is_supported() of - true -> - [{ssl_dist, false}, {ssl_dist_prefix, "Crypto"}, - {ssl_dist_args, - "-proto_dist inet_crypto " - "-inet_crypto '#{secret => \"123456\"}'"} - |Config]; - false -> - {skip, "Not supported on this OTP version"} - end; + [{ssl_dist, false}, {ssl_dist_prefix, "Crypto"}, + {ssl_dist_args, + "-proto_dist inet_crypto"} + |Config]; init_per_group(plain, Config) -> [{ssl_dist, false}, {ssl_dist_prefix, "Plain"}|Config]; init_per_group(_GroupName, Config) -> diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 98070f794c..3c66ffd852 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 9.2.2 +SSL_VSN = 9.3 diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 65650a25c7..605a9f224d 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,265 @@ </header> <p>This document describes the changes made to the STDLIB application.</p> +<section><title>STDLIB 3.9</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix a bug in <c>string:lexemes/2</c>. </p> <p> The + bug was found when optimizing the handling of deep lists + of Unicode characters in the <c>string</c> module. </p> + <p> + Own Id: OTP-15649</p> + </item> + <item> + <p>A bug has been fixed in the <c>maps</c> implementation + that could cause a crash or memory usage to grow until + the machine ran out of memory. This could happen when + inserting a new key-value pair with a key <c>K1</c> + containing a binary <c>B1</c> into a map <c>M</c> having + a key <c>K2</c> with a binary <c>B2</c> if the following + conditions were met:</p> <list> <item><c>B1 =/= + B2</c></item> <item><c>size(B1) >= 4294967296</c></item> + <item><c>size(B2) >= 4294967296</c></item> + <item><c>size(M) >= 32</c></item> <item><c>(size(B1) rem + 4294967296) == (size(B2) rem 4294967296)</c></item> + <item>the first <c>(size(B1) rem 4294967296)</c> bytes + are the same both in <c>B1</c> and <c>B2</c></item> + <item>substituting <c>B1</c> in <c>K1</c> with <c>B2</c> + would create a term with the same value as + <c>K2</c></item> </list> <p>The root cause of the problem + is that the <c>maps</c> implementation only hashed the + first <c>(X rem 4294967296)</c> bytes of binaries so that + different binaries could get the same hash value + independently of the hash seed.</p> + <p> + Own Id: OTP-15707</p> + </item> + <item> + <p> Since the introduction of the stack trace variable, + the Erlang Pretty Printer has left out the exception + class <c>throw</c> even when the stack trace variable + cannot be left out, which is not correct Erlang code. The + fix is to always include the exception class + <c>throw</c>. </p> + <p> + Own Id: OTP-15751</p> + </item> + <item> + <p><c>record_info/2</c> is a pseudo-function that + requires literal arguments known at compile time. + Therefore, the following usage is illegal: <c>fun + record/info/2</c>. The compiler would crash when during + compilation of that kind of code. Corrected to issue a + compilation error.</p> + <p> + Own Id: OTP-15760 Aux Id: ERL-907 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> A new <c>rand</c> module algorithm, <c>exro928ss</c> + (Xoroshiro928**), has been implemented. It has got a + really long period and good statistical quality for all + output bits, while still being only about 50% slower than + the default algorithm. </p><p> The same generator is also + used as a long period counter in a new <c>crypto</c> + plugin for the <c>rand</c> module, algorithm + <c>crypto_aes</c>. This plugin uses AES-256 to scramble + the counter which buries any detectable statistical + artifacts. Scrambling is done in chunks which are cached + to get good amortized speed (about half of the default + algorithm). </p> + <p> + Own Id: OTP-14461 Aux Id: PR-1857 </p> + </item> + <item> + <p> + Types related to server naming and starting have been + exported from <c>gen_statem</c>. These are: + <c>server_name/0</c>, <c>server_ref/0</c>, + <c>start_opt/0</c>, <c>start_ret/0</c> and + <c>enter_loop_opt/0</c>.</p> + <p> + Own Id: OTP-14724 Aux Id: PR-2056 </p> + </item> + <item> + <p> + The default algorithm for the <c>rand</c> module has been + changed to <c>exsss</c> (Xorshift116**) which is a + combination of the Xorshift116 (<c>exsp</c>) state update + and a new scrambler "StarStar" from the 2018 paper + "Scrambled Linear Pseudorandom Number Generators" by + David Blackman and Sebastiano Vigna. This combination + should not have the caveat of weak low bits that the + previous default algorithm(s) have had, with the cost of + about 10% lower speed. See GitHub pull request #1969.</p> + <p> + Own Id: OTP-14731 Aux Id: PR-1969 </p> + </item> + <item> + <p> + The generic state machine behaviour <c>gen_statem</c> has + gotten code cleanup and documentation improvements from + GitHub Pull Request #1855, even though the PR itself was + rejected.</p> + <p> + Own Id: OTP-14737 Aux Id: PR-1855 </p> + </item> + <item> + <p> + Update Unicode specification to version 11.0.</p> + <p> + Own Id: OTP-15111</p> + </item> + <item> + <p> + ETS option <c>write_concurrency</c> now also affects and + improves the scalability of <c>ordered_set</c> tables. + The implementation is based on a data structure called + contention adapting search tree, where the lock + granularity adapts to the actual amount of concurrency + exploited by the applications in runtime.</p> + <p> + Own Id: OTP-15128</p> + </item> + <item> + <p> + Optimized <c>maps:new/0</c> with trivial Erlang + implementation, making use of literal terms (the empty + map) not needing dynamic heap allocation.</p> + <p> + Own Id: OTP-15200 Aux Id: PR-1878 </p> + </item> + <item> + <p>The <c>gen_*</c> behaviours have been changed so that + if logging of the last N messages through + <c>sys:log/2,3</c> is active for the server, this log is + included in the terminate report.</p> <p>To accomplish + this the format of "System Events" as defined in the man + page for <c>sys</c> has been clarified and cleaned up, a + new function <c>sys:get_log/1</c> has been added, and + <c>sys:get_debug/3</c> has been deprecated. Due to these + changes, code that relies on the internal badly + documented format of "System Events", need to be + corrected.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15381</p> + </item> + <item> + <p> + The <c>gen_statem</c> behaviour engine loop has been + optimized for better performance in particular when the + callback module returns some actions, that is better + performance for more realistic applications than the Echo + Benchmark.</p> + <p> + Own Id: OTP-15452</p> + </item> + <item> + <p> Do not allow function specifications for functions + residing in other modules. </p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15563 Aux Id: ERL-845, OTP-15562 </p> + </item> + <item> + <p> + The <c>persistent_term</c> functions <c>put/2</c> and + <c>erase/1</c> are now yielding.</p> + <p> + Own Id: OTP-15615</p> + </item> + <item> + <p>Previously, all ETS tables used centralized counter + variables to keep track of the number of items stored and + the amount of memory consumed. These counters can cause + scalability problems (especially on big NUMA systems). + This change adds an implementation of a decentralized + counter and modifies the implementation of ETS so that + ETS tables of type <c>ordered_set</c> with + <c>write_concurrency</c> enabled use the decentralized + counter. Experiments indicate that this change + substantially improves the scalability of ETS + <c>ordered_set</c> tables with <c>write_concurrency</c> + enabled in scenarios with frequent <c>ets:insert/2</c> + and <c>ets:delete/2</c> calls.</p> + <p> + Own Id: OTP-15623 Aux Id: PR-2190 </p> + </item> + <item> + <p> Use <c>ssh</c> instead of <c>rsh</c> as the default + remote shell. </p> + <p> + Own Id: OTP-15633 Aux Id: PR-1787 </p> + </item> + <item> + <p>Added <c>beam_lib:strip/2</c> and friends, which + accept a list of chunks that should be preserved when + stripping.</p> + <p> + Own Id: OTP-15680 Aux Id: PR-2114 </p> + </item> + <item> + <p> Optimize printing of maps with <c>io_lib:write()</c>. + Also optimize pretty printing of strings (<c>~s</c> and + <c>~ts</c>) when limiting the output with the + <c>chars_limit</c> option. </p> + <p> + Own Id: OTP-15705</p> + </item> + <item> + <p> There are new compiler options <c>nowarn_removed</c> + and <c>{nowarn_removed,Items}</c> to suppress warnings + for functions and modules that have been removed from + OTP.</p> + <p> + Own Id: OTP-15749 Aux Id: ERL-904 </p> + </item> + <item> + <p> Let the Erlang Pretty Printer put atomic parts on the + same line. </p> + <p> + Own Id: OTP-15755</p> + </item> + <item> + <p> Add option <c>quote_singleton_atom_types</c> to the + Erlang Pretty Printer's functions. Setting the option to + <c>true</c> adds quotes to all singleton atom types. </p> + <p> + Own Id: OTP-15756</p> + </item> + </list> + </section> + +</section> + +<section><title>STDLIB 3.8.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A bug in gen_statem has been fixed where the internal + timeout message could arrive as an info to the callback + module during high load due to incorrect use of + asynchronous timer cancel.</p> + <p> + Own Id: OTP-15295</p> + </item> + </list> + </section> + +</section> + <section><title>STDLIB 3.8.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl index 2b5a374cf2..21d66c5529 100644 --- a/lib/stdlib/src/io_lib.erl +++ b/lib/stdlib/src/io_lib.erl @@ -412,14 +412,25 @@ write_port(Port) -> write_ref(Ref) -> erlang:ref_to_list(Ref). +write_map(_, 1, _E) -> "#{}"; write_map(Map, D, E) when is_integer(D) -> - [$#,${,write_map_body(maps:to_list(Map), D, D - 1, E),$}]. + I = maps:iterator(Map), + case maps:next(I) of + {K, V, NextI} -> + D0 = D - 1, + W = write_map_assoc(K, V, D0, E), + [$#,${,[W | write_map_body(NextI, D0, D0, E)],$}]; + none -> "#{}" + end. -write_map_body(_, 1, _D0, _E) -> "..."; -write_map_body([], _, _D0, _E) -> []; -write_map_body([{K,V}], _D, D0, E) -> write_map_assoc(K, V, D0, E); -write_map_body([{K,V}|KVs], D, D0, E) -> - [write_map_assoc(K, V, D0, E),$, | write_map_body(KVs, D - 1, D0, E)]. +write_map_body(_, 1, _D0, _E) -> ",..."; +write_map_body(I, D, D0, E) -> + case maps:next(I) of + {K, V, NextI} -> + W = write_map_assoc(K, V, D0, E), + [$,,W|write_map_body(NextI, D - 1, D0, E)]; + none -> "" + end. write_map_assoc(K, V, D, E) -> [write1(K, D, E)," => ",write1(V, D, E)]. diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl index d1aa4cd157..157cc07e19 100644 --- a/lib/stdlib/src/io_lib_format.erl +++ b/lib/stdlib/src/io_lib_format.erl @@ -327,11 +327,11 @@ indentation([], I) -> I. %% PadChar, Encoding, StringP, ChrsLim, Indentation) -> String %% These are the dispatch functions for the various formatting controls. -control_small($s, [A], F, Adj, P, Pad, latin1) when is_atom(A) -> +control_small($s, [A], F, Adj, P, Pad, latin1=Enc) when is_atom(A) -> L = iolist_to_chars(atom_to_list(A)), - string(L, F, Adj, P, Pad); -control_small($s, [A], F, Adj, P, Pad, unicode) when is_atom(A) -> - string(atom_to_list(A), F, Adj, P, Pad); + string(L, F, Adj, P, Pad, Enc); +control_small($s, [A], F, Adj, P, Pad, unicode=Enc) when is_atom(A) -> + string(atom_to_list(A), F, Adj, P, Pad, Enc); control_small($e, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> fwrite_e(A, F, Adj, P, Pad); control_small($f, [A], F, Adj, P, Pad, _Enc) when is_float(A) -> @@ -371,12 +371,12 @@ control_small($n, [], F, Adj, P, Pad, _Enc) -> newline(F, Adj, P, Pad); control_small($i, [_A], _F, _Adj, _P, _Pad, _Enc) -> []; control_small(_C, _As, _F, _Adj, _P, _Pad, _Enc) -> not_small. -control_limited($s, [L0], F, Adj, P, Pad, latin1, _Str, CL, _I) -> - L = iolist_to_chars(L0), - string(limit_string(L, F, CL), limit_field(F, CL), Adj, P, Pad); -control_limited($s, [L0], F, Adj, P, Pad, unicode, _Str, CL, _I) -> - L = cdata_to_chars(L0), - uniconv(string(limit_string(L, F, CL), limit_field(F, CL), Adj, P, Pad)); +control_limited($s, [L0], F, Adj, P, Pad, latin1=Enc, _Str, CL, _I) -> + L = iolist_to_chars(L0, F, CL), + string(L, limit_field(F, CL), Adj, P, Pad, Enc); +control_limited($s, [L0], F, Adj, P, Pad, unicode=Enc, _Str, CL, _I) -> + L = cdata_to_chars(L0, F, CL), + uniconv(string(L, limit_field(F, CL), Adj, P, Pad, Enc)); control_limited($w, [A], F, Adj, P, Pad, Enc, _Str, CL, _I) -> Chars = io_lib:write(A, [{depth, -1}, {encoding, Enc}, {chars_limit, CL}]), term(Chars, F, Adj, P, Pad); @@ -718,7 +718,10 @@ fwrite_g(Fl, F, Adj, P, Pad) when P >= 1 -> end. -%% iolist_to_chars(iolist()) -> io_lib:chars() +iolist_to_chars(Cs, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> + iolist_to_chars(Cs); +iolist_to_chars(Cs, _, CharsLimit) -> + limit_iolist_to_chars(Cs, sub(CharsLimit, 3), [], normal). % three dots iolist_to_chars([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 -> [C | iolist_to_chars(Cs)]; @@ -729,12 +732,34 @@ iolist_to_chars([]) -> iolist_to_chars(B) when is_binary(B) -> binary_to_list(B). -%% cdata() :: clist() | cbinary() -%% clist() :: maybe_improper_list(char() | cbinary() | clist(), -%% cbinary() | nil()) -%% cbinary() :: unicode:unicode_binary() | unicode:latin1_binary() +limit_iolist_to_chars(Cs, 0, S, normal) -> + L = limit_iolist_to_chars(Cs, 4, S, final), + case iolist_size(L) of + N when N < 4 -> L; + 4 -> "..." + end; +limit_iolist_to_chars(_Cs, 0, _S, final) -> []; +limit_iolist_to_chars([C|Cs], Limit, S, Mode) when C >= $\000, C =< $\377 -> + [C | limit_iolist_to_chars(Cs, Limit - 1, S, Mode)]; +limit_iolist_to_chars([I|Cs], Limit, S, Mode) -> + limit_iolist_to_chars(I, Limit, [Cs|S], Mode); +limit_iolist_to_chars([], _Limit, [], _Mode) -> + []; +limit_iolist_to_chars([], Limit, [Cs|S], Mode) -> + limit_iolist_to_chars(Cs, Limit, S, Mode); +limit_iolist_to_chars(B, Limit, S, Mode) when is_binary(B) -> + case byte_size(B) of + Sz when Sz > Limit -> + {B1, B2} = split_binary(B, Limit), + [binary_to_list(B1) | limit_iolist_to_chars(B2, 0, S, Mode)]; + Sz -> + [binary_to_list(B) | limit_iolist_to_chars([], Limit-Sz, S, Mode)] + end. -%% cdata_to_chars(cdata()) -> io_lib:chars() +cdata_to_chars(Cs, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> + cdata_to_chars(Cs); +cdata_to_chars(Cs, _, CharsLimit) -> + limit_cdata_to_chars(Cs, sub(CharsLimit, 3), normal). % three dots cdata_to_chars([C|Cs]) when is_integer(C), C >= $\000 -> [C | cdata_to_chars(Cs)]; @@ -748,11 +773,25 @@ cdata_to_chars(B) when is_binary(B) -> _ -> binary_to_list(B) end. -limit_string(S, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> S; -limit_string(S, _F, CharsLimit) -> - case io_lib:chars_length(S) =< CharsLimit of - true -> S; - false -> [string:slice(S, 0, sub(CharsLimit, 3)), "..."] +limit_cdata_to_chars(Cs, 0, normal) -> + L = limit_cdata_to_chars(Cs, 4, final), + case string:length(L) of + N when N < 4 -> L; + 4 -> "..." + end; +limit_cdata_to_chars(_Cs, 0, final) -> []; +limit_cdata_to_chars(Cs, Limit, Mode) -> + case string:next_grapheme(Cs) of + {error, <<C,Cs1/binary>>} -> + %% This is how ~ts handles Latin1 binaries with option + %% chars_limit. + [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; + {error, [C|Cs1]} -> % not all versions of module string return this + [C | limit_cdata_to_chars(Cs1, Limit - 1, Mode)]; + [] -> + []; + [GC|Cs1] -> + [GC | limit_cdata_to_chars(Cs1, Limit - 1, Mode)] end. limit_field(F, CharsLimit) when CharsLimit < 0; F =:= none -> @@ -762,30 +801,30 @@ limit_field(F, CharsLimit) -> %% string(String, Field, Adjust, Precision, PadChar) -string(S, none, _Adj, none, _Pad) -> S; -string(S, F, Adj, none, Pad) -> - string_field(S, F, Adj, io_lib:chars_length(S), Pad); -string(S, none, _Adj, P, Pad) -> - string_field(S, P, left, io_lib:chars_length(S), Pad); -string(S, F, Adj, P, Pad) when F >= P -> +string(S, none, _Adj, none, _Pad, _Enc) -> S; +string(S, F, Adj, none, Pad, Enc) -> + string_field(S, F, Adj, io_lib:chars_length(S), Pad, Enc); +string(S, none, _Adj, P, Pad, Enc) -> + string_field(S, P, left, io_lib:chars_length(S), Pad, Enc); +string(S, F, Adj, P, Pad, Enc) when F >= P -> N = io_lib:chars_length(S), if F > P -> if N > P -> - adjust(flat_trunc(S, P), chars(Pad, F-P), Adj); + adjust(flat_trunc(S, P, Enc), chars(Pad, F-P), Adj); N < P -> adjust([S|chars(Pad, P-N)], chars(Pad, F-P), Adj); true -> % N == P adjust(S, chars(Pad, F-P), Adj) end; true -> % F == P - string_field(S, F, Adj, N, Pad) + string_field(S, F, Adj, N, Pad, Enc) end. -string_field(S, F, _Adj, N, _Pad) when N > F -> - flat_trunc(S, F); -string_field(S, F, Adj, N, Pad) when N < F -> +string_field(S, F, _Adj, N, _Pad, Enc) when N > F -> + flat_trunc(S, F, Enc); +string_field(S, F, Adj, N, Pad, _Enc) when N < F -> adjust(S, chars(Pad, F-N), Adj); -string_field(S, _, _, _, _) -> % N == F +string_field(S, _, _, _, _, _) -> % N == F S. %% unprefixed_integer(Int, Field, Adjust, Base, PadChar, Lowercase) @@ -837,7 +876,10 @@ adjust(Data, Pad, right) -> [Pad|Data]. %% Flatten and truncate a deep list to at most N elements. -flat_trunc(List, N) when is_integer(N), N >= 0 -> +flat_trunc(List, N, latin1) when is_integer(N), N >= 0 -> + {S, _} = lists:split(N, lists:flatten(List)), + S; +flat_trunc(List, N, unicode) when is_integer(N), N >= 0 -> string:slice(List, 0, N). %% A deep version of lists:duplicate/2 diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl index 8f2fd7ea8f..b1a5991bf0 100644 --- a/lib/stdlib/src/io_lib_pretty.erl +++ b/lib/stdlib/src/io_lib_pretty.erl @@ -720,55 +720,40 @@ printable_list(_L, 1, _T, _Enc) -> false; printable_list(L, _D, T, latin1) when T < 0 -> io_lib:printable_latin1_list(L); -printable_list(L, _D, T, Enc) when T >= 0 -> - case slice(L, tsub(T, 2), Enc) of - false -> - false; - {prefix, Prefix} when Enc =:= latin1 -> - io_lib:printable_latin1_list(Prefix) andalso {true, Prefix}; - {prefix, Prefix} -> - %% Probably an overestimation. - io_lib:printable_list(Prefix) andalso {true, Prefix}; - all when Enc =:= latin1 -> - io_lib:printable_latin1_list(L); +printable_list(L, _D, T, latin1) when T >= 0 -> + N = tsub(T, 2), + case printable_latin1_list(L, N) of all -> - io_lib:printable_list(L) - end; -printable_list(L, _D, T, _Uni) when T < 0-> - io_lib:printable_list(L). - -slice(L, N, latin1) -> - try lists:split(N, L) of - {_, []} -> - all; - {[], _} -> - false; - {L1, _} -> - {prefix, L1} - catch - _:_ -> - all + true; + 0 -> + {L1, _} = lists:split(N, L), + {true, L1}; + _NC -> + false end; -slice(L, N, _Uni) -> +printable_list(L, _D, T, _Unicode) when T >= 0 -> + N = tsub(T, 2), %% Be careful not to traverse more of L than necessary. try string:slice(L, 0, N) of "" -> false; Prefix -> - %% Assume no binaries are introduced by string:slice(). case is_flat(L, lists:flatlength(Prefix)) of true -> case string:equal(Prefix, L) of true -> - all; + io_lib:printable_list(L); false -> - {prefix, Prefix} + io_lib:printable_list(Prefix) + andalso {true, Prefix} end; false -> false end catch _:_ -> false - end. + end; +printable_list(L, _D, T, _Uni) when T < 0-> + io_lib:printable_list(L). is_flat(_L, 0) -> true; @@ -845,7 +830,7 @@ printable_bin1(Bin, Start, Len) -> end. %% -> all | integer() >=0. Adopted from io_lib.erl. -% printable_latin1_list([_ | _], 0) -> 0; +printable_latin1_list([_ | _], 0) -> 0; printable_latin1_list([C | Cs], N) when C >= $\s, C =< $~ -> printable_latin1_list(Cs, N - 1); printable_latin1_list([C | Cs], N) when C >= $\240, C =< $\377 -> diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src index 9cd425db9a..ecb514e9f3 100644 --- a/lib/stdlib/src/stdlib.app.src +++ b/lib/stdlib/src/stdlib.app.src @@ -108,7 +108,7 @@ dets]}, {applications, [kernel]}, {env, []}, - {runtime_dependencies, ["sasl-3.0","kernel-6.0","erts-@OTP-15128@","crypto-3.3", + {runtime_dependencies, ["sasl-3.0","kernel-6.0","erts-10.4","crypto-3.3", "compiler-5.0"]} ]}. diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 08612ed17f..7038cc159c 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -19,22 +19,15 @@ %% %% We allow upgrade from, and downgrade to all previous %% versions from the following OTP releases: -%% - OTP 20 %% - OTP 21 +%% - OTP 22 %% %% We also allow upgrade from, and downgrade to all %% versions that have branched off from the above %% stated previous versions. %% {"%VSN%", - [{<<"^3\\.4$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.5$">>,[restart_new_emulator]}, + [{<<"^3\\.5$">>,[restart_new_emulator]}, {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.6$">>,[restart_new_emulator]}, @@ -43,15 +36,10 @@ {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.8$">>,[restart_new_emulator]}, - {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}], - [{<<"^3\\.4$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, - {<<"^3\\.5$">>,[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\\.5$">>,[restart_new_emulator]}, {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.6$">>,[restart_new_emulator]}, @@ -60,4 +48,6 @@ {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}, {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}, {<<"^3\\.8$">>,[restart_new_emulator]}, - {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[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]}]}. diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index 824f5d19f2..9b6d8d7401 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_15705/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_15705]. %% Error cases for output. error_1(Config) when is_list(Config) -> @@ -2504,9 +2504,11 @@ otp_14983(_Config) -> trunc_string() -> "str " = trf("str ", [], 10), - "str ..." = trf("str ~s", ["str"], 6), + "str str" = trf("str ~s", ["str"], 6), + "str ..." = trf("str ~s", ["str1"], 6), "str str" = trf("str ~s", ["str"], 7), - "str ..." = trf("str ~8s", ["str"], 6), + "str str" = trf("str ~8s", ["str"], 6), + "str ..." = trf("str ~8s", ["str1"], 6), Pa = filename:dirname(code:which(?MODULE)), {ok, UNode} = test_server:start_node(printable_range_unicode, slave, [{args, " +pc unicode -pa " ++ Pa}]), @@ -2680,3 +2682,29 @@ otp_15639(_Config) -> "\"12345678\"..." = pretty("123456789"++[x], UOpts), "[[...]|...]" = pretty(["1","2","3","4","5","6","7","8"], UOpts), ok. + +otp_15705(_Config) -> + L = [<<"an">>,["at"],[["om"]]], + "..." = trf("~s", [L], 0), + "..." = trf("~s", [L], 1), + "..." = trf("~s", [L], 2), + "..." = trf("~s", [L], 3), + "a..." = trf("~s", [L], 4), + "an..." = trf("~s", [L], 5), + "anatom" = trf("~s", [L], 6), + L2 = ["a",[<<"na">>],[["tom"]]], + "..." = trf("~s", [L2], 3), + "a..." = trf("~s", [L2], 4), + "an..." = trf("~s", [L2], 5), + "anatom" = trf("~s", [L2], 6), + + A = [[<<"äpple"/utf8>>, "plus", <<"äpple">>]], + "äp..." = trf("~ts", [A], 5), + "äppleplusäpple" = trf("~ts", [A], 14), + U = [["ки"],"рилл","и́ческий атом"], + "ки..." = trf("~ts", [U], 5), + "кирилли́ческий..." = trf("~ts", [U], 16), + "кирилли́ческий атом" = trf("~ts", [U], 20), + + "|кирилли́чес|" = trf("|~10ts|", [U], -1), + ok. diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 6471dc70e0..07224afdc9 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 3.8.1 +STDLIB_VSN = 3.9 diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml index 772f5e6e04..a2dd78f280 100644 --- a/lib/syntax_tools/doc/src/notes.xml +++ b/lib/syntax_tools/doc/src/notes.xml @@ -32,6 +32,34 @@ <p>This document describes the changes made to the Syntax_Tools application.</p> +<section><title>Syntax_Tools 2.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Correct links in the documentation. </p> + <p> + Own Id: OTP-15761</p> + </item> + </list> + </section> + +</section> + <section><title>Syntax_Tools 2.1.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk index 538c71dc24..0ace11772d 100644 --- a/lib/syntax_tools/vsn.mk +++ b/lib/syntax_tools/vsn.mk @@ -1 +1 @@ -SYNTAX_TOOLS_VSN = 2.1.7 +SYNTAX_TOOLS_VSN = 2.2 diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index 2191ebe2df..fd41e2cbeb 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -31,6 +31,49 @@ </header> <p>This document describes the changes made to the Tools application.</p> +<section><title>Tools 3.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add <c>cprof</c> and <c>tags</c> modules to .app file so + that they are included in releases.</p> + <p> + Own Id: OTP-15534 Aux Id: PR-2078 </p> + </item> + <item> + <p> + Improved documentation parsing in emacs erldoc + functionality.</p> + <p> + Own Id: OTP-15699 Aux Id: PR-2184 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>The <c>cover</c> tool now uses the <c>counters</c> + module instead of <c>ets</c> for updating the counters + for how many times a line has been executed. By default, + Cover will work with distributed nodes, but a new + function <c>cover:local_only/0</c> allows running the + Cover in a restricted but faster local-only mode.</p> + <p>The increase in speed will vary depending on the type + of code being cover-compiled, but as an example, the + compiler test suite runs more than twice as fast with the + new Cover.</p> + <p> + Own Id: OTP-15575</p> + </item> + </list> + </section> + +</section> + <section><title>Tools 3.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 8fe866cb69..2b3af417b6 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -196,6 +196,8 @@ start() -> receive {?SERVER,started} -> {ok,Pid}; + {?SERVER,{error,Error}} -> + {error,Error}; {'DOWN', Ref, _Type, _Object, Info} -> {error,Info} end, @@ -645,19 +647,31 @@ remote_reply(MainNode,Reply) -> %%%---------------------------------------------------------------------- init_main(Starter) -> - register(?SERVER,self()), - ?COVER_MAPPING_TABLE = ets:new(?COVER_MAPPING_TABLE, - [ordered_set, public, named_table]), - ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public, - named_table]), - ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]), - ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public, - named_table]), - ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE, [set, public, - named_table]), - ok = net_kernel:monitor_nodes(true), - Starter ! {?SERVER,started}, - main_process_loop(#main_state{}). + try register(?SERVER,self()) of + true -> + ?COVER_MAPPING_TABLE = ets:new(?COVER_MAPPING_TABLE, + [ordered_set, public, named_table]), + ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public, + named_table]), + ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]), + ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public, + named_table]), + ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE, + [set, public, named_table]), + ok = net_kernel:monitor_nodes(true), + Starter ! {?SERVER,started}, + main_process_loop(#main_state{}) + catch + error:badarg -> + %% The server's already registered; either report that it's already + %% started or try again if it died before we could find its pid. + case whereis(?SERVER) of + undefined -> + init_main(Starter); + Pid -> + Starter ! {?SERVER, {error, {already_started, Pid}}} + end + end. main_process_loop(State) -> receive diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl index ee58fd7a10..462767f430 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.erl @@ -37,7 +37,7 @@ all() -> dont_reconnect_after_stop, stop_node_after_disconnect, export_import, otp_5031, otp_6115, otp_8270, otp_10979_hanging_node, otp_14817, - local_only], + local_only, startup_race], case whereis(cover_server) of undefined -> [coverage,StartStop ++ NoStartStop]; @@ -1775,7 +1775,32 @@ local_only(Config) -> {ok,Name} = test_server:start_node(?FUNCTION_NAME, slave, []), {error,local_only} = cover:start([Name]), test_server:stop_node(Name), + ok. +%% ERL-943; We should not crash on startup when multiple servers race to +%% register the server name. +startup_race(Config) when is_list(Config) -> + PidRefs = [spawn_monitor(fun() -> + case cover:start() of + {error, {already_started, _Pid}} -> + ok; + {ok, _Pid} -> + ok + end + end) || _<- lists:seq(1,8)], + startup_race_1(PidRefs). + +startup_race_1([{Pid, Ref} | PidRefs]) -> + receive + {'DOWN', Ref, process, Pid, normal} -> + startup_race_1(PidRefs); + {'DOWN', Ref, process, Pid, _Other} -> + ct:fail("Cover server crashed on startup.") + after 5000 -> + ct:fail("Timed out.") + end; +startup_race_1([]) -> + cover:stop(), ok. %%--Auxiliary------------------------------------------------------------ diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 5700885549..191a458c62 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 3.1 +TOOLS_VSN = 3.2 diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index 33d02e22ba..0c3374091d 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -32,6 +32,23 @@ <p>This document describes the changes made to the wxErlang application.</p> +<section><title>Wx 1.8.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All incorrect (that is, all) uses of "can not" has been + corrected to "cannot" in source code comments, + documentation, examples, and so on.</p> + <p> + Own Id: OTP-14282 Aux Id: PR-1891 </p> + </item> + </list> + </section> + +</section> + <section><title>Wx 1.8.7</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index dac219fa98..91d15de3a9 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 1.8.7 +WX_VSN = 1.8.8 diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml index d6b6dfdfb5..37973d0dba 100644 --- a/lib/xmerl/doc/src/notes.xml +++ b/lib/xmerl/doc/src/notes.xml @@ -32,6 +32,21 @@ <p>This document describes the changes made to the Xmerl application.</p> +<section><title>Xmerl 1.3.21</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A typo in an error printout has been fixed.</p> + <p> + Own Id: OTP-14703 Aux Id: PR-1964 </p> + </item> + </list> + </section> + +</section> + <section><title>Xmerl 1.3.20</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk index 31ffa6e749..08696606e6 100644 --- a/lib/xmerl/vsn.mk +++ b/lib/xmerl/vsn.mk @@ -1 +1 @@ -XMERL_VSN = 1.3.20 +XMERL_VSN = 1.3.21 diff --git a/make/otp_patch_solve_forward_merge_version b/make/otp_patch_solve_forward_merge_version index ec635144f6..f599e28b8a 100644 --- a/make/otp_patch_solve_forward_merge_version +++ b/make/otp_patch_solve_forward_merge_version @@ -1 +1 @@ -9 +10 diff --git a/make/otp_version_tickets b/make/otp_version_tickets index b8220e1a87..12cf3070e5 100644 --- a/make/otp_version_tickets +++ b/make/otp_version_tickets @@ -1 +1,147 @@ -DEVELOPMENT +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 diff --git a/otp_versions.table b/otp_versions.table index 566aa3cb4c..101915dc6e 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,6 @@ +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 : OTP-21.3.7 : ssh-4.7.6 # 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 erl_interface-3.11.2 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 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 : OTP-21.3.6 : ssl-9.2.2 # 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 erl_interface-3.11.2 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.5 stdlib-3.8.1 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 : OTP-21.3.5 : diameter-2.2.1 erts-10.3.4 inets-7.0.7 # 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 edoc-0.10 eldap-1.2.6 erl_docgen-0.9 erl_interface-3.11.2 et-1.6.4 eunit-2.3.7 ftp-1.0.2 hipe-3.18.3 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.5 ssl-9.2.1 stdlib-3.8.1 syntax_tools-2.1.7 tftp-1.0.1 tools-3.1 wx-1.8.7 xmerl-1.3.20 : diff --git a/scripts/run-dialyzer b/scripts/run-dialyzer index 44436594d3..34724a8ca0 100755 --- a/scripts/run-dialyzer +++ b/scripts/run-dialyzer @@ -43,5 +43,5 @@ $ERL_TOP/bin/dialyzer --build_plt -Wunknown --apps $BASE_PLT $APP_PLT --statisti $ERL_TOP/bin/dialyzer -n -Wunknown -Wunmatched_returns --apps $UNMATCHED --statistics $ERL_TOP/bin/dialyzer -n -Wunknown --apps $NO_UNMATCHED --statistics if [ "X$WARNINGS" != "X" ]; then - $ERL_TOP/bin/dialyzer -n --apps $WARNINGS --statistics + $ERL_TOP/bin/dialyzer -n --apps $WARNINGS --statistics || true fi |