diff options
Diffstat (limited to 'lib/compiler/src/beam_validator.erl')
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 4c9122d2c6..050dc563eb 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -995,6 +995,18 @@ vi(raw_raise=I, Vst0) -> vi(bs_init_writable=I, Vst) -> validate_body_call(I, 1, Vst); +vi({bs_create_bin,{f,Fail},Heap,Live,Unit,Dst,{list,List}}, Vst0) -> + verify_live(Live, Vst0), + verify_y_init(Vst0), + verify_create_bin_list(List, Vst0), + Vst = heap_alloc(Heap, Vst0), + branch(Fail, Vst, + fun(SuccVst0) -> + SuccVst1 = update_create_bin_list(List, SuccVst0), + SuccVst = prune_x_regs(Live, SuccVst1), + create_term(#t_bitstring{size_unit=Unit}, bs_create_bin, [], Dst, + SuccVst, SuccVst1) + end); vi({bs_init2,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) -> verify_live(Live, Vst0), verify_y_init(Vst0), @@ -1305,6 +1317,54 @@ pmt_1([Key0, Value0 | List], Vst, Acc0) -> pmt_1([], _Vst, Acc) -> Acc. +verify_create_bin_list([{atom,string},_Seg,Unit,Flags,Val,Size|Args], Vst) -> + assert_bs_unit({atom,string}, Unit), + assert_term(Flags, Vst), + case Val of + {string,Bs} when is_binary(Bs) -> ok; + _ -> error({not_string,Val}) + end, + assert_term(Flags, Vst), + assert_term(Size, Vst), + verify_create_bin_list(Args, Vst); +verify_create_bin_list([Type,_Seg,Unit,Flags,Val,Size|Args], Vst) -> + assert_term(Type, Vst), + assert_bs_unit(Type, Unit), + assert_term(Flags, Vst), + assert_term(Val, Vst), + assert_term(Size, Vst), + verify_create_bin_list(Args, Vst); +verify_create_bin_list([], _Vst) -> ok. + +update_create_bin_list([{atom,string},_Seg,_Unit,_Flags,_Val,_Size|T], Vst) -> + update_create_bin_list(T, Vst); +update_create_bin_list([{atom,Op},_Seg,_Unit,_Flags,Val,_Size|T], Vst0) -> + Type = update_create_bin_type(Op), + Vst = update_type(fun meet/2, Type, Val, Vst0), + update_create_bin_list(T, Vst); +update_create_bin_list([], Vst) -> Vst. + +update_create_bin_type(append) -> #t_bitstring{}; +update_create_bin_type(private_append) -> #t_bitstring{}; +update_create_bin_type(binary) -> #t_bitstring{}; +update_create_bin_type(float) -> #t_float{}; +update_create_bin_type(integer) -> #t_integer{}; +update_create_bin_type(utf8) -> #t_integer{}; +update_create_bin_type(utf16) -> #t_integer{}; +update_create_bin_type(utf32) -> #t_integer{}. + +assert_bs_unit({atom,Type}, 0) -> + case Type of + utf8 -> ok; + utf16 -> ok; + utf32 -> ok; + _ -> error({zero_unit_invalid_for_type,Type}) + end; +assert_bs_unit({atom,_Type}, Unit) when is_integer(Unit), 0 < Unit, Unit =< 256 -> + ok; +assert_bs_unit(_, Unit) -> + error({invalid,Unit}). + %% %% Common code for validating returns, whether naked or as part of a tail call. %% |