File 4701-beam_validator-Improve-arithmetic-range-inference.patch of Package erlang
From 3b3e4625195443cfe9186b82cd556fd6b4c49ebf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Wed, 26 Apr 2023 07:31:27 +0200
Subject: [PATCH] beam_validator: Improve arithmetic range inference
Fixes #7171
---
lib/compiler/src/beam_validator.erl | 12 +++++++++++-
lib/compiler/test/beam_validator_SUITE.erl | 21 +++++++++++++++++++--
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index f19ea897fe..c11b4b8a2f 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -3429,7 +3429,17 @@ bif_types(Op, Ss, Vst) ->
Other
end;
{_,_} ->
- beam_call_types:types(erlang, Op, Args)
+ Res0 = beam_call_types:types(erlang, Op, Args),
+ {Ret0, ArgTypes, SubSafe} = Res0,
+
+ %% Match the non-converging range analysis done in
+ %% `beam_ssa_type:opt_ranges/1`. This is safe since the validator
+ %% doesn't have to worry about convergence.
+ case beam_call_types:arith_type({bif, Op}, Args) of
+ any -> Res0;
+ Ret0 -> Res0;
+ Ret -> {meet(Ret, Ret0), ArgTypes, SubSafe}
+ end
end.
join_tuple_elements(Tuple) ->
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 6b63f561c1..2092d7401a 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -43,7 +43,7 @@
bs_saved_position_units/1,parent_container/1,
container_performance/1,
not_equal_inference/1,singleton_inference/1,
- inert_update_type/1,
+ inert_update_type/1,range_inference/1,
too_many_arguments/1]).
-include_lib("common_test/include/ct.hrl").
@@ -80,7 +80,7 @@ groups() ->
bs_saved_position_units,parent_container,
container_performance,
not_equal_inference,singleton_inference,
- inert_update_type,
+ inert_update_type,range_inference,
too_many_arguments]}].
init_per_suite(Config) ->
@@ -1129,6 +1129,23 @@ mike([Head | _Rest]) -> joe(Head).
joe({Name, 42}) -> Name;
joe({sys_period, {A, _B}}) -> {41, 42, A}.
+range_inference(_Config) ->
+ ok = range_inference_1(id(<<$a>>)),
+ ok = range_inference_1(id(<<0>>)),
+ ok = range_inference_1(id(<<1114111/utf8>>)),
+
+ ok.
+
+range_inference_1(<<X/utf8>>) ->
+ case 9223372036854775807 - abs(X) of
+ Y when X < Y ->
+ ok;
+ 9223372036854775807 ->
+ ok;
+ -2147483648 ->
+ ok
+ end.
+
%% GH-9113: We didn't reject funs, comprehensions, and the likes which exceeded
%% the argument limit.
too_many_arguments(_Config) ->
--
2.35.3