diff options
author | Björn-Egil Dahlberg <[email protected]> | 2014-03-11 14:50:46 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-03-17 17:47:35 +0100 |
commit | 90a948d7cf7f188b5461c2a7bb25a656ec681966 (patch) | |
tree | 9e114d1103136b6e85b6316726347a876ae127b7 /lib/compiler/src/v3_kernel.erl | |
parent | c43dd2abaae653d5411fc662cad177c5971dde3b (diff) | |
download | otp-90a948d7cf7f188b5461c2a7bb25a656ec681966.tar.gz otp-90a948d7cf7f188b5461c2a7bb25a656ec681966.tar.bz2 otp-90a948d7cf7f188b5461c2a7bb25a656ec681966.zip |
compiler: Validate Map src
Reject all expressions that are known to fail.
Emit 'badarg' for those expressions.
Ex.
[]#{ a => 1}
Is not a valid map update expression.
Diffstat (limited to 'lib/compiler/src/v3_kernel.erl')
-rw-r--r-- | lib/compiler/src/v3_kernel.erl | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index d00dd56f30..ecff01c4e5 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -272,9 +272,18 @@ expr(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub, St0) -> expr(#c_tuple{anno=A,es=Ces}, Sub, St0) -> {Kes,Ep,St1} = atomic_list(Ces, Sub, St0), {#k_tuple{anno=A,es=Kes},Ep,St1}; -expr(#c_map{anno=A,var=Var0,es=Ces}, Sub, St0) -> - {Var,[],St1} = expr(Var0, Sub, St0), - map_split_pairs(A, Var, Ces, Sub, St1); +expr(#c_map{anno=A,var=Var,es=Ces}, Sub, St0) -> + try expr_map(A,Var,Ces,Sub,St0) of + {_,_,_}=Res -> Res + catch + throw:bad_map -> + St1 = add_warning(get_line(A), bad_map, A, St0), + Erl = #c_literal{val=erlang}, + Name = #c_literal{val=error}, + Args = [#c_literal{val=badarg}], + Error = #c_call{anno=A,module=Erl,name=Name,args=Args}, + expr(Error, Sub, St1) + end; expr(#c_binary{anno=A,segments=Cv}, Sub, St0) -> try atomic_bin(Cv, Sub, St0) of {Kv,Ep,St1} -> @@ -496,6 +505,21 @@ translate_match_fail_1(Anno, As, Sub, #kern{ff=FF}) -> translate_fc(Args) -> [#c_literal{val=function_clause},make_list(Args)]. +expr_map(A,Var0,Ces,Sub,St0) -> + %% An extra pass of validation of Map src because of inlining + {Var,Mps,St1} = expr(Var0, Sub, St0), + case is_valid_map_src(Var) of + true -> + {Km,Eps,St2} = map_split_pairs(A, Var, Ces, Sub, St1), + {Km,Eps++Mps,St2}; + false -> throw(bad_map) + end. + +is_valid_map_src(#k_map{}) -> true; +is_valid_map_src(#k_literal{val=M}) when is_map(M) -> true; +is_valid_map_src(#k_var{}) -> true; +is_valid_map_src(_) -> false. + map_split_pairs(A, Var, Ces, Sub, St0) -> %% two steps %% 1. force variables @@ -1986,7 +2010,9 @@ format_error(nomatch_shadow) -> format_error(bad_call) -> "invalid module and/or function name; this call will always fail"; format_error(bad_segment_size) -> - "binary construction will fail because of a type mismatch". + "binary construction will fail because of a type mismatch"; +format_error(bad_map) -> + "map construction will fail because of a type mismatch". add_warning(none, Term, Anno, #kern{ws=Ws}=St) -> File = get_file(Anno), |