diff options
author | Björn Gustavsson <[email protected]> | 2014-01-24 16:21:10 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2014-01-24 16:46:21 +0100 |
commit | 3ec5e5594657db530072be69ba94e4e655e4a407 (patch) | |
tree | 9297274b5e96041caac4b7e7d234f16444a99f6b /lib | |
parent | ab20369b433a8e6440e5e71a1c92bf7440916192 (diff) | |
download | otp-3ec5e5594657db530072be69ba94e4e655e4a407.tar.gz otp-3ec5e5594657db530072be69ba94e4e655e4a407.tar.bz2 otp-3ec5e5594657db530072be69ba94e4e655e4a407.zip |
beam_except: Eliminate compiler crash
Code such as:
bar(X) ->
case {X+1} of
1 -> ok
end.
would crash the beam_except pass of the compiler.
The reason for the crash is that the '+' operator would add a line/1
instruction that the beam_except pass was not prepared to handle.
Reported-by: Erik Søe Sørensen
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compiler/src/beam_except.erl | 10 | ||||
-rw-r--r-- | lib/compiler/test/beam_except_SUITE.erl | 10 |
2 files changed, 17 insertions, 3 deletions
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl index e5ec1bd904..d261809765 100644 --- a/lib/compiler/src/beam_except.erl +++ b/lib/compiler/src/beam_except.erl @@ -131,9 +131,13 @@ translate_exception(_, _, _, _) -> no. fix_block(Is, 0) -> reverse(Is); -fix_block(Is0, Words) -> - [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is] = reverse(Is0), - [{set,[],[],{alloc,Live,{F1,F2,Needed-Words,F3}}}|Is]. +fix_block(Is, Words) -> + fix_block_1(reverse(Is), Words). + +fix_block_1([{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is], Words) -> + [{set,[],[],{alloc,Live,{F1,F2,Needed-Words,F3}}}|Is]; +fix_block_1([I|Is], Words) -> + [I|fix_block_1(Is, Words)]. dig_out_block_fc([{set,[],[],{alloc,Live,_}}|Bl]) -> case dig_out_fc(Bl, Live-1, nil) of diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl index bf67eedd5f..d088863c5c 100644 --- a/lib/compiler/test/beam_except_SUITE.erl +++ b/lib/compiler/test/beam_except_SUITE.erl @@ -57,6 +57,11 @@ coverage(_) -> {'EXIT',{undef,[{erlang,error,[a,b,c],_}|_]}} = (catch erlang:error(a, b, c)), + + {'EXIT',{badarith,[{?MODULE,bar,1,[File,{line,9}]}|_]}} = + (catch bar(x)), + {'EXIT',{{case_clause,{1}},[{?MODULE,bar,1,[File,{line,9}]}|_]}} = + (catch bar(0)), ok. -file("fake.erl", 1). @@ -65,3 +70,8 @@ fc(a) -> %Line 2 fc(L) when length(L) > 2 -> %Line 4 %% Not the same as a "real" function_clause error. error(function_clause, [L]). %Line 6 +%% Would crash the compiler. +bar(X) -> %Line 8 + case {X+1} of %Line 9 + 1 -> ok %Line 10 + end. %Line 11 |