summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Högberg <john@erlang.org>2023-01-02 15:08:24 +0100
committerJohn Högberg <john@erlang.org>2023-01-02 15:18:08 +0100
commit334b590c6b930f42b5685dd77e2f19cedcd1f16e (patch)
tree730c7763bdad2339d17c7f2a251edc26ee0a7f56
parent351a47865f036e7dbd79caa37263befbb8fff1c3 (diff)
downloaderlang-334b590c6b930f42b5685dd77e2f19cedcd1f16e.tar.gz
beam_validator: Bail on impossible sizes in bs_get_integer
-rw-r--r--lib/compiler/src/beam_validator.erl58
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl42
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.