diff options
author | Björn Gustavsson <[email protected]> | 2016-01-11 15:58:57 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-01-12 10:06:02 +0100 |
commit | ff2ef4278045c985738e3ddb4af6127c7db933e7 (patch) | |
tree | 77dda64e520079c050639390c63f70866f7da4cf /lib/compiler/src | |
parent | 12dffc7f0c85aa4662b97cba4af2c9ae2ba74083 (diff) | |
download | otp-ff2ef4278045c985738e3ddb4af6127c7db933e7.tar.gz otp-ff2ef4278045c985738e3ddb4af6127c7db933e7.tar.bz2 otp-ff2ef4278045c985738e3ddb4af6127c7db933e7.zip |
Fix crash when attempting to update a fun as if it were a map
The following example would cause an internal consistency
failure in the compiler:
f() -> ok.
update() -> (fun f/0)#{u => 42}.
The reason is that internally, v3_core will (incorrectly)
rewrite update/0 to code similar to this:
update() ->
if
is_map(fun f/0) ->
maps:update(u, 42, fun f/0)
end.
Since funs are not allowed to be created in guards, incorrect and
unsafe code would be generated.
It is easy to fix the bug. There already is a is_valid_map_src/1
function in v3_core that tests whether the argument for the map update
operation can possibly be a valid map. A fun is represented as a
variable with a special name in Core Erlang, so it would not be
recognized as unsafe. All we'll need to do to fix the bug is to look
closer at variables to ensure they don't represent funs. That will
ensure that the code is rewritten in the correct way:
update() ->
error({badmap,fun f/0})
end.
Reported-by: Thomas Arts
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/v3_core.erl | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 0941ad5dd5..7d93e2ae16 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -804,7 +804,7 @@ map_op(map_field_assoc) -> #c_literal{val=assoc}; map_op(map_field_exact) -> #c_literal{val=exact}. is_valid_map_src(#c_literal{val = M}) when is_map(M) -> true; -is_valid_map_src(#c_var{}) -> true; +is_valid_map_src(#c_var{}=Var) -> not cerl:is_c_fname(Var); is_valid_map_src(_) -> false. %% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}. |