diff options
author | Björn Gustavsson <[email protected]> | 2019-08-01 10:54:53 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2019-08-01 10:54:53 +0200 |
commit | 94abe41967d6934701127e1734a8e75b6f32fb1e (patch) | |
tree | e74dc79dfb0b126482e0d7d38a50da8a6e5dea43 /lib/compiler | |
parent | 152da91d4f5e8df04e70c79b72ec12b4ecd07441 (diff) | |
parent | c7ac8d9bf26cbb04c2942e792f766a2ba6d8b07e (diff) | |
download | otp-94abe41967d6934701127e1734a8e75b6f32fb1e.tar.gz otp-94abe41967d6934701127e1734a8e75b6f32fb1e.tar.bz2 otp-94abe41967d6934701127e1734a8e75b6f32fb1e.zip |
Merge branch 'maint'
* maint:
Fix unsafe code sharing
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/beam_ssa_share.erl | 8 | ||||
-rw-r--r-- | lib/compiler/test/beam_ssa_SUITE.erl | 26 |
2 files changed, 30 insertions, 4 deletions
diff --git a/lib/compiler/src/beam_ssa_share.erl b/lib/compiler/src/beam_ssa_share.erl index 85ab088d14..fa728992f8 100644 --- a/lib/compiler/src/beam_ssa_share.erl +++ b/lib/compiler/src/beam_ssa_share.erl @@ -303,8 +303,12 @@ canonical_is([#b_ret{arg=Arg}], VarMap, Acc0) -> Acc0 end, {{ret,canonical_arg(Arg, VarMap),Acc1},VarMap}; -canonical_is([#b_br{bool=#b_var{},fail=Fail}], VarMap, Acc) -> - {{br,succ,Fail,Acc},VarMap}; +canonical_is([#b_br{bool=#b_var{}=Arg,fail=Fail}], VarMap, Acc) -> + %% A previous buggy version of this code omitted the canonicalized + %% argument in the return value. Unfortunately, that worked most + %% of the time, except when `br` terminator referenced a variable + %% defined in a previous block instead of in the same block. + {{br,canonical_arg(Arg, VarMap),succ,Fail,Acc},VarMap}; canonical_is([#b_br{succ=Succ}], VarMap, Acc) -> {{br,Succ,Acc},VarMap}; canonical_is([], VarMap, Acc) -> diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index 9227f56f8c..0a0f35ee7f 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -484,9 +484,11 @@ do_comb_sw_2(X) -> erase(?MODULE). share_opt(_Config) -> - ok = do_share_opt(0). + ok = do_share_opt_1(0), + ok = do_share_opt_2(), + ok. -do_share_opt(A) -> +do_share_opt_1(A) -> %% The compiler would be stuck in an infinite loop in beam_ssa_share. case A of 0 -> a; @@ -495,6 +497,26 @@ do_share_opt(A) -> end, receive after 1 -> ok end. +do_share_opt_2() -> + ok = sopt_2({[pointtopoint], [{dstaddr,any}]}, ok), + ok = sopt_2({[broadcast], [{broadaddr,any}]}, ok), + ok = sopt_2({[], []}, ok), + ok. + +sopt_2({Flags, Opts}, ok) -> + Broadcast = lists:member(broadcast, Flags), + P2P = lists:member(pointtopoint, Flags), + case Opts of + %% The following two clauses would be combined to one, silently + %% discarding the guard test of the P2P variable. + [{broadaddr,_}|Os] when Broadcast -> + sopt_2({Flags, Os}, ok); + [{dstaddr,_}|Os] when P2P -> + sopt_2({Flags, Os}, ok); + [] -> + ok + end. + beam_ssa_dead_crash(_Config) -> not_A_B = do_beam_ssa_dead_crash(id(false), id(true)), not_A_not_B = do_beam_ssa_dead_crash(false, false), |