aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl62
-rw-r--r--lib/compiler/test/beam_ssa_SUITE.erl26
-rw-r--r--lib/dialyzer/doc/src/notes.xml16
-rw-r--r--lib/dialyzer/src/dialyzer.erl48
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl107
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/hipe/doc/src/hipe_app.xml4
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl41
-rw-r--r--lib/inets/doc/src/notes.xml18
-rw-r--r--lib/inets/src/http_client/httpc.erl8
-rw-r--r--lib/inets/test/httpc_SUITE.erl13
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/ssl/doc/src/notes.xml31
-rw-r--r--lib/ssl/src/tls_connection.erl2
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl4
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl4
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/test/lists_SUITE.erl11
18 files changed, 224 insertions, 177 deletions
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index 9af72afca7..a2e687930b 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -156,7 +156,9 @@ passes(Opts) ->
%% Allocate registers.
?PASS(linear_scan),
?PASS(frame_size),
- ?PASS(turn_yregs)],
+ ?PASS(turn_yregs),
+
+ ?PASS(assert_no_critical_edges)],
[P || P <- Ps, P =/= ignore].
function(#b_function{anno=Anno,args=Args,bs=Blocks0,cnt=Count0}=F0,
@@ -1321,10 +1323,11 @@ fix_receives_1([{L,Blk}|Ls], Blocks0, Count0) ->
LoopExit = find_loop_exit(Rm, Blocks0),
Defs0 = beam_ssa:def([L], Blocks0),
CommonUsed = recv_common(Defs0, LoopExit, Blocks0),
- {Blocks1,Count1} = recv_fix_common(CommonUsed, LoopExit, Rm,
- Blocks0, Count0),
+ {Blocks1,Count1} = recv_crit_edges(Rm, LoopExit, Blocks0, Count0),
+ {Blocks2,Count2} = recv_fix_common(CommonUsed, LoopExit, Rm,
+ Blocks1, Count1),
Defs = ordsets:subtract(Defs0, CommonUsed),
- {Blocks,Count} = fix_receive(Rm, Defs, Blocks1, Count1),
+ {Blocks,Count} = fix_receive(Rm, Defs, Blocks2, Count2),
fix_receives_1(Ls, Blocks, Count);
#b_blk{} ->
fix_receives_1(Ls, Blocks0, Count0)
@@ -1341,6 +1344,57 @@ recv_common(Defs, Exit, Blocks) ->
Def = ordsets:subtract(Defs, ExitDefs),
ordsets:intersection(Def, ExitUsed).
+%% recv_crit_edges([RemoveMessageLabel], LoopExit,
+%% Blocks0, Count0) -> {Blocks,Count}.
+%%
+%% Adds dummy blocks on all conditional jumps to the exit block so that
+%% recv_fix_common/5 can insert phi nodes without having to worry about
+%% critical edges.
+
+recv_crit_edges(_Rms, none, Blocks0, Count0) ->
+ {Blocks0, Count0};
+recv_crit_edges(Rms, Exit, Blocks0, Count0) ->
+ Ls = beam_ssa:rpo(Rms, Blocks0),
+ rce_insert_edges(Ls, Exit, Count0, Blocks0).
+
+rce_insert_edges([L | Ls], Exit, Count0, Blocks0) ->
+ Successors = beam_ssa:successors(map_get(L, Blocks0)),
+ case member(Exit, Successors) of
+ true when Successors =/= [Exit] ->
+ {Blocks, Count} = rce_insert_edge(L, Exit, Count0, Blocks0),
+ rce_insert_edges(Ls, Exit, Count, Blocks);
+ _ ->
+ rce_insert_edges(Ls, Exit, Count0, Blocks0)
+ end;
+rce_insert_edges([], _Exit, Count, Blocks) ->
+ {Blocks, Count}.
+
+rce_insert_edge(L, Exit, Count, Blocks0) ->
+ #b_blk{last=Last0} = FromBlk0 = map_get(L, Blocks0),
+
+ ToExit = #b_br{bool=#b_literal{val=true},succ=Exit,fail=Exit},
+
+ FromBlk = FromBlk0#b_blk{last=rce_reroute_terminator(Last0, Exit, Count)},
+ EdgeBlk = #b_blk{anno=#{},is=[],last=ToExit},
+
+ Blocks = Blocks0#{ Count => EdgeBlk, L => FromBlk },
+ {Blocks, Count + 1}.
+
+rce_reroute_terminator(#b_br{succ=Exit}=Last, Exit, New) ->
+ rce_reroute_terminator(Last#b_br{succ=New}, Exit, New);
+rce_reroute_terminator(#b_br{fail=Exit}=Last, Exit, New) ->
+ rce_reroute_terminator(Last#b_br{fail=New}, Exit, New);
+rce_reroute_terminator(#b_br{}=Last, _Exit, _New) ->
+ Last;
+rce_reroute_terminator(#b_switch{fail=Exit}=Last, Exit, New) ->
+ rce_reroute_terminator(Last#b_switch{fail=New}, Exit, New);
+rce_reroute_terminator(#b_switch{list=List0}=Last, Exit, New) ->
+ List = [if
+ Lbl =:= Exit -> {Arg, New};
+ Lbl =/= Exit -> {Arg, Lbl}
+ end || {Arg, Lbl} <- List0],
+ Last#b_switch{list=List}.
+
%% recv_fix_common([CommonVar], LoopExit, [RemoveMessageLabel],
%% Blocks0, Count0) -> {Blocks,Count}.
%% Handle variables alwys defined in a receive and used
diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl
index a741ebbdf9..256bb95559 100644
--- a/lib/compiler/test/beam_ssa_SUITE.erl
+++ b/lib/compiler/test/beam_ssa_SUITE.erl
@@ -190,6 +190,12 @@ recv(_Config) ->
self() ! {[self(),r1],{2,99,<<"data">>}},
{Parent,r1,<<1:32,2:8,99:8,"data">>} = tricky_recv_4(),
+ %% Test tricky_recv_5/0.
+ self() ! 1,
+ a = tricky_recv_5(),
+ self() ! 2,
+ b = tricky_recv_5(),
+
ok.
sync_wait_mon({Pid, Ref}, Timeout) ->
@@ -295,6 +301,26 @@ tricky_recv_4() ->
end,
id({Pid,R,Request}).
+%% beam_ssa_pre_codegen would accidentally create phi nodes on critical edges
+%% when fixing up receives; the call to id/2 can either succeed or land in the
+%% catch block, and we added a phi node to its immediate successor.
+tricky_recv_5() ->
+ try
+ receive
+ X=1 ->
+ id(42),
+ a;
+ X=2 ->
+ b
+ end,
+ case X of
+ 1 -> a;
+ 2 -> b
+ end
+ catch
+ _:_ -> c
+ end.
+
maps(_Config) ->
{'EXIT',{{badmatch,#{}},_}} = (catch maps_1(any)),
ok.
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 0930f79840..b72453aac7 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -32,6 +32,22 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 4.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Make sure Dialyzer does not crash if the formatting
+ of results fails. Instead of crashing, an unformatted
+ version of the results is returned. </p>
+ <p>
+ Own Id: OTP-15922 Aux Id: PR-2240, ERL-949 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 4.0.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index d4fe064edd..c1bc5ff597 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -605,11 +605,9 @@ ordinal(N) when is_integer(N) -> io_lib:format("~wth", [N]).
%% Functions that parse type strings, literal strings, and contract
%% strings. Return strings formatted by erl_pp.
-%% If lib/hipe/cerl/erl_types.erl is compiled with DEBUG=true,
-%% the contents of opaque types are showed inside brackets.
-%% Since erl_parse:parse_form() cannot handle the bracket syntax,
-%% no indentation is done.
-%%-define(DEBUG , true).
+%% Note we always have to catch any error when trying to parse
+%% the syntax because other BEAM languages may not emit an
+%% Erlang AST that transforms into valid Erlang Source Code.
-define(IND, 10).
@@ -620,13 +618,15 @@ con(M, F, Src, I) ->
sig(Src, false) ->
Src;
sig(Src, true) ->
- Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])),
- {ok, Tokens, _EndLocation} = erl_scan:string(Str),
- exec(fun() ->
- {ok, {attribute, _, spec, {_MFA, Types}}} =
- erl_parse:parse_form(Tokens),
- indentation(?IND) ++ pp_spec(Types)
- end, Src).
+ try
+ Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])),
+ {ok, Tokens, _EndLocation} = erl_scan:string(Str),
+ {ok, {attribute, _, spec, {_MFA, Types}}} =
+ erl_parse:parse_form(Tokens),
+ indentation(?IND) ++ pp_spec(Types)
+ catch
+ _:_ -> Src
+ end.
%% Argument(list)s are a mix of types and Erlang code. Note: sometimes
%% (contract_range, call_without_opaque, opaque_type_test), the initial
@@ -681,21 +681,15 @@ ts(Src) ->
[C1|Src1] = Src, % $< (product) or $( (arglist)
[C2|RevSrc2] = lists:reverse(Src1),
Src2 = lists:reverse(RevSrc2),
- exec(fun() ->
- Types = parse_types_and_literals(Src2),
- CommaInd = [$, | Ind],
- (indentation(?IND-1) ++
- [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++
- [C2])
- end, Src).
-
--ifdef(DEBUG).
-exec(F, R) ->
- try F() catch _:_ -> R end.
--else.
-exec(F, _) ->
- F().
--endif.
+ try
+ Types = parse_types_and_literals(Src2),
+ CommaInd = [$, | Ind],
+ (indentation(?IND-1) ++
+ [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++
+ [C2])
+ catch
+ _:_ -> Src
+ end.
indentation(I) ->
[$\n | lists:duplicate(I, $\s)].
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index f887f661bd..5e680062fb 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -320,12 +320,6 @@ report_analysis_start(#options{analysis_type = Type,
end
end.
-report_native_comp(#options{report_mode = ReportMode}) ->
- case ReportMode of
- quiet -> ok;
- _ -> io:format(" Compiling some key modules to native code...")
- end.
-
report_elapsed_time(T1, T2, #options{report_mode = ReportMode}) ->
case ReportMode of
quiet -> ok;
@@ -375,7 +369,6 @@ do_analysis(Options) ->
do_analysis(Files, Options, Plt, PltInfo) ->
assert_writable(Options#options.output_plt),
- hipe_compile(Files, Options),
report_analysis_start(Options),
State0 = new_state(),
State1 = init_output(State0, Options),
@@ -484,106 +477,6 @@ expand_dependent_modules_1([Mod|Mods], Included, ModDeps) ->
expand_dependent_modules_1([], Included, _ModDeps) ->
Included.
--define(MIN_PARALLELISM, 7).
--define(MIN_FILES_FOR_NATIVE_COMPILE, 20).
-
--spec hipe_compile([file:filename()], #options{}) -> 'ok'.
-
-hipe_compile(Files, #options{erlang_mode = ErlangMode} = Options) ->
- NoNative = (get(dialyzer_options_native) =:= false),
- FewFiles = (length(Files) < ?MIN_FILES_FOR_NATIVE_COMPILE),
- case NoNative orelse FewFiles orelse ErlangMode of
- true -> ok;
- false ->
- case erlang:system_info(hipe_architecture) of
- undefined -> ok;
- _ ->
- Mods = [lists, dict, digraph, digraph_utils, ets,
- gb_sets, gb_trees, ordsets, sets, sofs,
- cerl, erl_types, cerl_trees, erl_bif_types,
- dialyzer_analysis_callgraph, dialyzer, dialyzer_behaviours,
- dialyzer_codeserver, dialyzer_contracts,
- dialyzer_coordinator, dialyzer_dataflow, dialyzer_dep,
- dialyzer_plt, dialyzer_succ_typings, dialyzer_typesig,
- dialyzer_worker],
- report_native_comp(Options),
- {T1, _} = statistics(wall_clock),
- Cache = (get(dialyzer_options_native_cache) =/= false),
- native_compile(Mods, Cache),
- {T2, _} = statistics(wall_clock),
- report_elapsed_time(T1, T2, Options)
- end
- end.
-
-native_compile(Mods, Cache) ->
- case dialyzer_utils:parallelism() > ?MIN_PARALLELISM of
- true ->
- Parent = self(),
- Pids = [spawn(fun () -> Parent ! {self(), hc(M, Cache)} end) || M <- Mods],
- lists:foreach(fun (Pid) -> receive {Pid, Res} -> Res end end, Pids);
- false ->
- lists:foreach(fun (Mod) -> hc(Mod, Cache) end, Mods)
- end.
-
-hc(Mod, Cache) ->
- {module, Mod} = code:ensure_loaded(Mod),
- case code:is_module_native(Mod) of
- true -> ok;
- false ->
- %% io:format(" ~w", [Mod]),
- case Cache of
- false ->
- {ok, Mod} = hipe:c(Mod),
- ok;
- true ->
- hc_cache(Mod)
- end
- end.
-
-hc_cache(Mod) ->
- CacheBase = cache_base_dir(),
- %% Use HiPE architecture, version and erts checksum in directory name,
- %% to avoid clashes between incompatible binaries.
- HipeArchVersion =
- lists:concat(
- [erlang:system_info(hipe_architecture), "-",
- hipe:version(), "-",
- hipe:erts_checksum()]),
- CacheDir = filename:join(CacheBase, HipeArchVersion),
- OrigBeamFile = code:which(Mod),
- {ok, {Mod, <<Checksum:128>>}} = beam_lib:md5(OrigBeamFile),
- CachedBeamFile = filename:join(CacheDir, lists:concat([Mod, "-", Checksum, ".beam"])),
- ok = filelib:ensure_dir(CachedBeamFile),
- ModBin =
- case filelib:is_file(CachedBeamFile) of
- true ->
- {ok, BinFromFile} = file:read_file(CachedBeamFile),
- BinFromFile;
- false ->
- {ok, Mod, CompiledBin} = compile:file(OrigBeamFile, [from_beam, native, binary]),
- ok = file:write_file(CachedBeamFile, CompiledBin),
- CompiledBin
- end,
- code:unstick_dir(filename:dirname(OrigBeamFile)),
- {module, Mod} = code:load_binary(Mod, CachedBeamFile, ModBin),
- true = code:is_module_native(Mod),
- ok.
-
-cache_base_dir() ->
- %% http://standards.freedesktop.org/basedir-spec/basedir-spec-0.7.html
- %% If XDG_CACHE_HOME is set to an absolute path, use it as base.
- XdgCacheHome = os:getenv("XDG_CACHE_HOME"),
- CacheHome =
- case is_list(XdgCacheHome) andalso filename:pathtype(XdgCacheHome) =:= absolute of
- true ->
- XdgCacheHome;
- false ->
- %% Otherwise, the default is $HOME/.cache.
- {ok, [[Home]]} = init:get_argument(home),
- filename:join(Home, ".cache")
- end,
- filename:join([CacheHome, "dialyzer_hipe_cache"]).
-
new_state() ->
#cl_state{}.
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index 466bbfd0f2..7a44daf683 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 4.0.1
+DIALYZER_VSN = 4.0.2
diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml
index 61d92fdffe..5ac445ac58 100644
--- a/lib/hipe/doc/src/hipe_app.xml
+++ b/lib/hipe/doc/src/hipe_app.xml
@@ -66,6 +66,10 @@
<item><p>The HiPE compiler will crash on modules containing binary
matching.</p>
</item>
+ <tag>try/catch</tag>
+ <item><p>The HiPE compiler will crash on modules containing 'try' or
+ 'catch'.</p>
+ </item>
<tag>Stack traces</tag>
<item><p>Stack traces returned from <seealso marker="erts:erlang#get_stacktrace/0">
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 8e7e56b6c4..995c961e09 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -557,32 +557,21 @@ trans_fun([{move,Src,Dst}|Instructions], Env) ->
Dst1 = mk_var(Dst),
Src1 = trans_arg(Src),
[hipe_icode:mk_move(Dst1,Src1) | trans_fun(Instructions,Env)];
-%%--- catch --- ITS PROCESSING IS POSTPONED
-trans_fun([{'catch',N,{_,EndLabel}}|Instructions], Env) ->
- NewContLbl = mk_label(new),
- [{'catch',N,EndLabel},NewContLbl | trans_fun(Instructions,Env)];
-%%--- catch_end --- ITS PROCESSING IS POSTPONED
-trans_fun([{catch_end,_N}=I|Instructions], Env) ->
- [I | trans_fun(Instructions,Env)];
-%%--- try --- ITS PROCESSING IS POSTPONED
-trans_fun([{'try',N,{_,EndLabel}}|Instructions], Env) ->
- NewContLbl = mk_label(new),
- [{'try',N,EndLabel},NewContLbl | trans_fun(Instructions,Env)];
-%%--- try_end ---
-trans_fun([{try_end,_N}|Instructions], Env) ->
- [hipe_icode:mk_end_try() | trans_fun(Instructions,Env)];
-%%--- try_case --- ITS PROCESSING IS POSTPONED
-trans_fun([{try_case,_N}=I|Instructions], Env) ->
- [I | trans_fun(Instructions,Env)];
-%%--- try_case_end ---
-trans_fun([{try_case_end,Arg}|Instructions], Env) ->
- BadArg = trans_arg(Arg),
- ErrVar = mk_var(new),
- Vs = [mk_var(new)],
- Atom = hipe_icode:mk_move(ErrVar,hipe_icode:mk_const(try_clause)),
- Tuple = hipe_icode:mk_primop(Vs,mktuple,[ErrVar,BadArg]),
- Fail = hipe_icode:mk_fail(Vs,error),
- [Atom,Tuple,Fail | trans_fun(Instructions,Env)];
+%%
+%% try/catch -- THESE ARE KNOWN TO MISCOMPILE, SEE OTP-15949
+%%
+trans_fun([{'catch'=Name,_,_}|_], _Env) ->
+ nyi(Name);
+trans_fun([{catch_end=Name,_}|_], _Env) ->
+ nyi(Name);
+trans_fun([{'try'=Name,_,_}|_], _Env) ->
+ nyi(Name);
+trans_fun([{try_end=Name,_}|_], _Env) ->
+ nyi(Name);
+trans_fun([{try_case=Name,_}|_], _Env) ->
+ nyi(Name);
+trans_fun([{try_case_end=Name,_}|_], _Env) ->
+ nyi(Name);
%%--- raise ---
trans_fun([{raise,{f,0},[Reg1,Reg2],{x,0}}|Instructions], Env) ->
V1 = trans_arg(Reg1),
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 03bd1d8042..45533c4f4b 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,7 +33,23 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 7.0.8</title>
+ <section><title>Inets 7.0.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix a regression in http client that causes a crash when
+ request URI has no scheme.</p>
+ <p>
+ Own Id: OTP-15930 Aux Id: ERL-969 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index 24a205ced9..9967488f61 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -317,7 +317,7 @@ store_cookies(SetCookieHeaders, Url, Profile)
{error, Bad, _} ->
{error, {parse_failed, Bad}};
URI ->
- Scheme = scheme_to_atom(maps:get(scheme, URI, '')),
+ Scheme = scheme_to_atom(maps:get(scheme, URI, undefined)),
Host = maps:get(host, URI, ""),
Port = maps:get(port, URI, default_port(Scheme)),
Path = uri_string:recompose(#{path => maps:get(path, URI, "")}),
@@ -536,7 +536,7 @@ handle_request(Method, Url,
BracketedHost = proplists:get_value(ipv6_host_with_brackets,
Options),
- Scheme = scheme_to_atom(maps:get(scheme, URI, '')),
+ Scheme = scheme_to_atom(maps:get(scheme, URI, undefined)),
Userinfo = maps:get(userinfo, URI, ""),
Host = http_util:maybe_add_brackets(maps:get(host, URI, ""), BracketedHost),
Port = maps:get(port, URI, default_port(Scheme)),
@@ -591,8 +591,8 @@ scheme_to_atom("http") ->
http;
scheme_to_atom("https") ->
https;
-scheme_to_atom('') ->
- '';
+scheme_to_atom(undefined) ->
+ throw({error, {no_scheme}});
scheme_to_atom(Scheme) ->
throw({error, {bad_scheme, Scheme}}).
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index d4b33ae2c6..1d37e71847 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -106,7 +106,8 @@ real_requests()->
streaming_error,
inet_opts,
invalid_headers,
- invalid_body
+ invalid_body,
+ no_scheme
].
real_requests_esi() ->
@@ -1231,6 +1232,16 @@ invalid_body(Config) ->
ok
end.
+
+%%-------------------------------------------------------------------------
+
+no_scheme(_Config) ->
+ {error,{bad_scheme,"ftp"}} = httpc:request("ftp://foobar"),
+ {error,{no_scheme}} = httpc:request("//foobar"),
+ {error,{no_scheme}} = httpc:request("foobar"),
+ ok.
+
+
%%-------------------------------------------------------------------------
remote_socket_close(Config) when is_list(Config) ->
URL = url(group_name(Config), "/just_close.html", Config),
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 5dbec9e7b3..d948204618 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 7.0.8
+INETS_VSN = 7.0.9
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 29bf5fc4e7..bb41b7e9ea 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,37 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 9.3.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix handling of certificate decoding problems in TLS 1.3
+ similarly as in TLS 1.2.</p>
+ <p>
+ Own Id: OTP-15900</p>
+ </item>
+ <item>
+ <p>
+ Hibernation now works as expected in all cases, was
+ accidently broken by optimization efforts.</p>
+ <p>
+ Own Id: OTP-15910</p>
+ </item>
+ <item>
+ <p>
+ Fix interoperability problems with openssl when the TLS
+ 1.3 server is configured wirh the option
+ signature_algs_cert.</p>
+ <p>
+ Own Id: OTP-15913</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 9.3.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 7cc2adfda1..24bc508a10 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -258,7 +258,7 @@ next_event(StateName, Record, State) ->
next_event(StateName, no_record, State0, Actions) ->
case next_record(StateName, State0) of
{no_record, State} ->
- {next_state, StateName, State, Actions};
+ ssl_connection:hibernate_after(StateName, State, Actions);
{Record, State} ->
next_event(StateName, Record, State, Actions)
end;
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 8a4ad922e1..53f9adbbd3 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -111,7 +111,7 @@ add_signature_algorithms_cert(Extensions, undefined) ->
Extensions;
add_signature_algorithms_cert(Extensions, SignAlgsCert) ->
Extensions#{signature_algorithms_cert =>
- #signature_algorithms{signature_scheme_list = SignAlgsCert}}.
+ #signature_algorithms_cert{signature_scheme_list = SignAlgsCert}}.
filter_tls13_algs(undefined) -> undefined;
@@ -802,7 +802,7 @@ validate_certificate_chain(Certs, CertDbHandle, CertDbRef, SslOptions, CRLDbHand
CertDbHandle, CertDbRef)
end
catch
- error:{badmatch,{asn1, Asn1Reason}} ->
+ error:{badmatch,{error, {asn1, Asn1Reason}}} ->
%% ASN-1 decode of certificate somehow failed
{error, {certificate_unknown, {failed_to_decode_certificate, Asn1Reason}}};
error:OtherReason ->
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 4f6ea6c886..f5ce3a2b65 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -3660,7 +3660,7 @@ hibernate(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
- timer:sleep(1500),
+ ct:sleep(1500),
{current_function, {erlang, hibernate, 3}} =
process_info(Pid, current_function),
@@ -3696,6 +3696,8 @@ hibernate_right_away(Config) ->
[{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]),
ssl_test_lib:check_result(Server1, ok, Client1, ok),
+
+ ct:sleep(1000), %% Schedule out
{current_function, {erlang, hibernate, 3}} =
process_info(Pid1, current_function),
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 01dee392f5..df38aea017 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 9.3.3
+SSL_VSN = 9.3.4
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index 5dab6f6697..c3c54710eb 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -2600,6 +2600,15 @@ subtract(Config) when is_list(Config) ->
[1,2,3,4,5,6,7,8,9,9999,10000,20,21,22] =
sub(lists:seq(1, 10000)++[20,21,22], lists:seq(10, 9998)),
+ %% ERL-986; an integer overflow relating to term comparison
+ %% caused subtraction to be inconsistent.
+ Ids = [2985095936,47540628,135460048,1266126295,240535295,
+ 115724671,161800351,4187206564,4178142725,234897063,
+ 14773162,6662515191,133150693,378034895,1874402262,
+ 3507611978,22850922,415521280,253360400,71683243],
+
+ [] = id(Ids) -- id(Ids),
+
%% Floats/integers.
[42.0,42.0] = sub([42.0,42,42.0], [42,42,42]),
[1,2,3,4,43.0] = sub([1,2,3,4,5,42.0,43.0], [42.0,5]),
@@ -2627,6 +2636,8 @@ subtract(Config) when is_list(Config) ->
ok.
+id(I) -> I.
+
sub_non_matching(A, B) ->
A = sub(A, B).