diff options
author | Björn Gustavsson <bjorn@erlang.org> | 2022-11-07 05:34:16 +0100 |
---|---|---|
committer | Björn Gustavsson <bjorn@erlang.org> | 2022-11-07 05:34:16 +0100 |
commit | c061907b1c3ed6c165c41443a37dbda5fc3cc9ac (patch) | |
tree | be1a6cc605061aad39dc9f2931f3d34f1c56bfa1 | |
parent | d0f071a9e634c6fdd6fea353a7d331fd31a517fb (diff) | |
parent | 706b555cf093252a3c4b833764cb79fb1fa6c65d (diff) | |
download | erlang-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.erl | 9 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa_opt.erl | 7 | ||||
-rw-r--r-- | lib/compiler/test/bs_match_SUITE.erl | 9 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 15 | ||||
-rw-r--r-- | lib/compiler/test/test_lib.erl | 18 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_dataflow.erl | 18 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer_typesig.erl | 29 | ||||
-rw-r--r-- | lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr | 4 | ||||
-rw-r--r-- | lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl | 13 | ||||
-rw-r--r-- | lib/stdlib/test/filelib_SUITE.erl | 11 |
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) -> |