diff options
author | Anthony Ramine <[email protected]> | 2013-03-28 08:52:43 +0100 |
---|---|---|
committer | Fredrik Gustafsson <[email protected]> | 2013-06-05 12:08:39 +0200 |
commit | 90efeaf21147505b1e8207822e606027f94183cc (patch) | |
tree | a8f4709a1625aa7ac96e67b08a43119943aae34a /lib/stdlib/src | |
parent | 872987787b0d95b89c45920c8b5453a86580d201 (diff) | |
download | otp-90efeaf21147505b1e8207822e606027f94183cc.tar.gz otp-90efeaf21147505b1e8207822e606027f94183cc.tar.bz2 otp-90efeaf21147505b1e8207822e606027f94183cc.zip |
Forbid unsized fields in patterns of binary generators
It makes no sense to be able to do `<<...,Rest/binary>> <= ...` in a
comprehension. The related Dialyzer test is removed.
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r-- | lib/stdlib/src/erl_lint.erl | 21 | ||||
-rw-r--r-- | lib/stdlib/src/eval_bits.erl | 19 |
2 files changed, 32 insertions, 8 deletions
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 08b8541014..573b05e4e2 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -281,6 +281,8 @@ format_error(utf_bittype_size_or_unit) -> "neither size nor unit must be given for segments of type utf8/utf16/utf32"; format_error({bad_bitsize,Type}) -> io_lib:format("bad ~s bit size", [Type]); +format_error(unsized_binary_in_bin_gen_pattern) -> + "binary fields without size are not allowed in patterns of bit string generators"; %% --- behaviours --- format_error({conflicting_behaviours,{Name,Arity},B,FirstL,FirstB}) -> io_lib:format("conflicting behaviours - callback ~w/~w required by both '~p' " @@ -2878,7 +2880,8 @@ lc_quals([{generate,_Line,P,E} | Qs], Vt0, Uvt0, St0) -> {Vt,Uvt,St} = handle_generator(P,E,Vt0,Uvt0,St0), lc_quals(Qs, Vt, Uvt, St); lc_quals([{b_generate,_Line,P,E} | Qs], Vt0, Uvt0, St0) -> - {Vt,Uvt,St} = handle_generator(P,E,Vt0,Uvt0,St0), + St1 = handle_bitstring_gen_pat(P,St0), + {Vt,Uvt,St} = handle_generator(P,E,Vt0,Uvt0,St1), lc_quals(Qs, Vt, Uvt, St); lc_quals([F|Qs], Vt, Uvt, St0) -> {Fvt,St1} = case is_guard_test2(F, St0#lint.records) of @@ -2906,6 +2909,22 @@ handle_generator(P,E,Vt,Uvt,St0) -> Vt3 = vtupdate(vtsubtract(Vt2, Binvt), Binvt), {Vt3,NUvt,St5}. +handle_bitstring_gen_pat({bin,_,Segments=[_|_]},St) -> + case lists:last(Segments) of + {bin_element,Line,{var,_,_},default,Flags} when is_list(Flags) -> + case member(binary, Flags) orelse member(bits, Flags) + orelse member(bitstring, Flags) of + true -> + add_error(Line, unsized_binary_in_bin_gen_pattern, St); + false -> + St + end; + _ -> + St + end; +handle_bitstring_gen_pat(_,St) -> + St. + %% fun_clauses(Clauses, ImportVarTable, State) -> %% {UsedVars, State}. %% Fun's cannot export any variables. diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl index e49cbc1fd1..75fe2c00c7 100644 --- a/lib/stdlib/src/eval_bits.erl +++ b/lib/stdlib/src/eval_bits.erl @@ -192,7 +192,7 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0}, make_bit_type(Line, Size0, Options0), V = erl_eval:partial_eval(VE), NewV = coerce_to_float(V, Type), - match_check_size(Mfun, Size1, BBs0), + match_check_size(Mfun, Size1, BBs0, false), {value, Size, _BBs} = Efun(Size1, BBs0), bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun). @@ -380,20 +380,25 @@ make_bit_type(_Line, Size, Type0) -> %Size evaluates to an integer or 'all' {error,Reason} -> error(Reason) end. -match_check_size(Mfun, {var,_,V}, Bs) -> +match_check_size(Mfun, Size, Bs) -> + match_check_size(Mfun, Size, Bs, true). + +match_check_size(Mfun, {var,_,V}, Bs, _AllowAll) -> case Mfun(binding, {V,Bs}) of {value,_} -> ok; unbound -> throw(invalid) % or, rather, error({unbound,V}) end; -match_check_size(_, {atom,_,all}, _Bs) -> +match_check_size(_, {atom,_,all}, _Bs, true) -> ok; -match_check_size(_, {atom,_,undefined}, _Bs) -> +match_check_size(_, {atom,_,all}, _Bs, false) -> + throw(invalid); +match_check_size(_, {atom,_,undefined}, _Bs, _AllowAll) -> ok; -match_check_size(_, {integer,_,_}, _Bs) -> +match_check_size(_, {integer,_,_}, _Bs, _AllowAll) -> ok; -match_check_size(_, {value,_,_}, _Bs) -> +match_check_size(_, {value,_,_}, _Bs, _AllowAll) -> ok; %From the debugger. -match_check_size(_, _, _Bs) -> +match_check_size(_, _, _Bs, _AllowAll) -> throw(invalid). %% error(Reason) -> exception thrown |