From 051ecbc1b3b78d9ea1600382a827237f73ef6c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 14 Feb 2020 06:58:00 +0100 Subject: 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. --- lib/compiler/src/v3_core.erl | 14 ++++++++++++++ lib/compiler/test/receive_SUITE.erl | 15 +++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'lib') 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 -- cgit v1.2.1