summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2022-11-07 05:34:16 +0100
committerBjörn Gustavsson <bjorn@erlang.org>2022-11-07 05:34:16 +0100
commitc061907b1c3ed6c165c41443a37dbda5fc3cc9ac (patch)
treebe1a6cc605061aad39dc9f2931f3d34f1c56bfa1
parentd0f071a9e634c6fdd6fea353a7d331fd31a517fb (diff)
parent706b555cf093252a3c4b833764cb79fb1fa6c65d (diff)
downloaderlang-c061907b1c3ed6c165c41443a37dbda5fc3cc9ac.tar.gz
Merge branch 'maint'
* maint: compiler: Eliminate internal error in sub pass ssa_opt_bsm_shortcut Eliminate Dialyzer crash for ill-typed code compile_SUITE: Make core_roundtrip/1 less resource-intensive compile_SUITE: Avoid eaccess error during cleanup on Windows asn1, compiler: Avoid running out of memory on Windows Fix filelib_SUITE:ensure_path_invalid_path/1
-rw-r--r--lib/asn1/test/asn1_test_lib.erl9
-rw-r--r--lib/compiler/src/beam_ssa_opt.erl7
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl9
-rw-r--r--lib/compiler/test/compile_SUITE.erl15
-rw-r--r--lib/compiler/test/test_lib.erl18
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl18
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl29
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl13
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl11
10 files changed, 107 insertions, 26 deletions
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index 0a331d0dd0..d421c29dd3 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -306,7 +306,14 @@ ber_get_len(<<1:1,Octets:7,T0/binary>>) ->
%% Will fail the test case if there were any errors.
p_run(Test, List) ->
- S = erlang:system_info(schedulers),
+ %% Limit the number of parallel processes to avoid running out of
+ %% memory.
+ S = case {erlang:system_info(schedulers),erlang:system_info(wordsize)} of
+ {S0,4} ->
+ min(S0, 2);
+ {S0,_} ->
+ min(S0, 8)
+ end,
N = case test_server:is_cover() of
false ->
S + 1;
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index 673a366288..11e065e6a6 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -1900,14 +1900,15 @@ coalesce_skips_is([#b_set{op=bs_match,
args=[#b_literal{val=skip},
Ctx0,Type,Flags,
#b_literal{val=Size0},
- #b_literal{val=Unit0}]}=Skip0,
+ #b_literal{val=Unit0}],
+ dst=Ctx}=Skip0,
#b_set{op={succeeded,guard}}],
#b_br{succ=L2,fail=Fail}=Br0,
Bs0) when is_integer(Size0) ->
case Bs0 of
[{L2,#b_blk{is=[#b_set{op=bs_match,
dst=SkipDst,
- args=[#b_literal{val=skip},_,_,_,
+ args=[#b_literal{val=skip},Ctx,_,_,
#b_literal{val=Size1},
#b_literal{val=Unit1}]},
#b_set{op={succeeded,guard}}=Succeeded],
@@ -1921,7 +1922,7 @@ coalesce_skips_is([#b_set{op=bs_match,
Is = [Skip,Succeeded],
{Is,Br,Bs};
[{L2,#b_blk{is=[#b_set{op=bs_test_tail,
- args=[_Ctx,#b_literal{val=TailSkip}]}],
+ args=[Ctx,#b_literal{val=TailSkip}]}],
last=#b_br{succ=NextSucc,fail=Fail}}}|Bs] ->
SkipBits = Size0 * Unit0,
TestTail = Skip0#b_set{op=bs_test_tail,
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 1b4d73f642..7fe6d89883 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -2470,6 +2470,11 @@ empty_matches(Config) when is_list(Config) ->
<<Zero:0/unit:1>> = id(<<>>),
0 = id(Zero),
+ ok = em_4(<<>>, <<>>),
+ {'EXIT',{function_clause,[_|_]}} = catch em_4(<<>>, <<0:1>>),
+ {'EXIT',{function_clause,[_|_]}} = catch em_4(<<0:1>>, <<>>),
+ {'EXIT',{function_clause,[_|_]}} = catch em_4(<<0:1>>, <<0:1>>),
+
ok.
em_1(Bytes) ->
@@ -2493,6 +2498,10 @@ em_3(<<V:0/binary,Rest/bits>>) ->
em_3_1(I) -> I.
+%% GH-6426/OTP-xxxxx
+em_4(<<X:0, _:X>>, <<Y:0, _:Y>>) ->
+ ok.
+
%% beam_trim would sometimes crash when bs_start_match4 had {atom,resume} as
%% its fail label.
trim_bs_start_match_resume(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 88711d5aab..79bd7b9a91 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -676,7 +676,7 @@ encrypted_abstr(Config) when is_list(Config) ->
%% Now run the tests that require crypto.
encrypted_abstr_1(Simple, Target),
ok = file:delete(Target),
- ok = file:del_dir_r(filename:dirname(Target))
+ _ = file:del_dir_r(filename:dirname(Target))
end,
%% Cleanup.
@@ -1130,7 +1130,7 @@ do_core_pp_1(M, A, Outdir) ->
compile_forms(M, Core, [clint,ssalint,from_core,binary]),
%% Don't optimize to test that we are not dependent
- %% on the Core Erlang optmimization passes.
+ %% on the Core Erlang optimization passes.
%% (Example of a previous bug: The core_parse pass
%% would not turn map literals into #c_literal{}
%% records; if sys_core_fold was run it would fix
@@ -1154,7 +1154,16 @@ core_roundtrip(Config) ->
ok = file:make_dir(Outdir),
TestBeams = get_unique_beam_files(),
- test_lib:p_run(fun(F) -> do_core_roundtrip(F, Outdir) end, TestBeams).
+
+ Test = fun(F) -> do_core_roundtrip(F, Outdir) end,
+ case erlang:system_info(wordsize) of
+ 4 ->
+ %% This test case is very memory intensive. Only
+ %% use a single process.
+ test_lib:p_run(Test, TestBeams, 1);
+ 8 ->
+ test_lib:p_run(Test, TestBeams)
+ end.
do_core_roundtrip(Beam, Outdir) ->
try
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
index 08c773d997..a6e75f232c 100644
--- a/lib/compiler/test/test_lib.erl
+++ b/lib/compiler/test/test_lib.erl
@@ -23,7 +23,7 @@
-compile({no_auto_import,[binary_part/2]}).
-export([id/1,recompile/1,recompile_core/1,parallel/0,
uniq/0,opt_opts/1,get_data_dir/1,
- is_cloned_mod/1,smoke_disasm/1,p_run/2,
+ is_cloned_mod/1,smoke_disasm/1,p_run/2,p_run/3,
highest_opcode/1]).
%% Used by test case that override BIFs.
@@ -142,6 +142,7 @@ is_cloned_mod_1("_no_opt_SUITE") -> true;
is_cloned_mod_1("_no_copt_SUITE") -> true;
is_cloned_mod_1("_no_copt_ssa_SUITE") -> true;
is_cloned_mod_1("_no_ssa_opt_SUITE") -> true;
+is_cloned_mod_1("_no_type_opt_SUITE") -> true;
is_cloned_mod_1("_post_opt_SUITE") -> true;
is_cloned_mod_1("_inline_SUITE") -> true;
is_cloned_mod_1("_no_module_opt_SUITE") -> true;
@@ -160,9 +161,20 @@ highest_opcode(Beam) ->
%% Will fail the test case if there were any errors.
p_run(Test, List) ->
- S = erlang:system_info(schedulers),
+ %% Limit the number of parallel processes to avoid running out of
+ %% memory.
+ S = case {erlang:system_info(schedulers),erlang:system_info(wordsize)} of
+ {S0,4} ->
+ min(S0, 2);
+ {S0,8} ->
+ min(S0, 8)
+ end,
N = S + 1,
- io:format("p_run: ~p parallel processes\n", [N]),
+ p_run(Test, List, N).
+
+p_run(Test, List, N) ->
+ io:format("p_run: ~p parallel processes; ~p jobs\n",
+ [N,length(List)]),
p_run_loop(Test, List, N, [], 0, 0).
p_run_loop(_, [], _, [], Errors, Ws) ->
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 47b5b069e1..68068ed67e 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -1600,7 +1600,8 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
Val = cerl:bitstr_val(Seg),
SegType = cerl:concrete(cerl:bitstr_type(Seg)),
UnitVal = cerl:concrete(cerl:bitstr_unit(Seg)),
- case cerl:bitstr_bitsize(Seg) of
+ Size = cerl:bitstr_size(Seg),
+ case bitstr_bitsize_type(Size) of
all ->
binary = SegType, [] = Segs, %% just an assert
T = t_inf(t_bitstr(UnitVal, 0), BinType),
@@ -1614,8 +1615,7 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
Map, State, false, []),
Type = t_binary(),
bind_bin_segs(Segs, BinType, [Type|Acc], Map1, State);
- BitSz when is_integer(BitSz); BitSz =:= any ->
- Size = cerl:bitstr_size(Seg),
+ any ->
{Map1, [SizeType]} = do_bind_pat_vars([Size], [t_non_neg_integer()],
Map, State, false, []),
Opaques = State#state.opaques,
@@ -1666,6 +1666,18 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
bind_bin_segs([], _BinType, Acc, Map, _State) ->
{Map, lists:reverse(Acc)}.
+bitstr_bitsize_type(Size) ->
+ case cerl:is_literal(Size) of
+ true ->
+ case cerl:concrete(Size) of
+ all -> all;
+ undefined -> utf;
+ _ -> any
+ end;
+ false ->
+ any
+ end.
+
%% Return the infimum (meet) of ExpectedType and Type if is not
%% t_none(), and raise a bind_error() it is t_none().
bind_checked_inf(Pat, ExpectedType, Type, Opaques) ->
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 1e96dd33be..d49a07dfd0 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -256,17 +256,24 @@ traverse(Tree, DefinedVars, State) ->
{State1, [SizeType, ValType]} =
traverse_list([Size, Val], DefinedVars, State),
{State2, TypeConstr, BinValTypeConstr} =
- case cerl:bitstr_bitsize(Tree) of
- all ->
- T = t_bitstr(UnitVal, 0),
- {State1, T, T};
- utf ->
- %% contains an integer number of bytes
- T = t_binary(),
- {State1, T, T};
- N when is_integer(N) ->
- {State1, t_bitstr(0, N), t_bitstr(1, N)};
- any -> % Size is not a literal
+ case cerl:is_literal(Size) of
+ true ->
+ case cerl:concrete(Size) of
+ all ->
+ T = t_bitstr(UnitVal, 0),
+ {State1, T, T};
+ undefined -> %utf-8/16/32
+ %% contains an integer number of bytes
+ T = t_binary(),
+ {State1, T, T};
+ N0 when is_integer(N0) ->
+ N = N0 * UnitVal,
+ {State1, t_bitstr(0, N), t_bitstr(1, N)};
+ _ ->
+ {State1, t_none(), t_none()}
+ end;
+ false ->
+ %% Size is not a literal
T1 = ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType]),
T2 =
?mk_fun_var(bitstr_constr(SizeType, UnitVal, match), [SizeType]),
diff --git a/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr b/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
index ce923a1c88..368c07a4e3 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
+++ b/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
@@ -3,6 +3,10 @@ bs_fail_constr.erl:11:1: Function w3/1 has no local return
bs_fail_constr.erl:12:8: Binary construction will fail since the size field S in segment 42:S has type neg_integer()
bs_fail_constr.erl:14:1: Function w4/1 has no local return
bs_fail_constr.erl:15:5: Binary construction will fail since the value field V in segment V/utf32 has type float()
+bs_fail_constr.erl:18:1: Function bad_size_1/1 has no local return
+bs_fail_constr.erl:18:1: The pattern <<X:[]>> can never match the type any()
+bs_fail_constr.erl:21:1: Function bad_size_2/1 has no local return
+bs_fail_constr.erl:24:9: The pattern <<X:Size>> can never match the type any()
bs_fail_constr.erl:5:1: Function w1/1 has no local return
bs_fail_constr.erl:6:5: Binary construction will fail since the value field V in segment V has type float()
bs_fail_constr.erl:8:1: Function w2/1 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl b/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
index 8c1f8c009a..a687fb45d2 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
@@ -1,6 +1,6 @@
-module(bs_fail_constr).
--export([w1/1, w2/1, w3/1, w4/1]).
+-export([w1/1, w2/1, w3/1, w4/1, bad_size_1/1, bad_size_2/1]).
w1(V) when is_float(V) ->
<<V/integer>>.
@@ -13,3 +13,14 @@ w3(S) when is_integer(S), S < 0 ->
w4(V) when is_float(V) ->
<<V/utf32>>.
+
+%% GH-6419
+bad_size_1(<<X:[]>>) ->
+ ok.
+
+bad_size_2(Bin) ->
+ Size = [],
+ case Bin of
+ <<X:Size>> ->
+ ok
+ end.
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index eac0dea4d8..179567f128 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -493,7 +493,16 @@ ensure_path_invalid_path(Config) when is_list(Config) ->
FileName = filename:join(BaseDir, "foo"),
ok = file:write_file(FileName, <<"eh?\n">>),
Path = filename:join(FileName, "foo/bar/baz"),
- {error,enotdir} = filelib:ensure_path(Path),
+ case filelib:ensure_path(Path) of
+ {error,enotdir} ->
+ ok;
+ {error,enoent} ->
+ %% The documentation has the following to say about the
+ %% `enotdir` error reason:
+ %%
+ %% "On some platforms, enoent is returned instead."
+ ok
+ end,
false = filelib:is_dir(Path).
ensure_path_relative_path(Config) when is_list(Config) ->