summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2020-02-14 06:58:00 +0100
committerBjörn Gustavsson <bjorn@erlang.org>2020-02-17 10:33:53 +0100
commit051ecbc1b3b78d9ea1600382a827237f73ef6c6c (patch)
treecb71128bc66ff757d32053e5f2260ae8e4c47056 /lib
parent0e30237d28d5267b758e7f115117ae14f0a5fcf5 (diff)
downloaderlang-051ecbc1b3b78d9ea1600382a827237f73ef6c6c.tar.gz
v3_core: Eliminate crash when no receive clauses could match
The following code would crash the compiler: foobar() -> receive a = b -> V = a end, V.
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/v3_core.erl14
-rw-r--r--lib/compiler/test/receive_SUITE.erl15
2 files changed, 29 insertions, 0 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index a20595c131..9e2ca45074 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -2191,6 +2191,20 @@ uexprs([#imatch{anno=A,pat=P0,arg=Arg,fc=Fc}|Les], Ks, St0) ->
uexprs([#icase{anno=A,args=[Arg],
clauses=[Mc],fc=Fc}], Ks, St0)
end;
+uexprs([#ireceive1{clauses=[]}=Le0|_], Ks, St0) ->
+ %% All clauses have been optimized away because they had impossible patterns.
+ %% For example:
+ %%
+ %% receive
+ %% a = b ->
+ %% V = whatever
+ %% end,
+ %% V
+ %%
+ %% Discard the unreachable code following the receive to ensure
+ %% that there are no references to unbound variables.
+ {Le1,St1} = uexpr(Le0, Ks, St0),
+ {[Le1],St1};
uexprs([Le0|Les0], Ks, St0) ->
{Le1,St1} = uexpr(Le0, Ks, St0),
{Les1,St2} = uexprs(Les0, union((get_anno(Le1))#a.ns, Ks), St1),
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index dd70925ff7..b1f1099095 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -145,6 +145,11 @@ coverage(Config) when is_list(Config) ->
ok = receive_sink_tuple({any,pattern}),
{b,a} = receive_sink_tuple({a,b}),
+ %% Basically a smoke test of no_clauses_left/0.
+ NoClausesLeft = spawn(fun no_clauses_left/0),
+ receive after 1 -> ok end,
+ exit(NoClausesLeft, kill),
+
ok.
monitor_plus_badmap(Pid) ->
@@ -193,6 +198,16 @@ tuple_to_values(Timeout, X) ->
end,
A+B.
+no_clauses_left() ->
+ receive
+ %% This clause would be removed because it cannot match...
+ a = b ->
+ V = whatever
+ end,
+ %% ... leaving a reference to an unbound variable. Crash.
+ V.
+
+
%% Cover a help function for beam_ssa_opt:ssa_opt_sink/1.
receive_sink_tuple({Line,Pattern}) ->
receive