aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2016-01-11 15:58:57 +0100
committerBjörn Gustavsson <[email protected]>2016-01-12 10:06:02 +0100
commitff2ef4278045c985738e3ddb4af6127c7db933e7 (patch)
tree77dda64e520079c050639390c63f70866f7da4cf /lib/compiler/src
parent12dffc7f0c85aa4662b97cba4af2c9ae2ba74083 (diff)
downloadotp-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.erl2
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}.