diff options
author | John Högberg <john@erlang.org> | 2023-01-02 15:08:24 +0100 |
---|---|---|
committer | John Högberg <john@erlang.org> | 2023-01-02 15:18:08 +0100 |
commit | 334b590c6b930f42b5685dd77e2f19cedcd1f16e (patch) | |
tree | 730c7763bdad2339d17c7f2a251edc26ee0a7f56 | |
parent | 351a47865f036e7dbd79caa37263befbb8fff1c3 (diff) | |
download | erlang-334b590c6b930f42b5685dd77e2f19cedcd1f16e.tar.gz |
beam_validator: Bail on impossible sizes in bs_get_integer
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 58 | ||||
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 42 |
2 files changed, 71 insertions, 29 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 9188d7bd67..59dd35b3e4 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -977,8 +977,8 @@ vi({test,bs_get_integer2=Op,{f,Fail},Live,[Ctx,Sz0,Unit,{field_flags,Flags}],Dst #t_integer{elements={_,SizeMax}} when SizeMax * Unit < 64 -> NumBits = SizeMax * Unit, bs_integer_type(NumBits, Flags); - _ -> - #t_integer{} + Other -> + Other end, validate_bs_get(Op, Fail, Ctx, Live, Unit, Type, Dst, Vst); vi({test,bs_get_float2=Op,{f,Fail},Live,[Ctx,Size,Unit,_],Dst},Vst) -> @@ -1785,42 +1785,46 @@ bs_integer_type(NumBits, Flags) -> %% Common code for validating bs_get* instructions. %% +validate_bs_get(_Op, Fail, Ctx0, Live, _Stride, none, _Dst, Vst) -> + Ctx = unpack_typed_arg(Ctx0), + validate_bs_get_1( + Fail, Ctx, Live, Vst, + fun(SuccVst) -> + kill_state(SuccVst) + end); validate_bs_get(Op, Fail, Ctx0, Live, Stride, Type, Dst, Vst) -> Ctx = unpack_typed_arg(Ctx0), - - assert_no_exception(Fail), - - assert_type(#t_bs_context{}, Ctx, Vst), - verify_live(Live, Vst), - verify_y_init(Vst), - - branch(Fail, Vst, - fun(SuccVst0) -> - SuccVst1 = advance_bs_context(Ctx, Stride, SuccVst0), - SuccVst = prune_x_regs(Live, SuccVst1), - extract_term(Type, Op, [Ctx], Dst, SuccVst, SuccVst0) - end). + validate_bs_get_1( + Fail, Ctx, Live, Vst, + fun(SuccVst0) -> + SuccVst1 = advance_bs_context(Ctx, Stride, SuccVst0), + SuccVst = prune_x_regs(Live, SuccVst1), + extract_term(Type, Op, [Ctx], Dst, SuccVst, SuccVst0) + end). validate_bs_get_all(Op, Fail, Ctx0, Live, Stride, Type, Dst, Vst) -> Ctx = unpack_typed_arg(Ctx0), - + validate_bs_get_1( + Fail, Ctx, Live, Vst, + fun(SuccVst0) -> + %% This acts as an implicit unit test on the current match + %% position, so we'll update the unit in case we rewind here + %% later on. + SuccVst1 = update_bs_unit(Ctx, Stride, SuccVst0), + + SuccVst2 = advance_bs_context(Ctx, Stride, SuccVst1), + SuccVst = prune_x_regs(Live, SuccVst2), + extract_term(Type, Op, [Ctx], Dst, SuccVst, SuccVst0) + end). + +validate_bs_get_1(Fail, Ctx, Live, Vst, SuccFun) -> assert_no_exception(Fail), assert_type(#t_bs_context{}, Ctx, Vst), verify_live(Live, Vst), verify_y_init(Vst), - branch(Fail, Vst, - fun(SuccVst0) -> - %% This acts as an implicit unit test on the current match - %% position, so we'll update the unit in case we rewind here - %% later on. - SuccVst1 = update_bs_unit(Ctx, Stride, SuccVst0), - - SuccVst2 = advance_bs_context(Ctx, Stride, SuccVst1), - SuccVst = prune_x_regs(Live, SuccVst2), - extract_term(Type, Op, [Ctx], Dst, SuccVst, SuccVst0) - end). + branch(Fail, Vst, SuccFun). %% %% Common code for validating bs_skip* instructions. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 5a00a9ecf7..5070406cd3 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -42,7 +42,7 @@ bs_saved_position_units/1,parent_container/1, container_performance/1, infer_relops/1, - not_equal_inference/1]). + not_equal_inference/1,bad_bin_unit/1]). -include_lib("common_test/include/ct.hrl"). @@ -78,7 +78,7 @@ groups() -> missing_return_type,will_succeed, bs_saved_position_units,parent_container, container_performance,infer_relops, - not_equal_inference]}]. + not_equal_inference,bad_bin_unit]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), @@ -1062,5 +1062,43 @@ not_equal_inference(_Config) -> not_equal_inference_1(X) when (X /= []) /= is_port(0 div 0) -> [X || _ <- []]. +bad_bin_unit(_Config) -> + {'EXIT', {function_clause,_}} = catch bad_bin_unit_1(<<1:1>>), + [] = bad_bin_unit_2(), + ok. + +bad_bin_unit_1(<<X:((ok > {<<(true andalso ok)>>}) orelse 1)>>) -> + try + bad_bin_unit_1_a() + after + -(X + bad_bin_unit_1_b(not ok)), + try + ok + catch + _ -> + ok; + _ -> + ok; + _ -> + ok; + _ -> + ok; + _ -> + ok; + _ -> + ok + end + end. + +bad_bin_unit_1_a() -> ok. +bad_bin_unit_1_b(_) -> ok. + +bad_bin_unit_2() -> + [ + ok + || <<X:(is_number(<<(<<(0 bxor 0)>>)>>) orelse 1)>> <= <<>>, + #{X := _} <- ok + ]. + id(I) -> I. |