diff options
author | Björn Gustavsson <[email protected]> | 2016-02-08 07:06:31 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-02-08 08:08:55 +0100 |
commit | abde1d03db03536af19fdb274f1119bbfaba262b (patch) | |
tree | fc7eb2311be3f3aa458fb298a5a23803b7bbfe67 /lib/compiler/src/beam_bsm.erl | |
parent | a03b7add86b92d0d7d2d744e5555314bedbc2197 (diff) | |
download | otp-abde1d03db03536af19fdb274f1119bbfaba262b.tar.gz otp-abde1d03db03536af19fdb274f1119bbfaba262b.tar.bz2 otp-abde1d03db03536af19fdb274f1119bbfaba262b.zip |
Eliminate crash because of unsafe delaying of sub-binary creation
The following code would fail to compile:
decode(<<Code/integer, Bin/binary>>) ->
<<C1/integer, B1/binary>> = Bin,
case C1 of
X when X =:= 1 orelse X =:= 2 ->
Bin2 = <<>>;
_ ->
Bin2 = B1
end,
case Code of
1 -> decode(Bin2);
_ -> Bin2
end.
The error message would be:
t: function decode/1+28:
Internal consistency check failed - please report this bug.
Instruction: return
Error: {match_context,{x,0}}:
The beam_bsm pass would delay the creation of a sub-binary when it was
unsafe to do so. The culprit was the btb_follow_branch/3 function that
for performance reasons cached labels that had already been checked.
The problem was the safety of a label also depends on the contents
of the registers. Therefore, the key for caching needs to be both
the label and the register contents.
Reported-by: José Valim
Diffstat (limited to 'lib/compiler/src/beam_bsm.erl')
-rw-r--r-- | lib/compiler/src/beam_bsm.erl | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl index 4f76350269..62356928ae 100644 --- a/lib/compiler/src/beam_bsm.erl +++ b/lib/compiler/src/beam_bsm.erl @@ -421,7 +421,8 @@ btb_follow_branches([], _, D) -> D. btb_follow_branch(0, _Regs, D) -> D; btb_follow_branch(Lbl, Regs, #btb{ok_br=Br0,index=Li}=D) -> - case gb_sets:is_member(Lbl, Br0) of + Key = {Lbl,Regs}, + case gb_sets:is_member(Key, Br0) of true -> %% We have already followed this branch and it was OK. D; @@ -432,7 +433,7 @@ btb_follow_branch(Lbl, Regs, #btb{ok_br=Br0,index=Li}=D) -> btb_reaches_match_1(Is, Regs, D), %% Since we got back, this branch is OK. - D#btb{ok_br=gb_sets:insert(Lbl, Br),must_not_save=MustNotSave, + D#btb{ok_br=gb_sets:insert(Key, Br),must_not_save=MustNotSave, must_save=MustSave} end. |