summaryrefslogtreecommitdiff
path: root/lib/compiler/test/core_fold_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/test/core_fold_SUITE.erl')
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl165
1 files changed, 162 insertions, 3 deletions
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 8167ab517d..18284b9ebe 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -18,6 +18,7 @@
%% %CopyrightEnd%
%%
-module(core_fold_SUITE).
+-feature(maybe_expr, enable).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -29,7 +30,8 @@
no_no_file/1,configuration/1,supplies/1,
redundant_stack_frame/1,export_from_case/1,
empty_values/1,cover_letrec_effect/1,
- receive_effect/1,map_effect/1]).
+ receive_effect/1,nested_lets/1,
+ map_effect/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -50,8 +52,8 @@ groups() ->
no_no_file,configuration,supplies,
redundant_stack_frame,export_from_case,
empty_values,cover_letrec_effect,
- receive_effect,map_effect]}].
-
+ receive_effect,nested_lets,
+ map_effect]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -675,6 +677,7 @@ cover_letrec_effect(_Config) ->
end,
_ = catch cover_letrec_effect_1(),
+ _ = catch cover_letrec_effect_2(),
ok.
@@ -692,6 +695,12 @@ cover_letrec_effect_1() ->
end
end.
+cover_letrec_effect_2() ->
+ maybe
+ << ok || ok, _ <- (catch ok)>>,
+ ok
+ end.
+
receive_effect(_Config) ->
self() ! whatever,
{} = do_receive_effect(),
@@ -700,6 +709,154 @@ receive_effect(_Config) ->
do_receive_effect() ->
{} = receive _ -> {} = {} end.
+nested_lets(_Config) ->
+ {'EXIT',{{case_clause,ok},_}} = catch nested_lets_1(<<42>>),
+ {'EXIT',{badarith,_}} = catch nested_lets_2(id(0), id(0)),
+ {'EXIT',{badarith,_}} = catch nested_lets_3(),
+ {'EXIT',{undef,_}} = catch nested_lets_4(),
+ {'EXIT',{{case_clause,_},_}} = catch nested_lets_5(),
+ {'EXIT',{badarith,_}} = catch nested_lets_6(),
+
+ ok.
+
+%% GH-6572: Deeply nested `let` expressions caused `sys_core_fold` to generate
+%% unsafe code that it would attempt to fix up later. Unfortunately it did so
+%% through a limited fixpoint iteration, and would leak said code once the
+%% limit was hit.
+nested_lets_1(<<X>>) ->
+ Y =
+ case ok of
+ X ->
+ true = (ok > (Y = -1)),
+ <<>> =
+ {id(
+ <<
+ (ok - ok),
+ (bnot ok),
+ (nested_lets_1_f() band ok),
+ (nested_lets_1_f()),
+ (not ok),
+ (ok or nested_lets_1_f()),
+ (id(
+ id(
+ <<
+ (id(
+ <<
+ (id(
+ <<0 || _ <- []>>
+ ))
+ >>
+ ) * ok)
+ >>
+ )
+ ))
+ >>
+ )}
+ end.
+
+nested_lets_1_f() ->
+ ok.
+
+%% GH-6612: A variant of GH-6572 that slipped through the initial fix.
+nested_lets_2(X, 0) ->
+ try
+ 0 = {
+ _ = 0 + 0,
+ Z = bnot ok,
+ {(_ = ok), (_ = X)}#{ok => ok},
+ ok +
+ (nested_lets_2_f(
+ ok +
+ nested_lets_2_f(
+ ok +
+ (nested_lets_2_f(
+ (Y =
+ -nested_lets_2_f(
+ #{
+ (ok +
+ (ok +
+ nested_lets_2_f(
+ case
+ try ok of
+ _ ->
+ fun(_) ->
+ ok
+ end
+ after
+ ok
+ end
+ of
+ #{} ->
+ ok
+ end
+ ))) => ok
+ } > ok
+ ))
+ ) + ok)
+ ) >
+ ok
+ ))
+ }
+ of
+ _ ->
+ Z;
+ _ ->
+ Y
+ after
+ ok
+ end.
+
+nested_lets_2_f(_) ->
+ ok.
+
+nested_lets_3() ->
+ try ((true = [X | _]) = (ok * (_ = ok))) of
+ _ ->
+ X
+ after
+ ok
+ end.
+
+nested_lets_4() ->
+ try
+ not (case {(_ = ok), (Y = ?MODULE:undef())} of
+ a ->
+ ok;
+ 0 ->
+ ok
+ end)
+ of
+ _ ->
+ Y
+ after
+ ok
+ end.
+
+%% GH-6633.
+nested_lets_5() ->
+ case self() of
+ [_ | X] ->
+ ok;
+ false ->
+ {ok#{
+ (X = ok) :=
+ ((ok /=
+ maybe
+ ok
+ end) =/= ok)
+ }}
+ end,
+ X.
+
+%% GH-6635.
+nested_lets_6() ->
+ try {not (false orelse (ok#{(1 / 0) := ok})), X = ok} of
+ X ->
+ ok
+ after
+ ok
+ end.
+
map_effect(_Config) ->
{'EXIT',{{badkey,key},_}} = catch map_effect_1(),
@@ -716,4 +873,6 @@ map_effect_2(Map) ->
Map#{key := value},
ok.
+%%% Common utility functions.
+
id(I) -> I.