aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_validator.erl
diff options
context:
space:
mode:
authorJohn Högberg <[email protected]>2019-02-08 11:35:43 +0100
committerJohn Högberg <[email protected]>2019-02-08 15:47:13 +0100
commit9fc7477cb5452f7ca745f03fe10fbd895e9fff6c (patch)
treef1e991f263b3c0ade3db8c1ebf7ddb1d9ae38c3d /lib/compiler/src/beam_validator.erl
parent70aba8f1b77ebb40c9ea39cbcb5f78177c5c1283 (diff)
downloadotp-9fc7477cb5452f7ca745f03fe10fbd895e9fff6c.tar.gz
otp-9fc7477cb5452f7ca745f03fe10fbd895e9fff6c.tar.bz2
otp-9fc7477cb5452f7ca745f03fe10fbd895e9fff6c.zip
beam_validator: Explain why verify_get_map wipes dst registers
Diffstat (limited to 'lib/compiler/src/beam_validator.erl')
-rw-r--r--lib/compiler/src/beam_validator.erl14
1 files changed, 11 insertions, 3 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index a336cf7680..3713d2c573 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -896,12 +896,20 @@ valfun_4(_, _) ->
verify_get_map(Fail, Src, List, Vst0) ->
assert_not_literal(Src), %OTP 22.
assert_type(map, Src, Vst0),
- Vst1 = foldl(fun(D, Vsti) ->
- case is_reg_defined(D,Vsti) of
- true -> create_term(term, D, Vsti);
+
+ %% get_map_elements may leave its destinations in an inconsistent state
+ %% when the fail label is taken. Consider the following:
+ %%
+ %% {get_map_elements,{f,7},{x,1},{list,[{atom,a},{x,1},{atom,b},{x,2}]}}.
+ %%
+ %% If 'a' exists but not 'b', {x,1} is overwritten when we jump to {f,7}.
+ Vst1 = foldl(fun(Dst, Vsti) ->
+ case is_reg_defined(Dst,Vsti) of
+ true -> extract_term(term, [Src], Dst, Vsti);
false -> Vsti
end
end, Vst0, extract_map_vals(List)),
+
Vst2 = branch_state(Fail, Vst1),
Keys = extract_map_keys(List),
assert_unique_map_keys(Keys),