diff options
| author | Björn Gustavsson <[email protected]> | 2016-08-11 15:35:29 +0200 | 
|---|---|---|
| committer | Björn Gustavsson <[email protected]> | 2016-08-11 15:43:46 +0200 | 
| commit | d39cac954fc76a838763ac1ac03cb71bf8e5d68d (patch) | |
| tree | 16b3b7464f794f1f8911773e92d49201a6f26ff2 | |
| parent | 4ab154e94aaaf6cb4e610595a31609559eb1732c (diff) | |
| download | otp-d39cac954fc76a838763ac1ac03cb71bf8e5d68d.tar.gz otp-d39cac954fc76a838763ac1ac03cb71bf8e5d68d.tar.bz2 otp-d39cac954fc76a838763ac1ac03cb71bf8e5d68d.zip | |
[ERL-209] Fix ambiguous_catch_try_state inconsistency error
It is not safe to share code between 'catch' blocks.
| -rw-r--r-- | lib/compiler/src/beam_jump.erl | 22 | ||||
| -rw-r--r-- | lib/compiler/test/beam_jump_SUITE.erl | 19 | 
2 files changed, 31 insertions, 10 deletions
| diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index 09cd3aa2d4..48b5a32814 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -167,12 +167,18 @@ share_1([{label,L}=Lbl|Is], Dict0, Seq, Acc) ->      end;  share_1([{func_info,_,_,_}=I|Is], _, [], Acc) ->      reverse(Is, [I|Acc]); +share_1([{'catch',_,_}=I|Is], Dict0, Seq, Acc) -> +    Dict = clean_non_sharable(Dict0), +    share_1(Is, Dict, [I|Seq], Acc);  share_1([{'try',_,_}=I|Is], Dict0, Seq, Acc) ->      Dict = clean_non_sharable(Dict0),      share_1(Is, Dict, [I|Seq], Acc);  share_1([{try_case,_}=I|Is], Dict0, Seq, Acc) ->      Dict = clean_non_sharable(Dict0),      share_1(Is, Dict, [I|Seq], Acc); +share_1([{catch_end,_}=I|Is], Dict0, Seq, Acc) -> +    Dict = clean_non_sharable(Dict0), +    share_1(Is, Dict, [I|Seq], Acc);  share_1([I|Is], Dict, Seq, Acc) ->      case is_unreachable_after(I) of  	false -> @@ -182,18 +188,18 @@ share_1([I|Is], Dict, Seq, Acc) ->      end.  clean_non_sharable(Dict) -> -    %% We are passing in or out of a 'try' block. Remove -    %% sequences that should not shared over the boundaries -    %% of a 'try' block. Since the end of the sequence must match, -    %% the only possible match between a sequence outside and -    %% a sequence inside the 'try' block is a sequence that ends -    %% with an instruction that causes an exception. Any sequence -    %% that causes an exception must contain a line/1 instruction. +    %% We are passing in or out of a 'catch' or 'try' block. Remove +    %% sequences that should not be shared over the boundaries of the +    %% block. Since the end of the sequence must match, the only +    %% possible match between a sequence outside and a sequence inside +    %% the 'catch'/'try' block is a sequence that ends with an +    %% instruction that causes an exception. Any sequence that causes +    %% an exception must contain a line/1 instruction.      maps:filter(fun(K, _V) -> sharable_with_try(K) end, Dict).  sharable_with_try([{line,_}|_]) ->      %% This sequence may cause an exception and may potentially -    %% match a sequence on the other side of the 'try' block +    %% match a sequence on the other side of the 'catch'/'try' block      %% boundary.      false;  sharable_with_try([_|Is]) -> diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl index 0b13adaff2..088f63606c 100644 --- a/lib/compiler/test/beam_jump_SUITE.erl +++ b/lib/compiler/test/beam_jump_SUITE.erl @@ -21,7 +21,7 @@  -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,  	 init_per_group/2,end_per_group/2, -	 undefined_label/1]). +	 undefined_label/1,ambiguous_catch_try_state/1]).  suite() ->      [{ct_hooks,[ts_install_cth]}]. @@ -32,7 +32,8 @@ all() ->  groups() ->      [{p,[parallel], -      [undefined_label +      [undefined_label, +       ambiguous_catch_try_state        ]}].  init_per_suite(Config) -> @@ -57,3 +58,17 @@ flights(0, [], []) when [], 0; 0.0, [], false ->      clark;  flights(_, Reproduction, introduction) when false, Reproduction ->      responsible. + +%% [ERL-209] beam_jump would share 'catch' blocks, causing an +%% ambiguous_catch_try_state error in beam_validator. + +ambiguous_catch_try_state(_Config) -> +    {{'EXIT',{{case_clause,song},_}},{'EXIT',{{case_clause,song},_}}} = +	checks(42), +    ok. + +river() -> song. + +checks(Wanted) -> +    %% Must be one line to cause the unsafe optimization. +    {catch case river() of sheet -> begin +Wanted, if "da" -> Wanted end end end, catch case river() of sheet -> begin + Wanted, if "da" -> Wanted end end end}. | 
