diff options
author | Björn Gustavsson <bjorn@erlang.org> | 2023-04-28 06:31:36 +0200 |
---|---|---|
committer | Björn Gustavsson <bjorn@erlang.org> | 2023-04-28 07:26:00 +0200 |
commit | 9a37583f4b319ecca3424f353aa6d4cd4e6b3fe2 (patch) | |
tree | 7b64dc3f2dd3406fd317e47db6ec684930ed4d98 | |
parent | 432aae16404da21d75ae85889e413d9843333d5e (diff) | |
download | erlang-9a37583f4b319ecca3424f353aa6d4cd4e6b3fe2.tar.gz |
Eliminate internal error in beam_types:float_from_range/1
Closes #7178
-rw-r--r-- | lib/compiler/src/beam_types.erl | 19 | ||||
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 37 |
2 files changed, 52 insertions, 4 deletions
diff --git a/lib/compiler/src/beam_types.erl b/lib/compiler/src/beam_types.erl index 9c3da159c4..b668251f79 100644 --- a/lib/compiler/src/beam_types.erl +++ b/lib/compiler/src/beam_types.erl @@ -1182,11 +1182,24 @@ float_from_range(any) -> float_from_range({'-inf','+inf'}) -> #t_float{}; float_from_range({'-inf',Max}) -> - #t_float{elements={'-inf',float(Max)}}; + make_float_range('-inf', safe_float(Max)); float_from_range({Min,'+inf'}) -> - #t_float{elements={float(Min),'+inf'}}; + make_float_range(safe_float(Min), '+inf'); float_from_range({Min,Max}) -> - #t_float{elements={float(Min),float(Max)}}. + make_float_range(safe_float(Min), safe_float(Max)). + +safe_float(N) when is_number(N) -> + try + float(N) + catch + error:_ when N < 0 -> '-inf'; + error:_ when N > 0 -> '+inf' + end. + +make_float_range('-inf', '+inf') -> + #t_float{}; +make_float_range(Min, Max) -> + #t_float{elements={Min, Max}}. integer_from_range(none) -> none; diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 6562b3228f..94aca11b01 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -22,7 +22,8 @@ -export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, integers/1,numbers/1,coverage/1,booleans/1,setelement/1, - cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1, + cons/1,tuple/1, + record_float/1,binary_float/1,float_compare/1,float_overflow/1, arity_checks/1,elixir_binaries/1,find_best/1, test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1, none_argument/1,success_type_oscillation/1,type_subtraction/1, @@ -51,6 +52,7 @@ groups() -> record_float, binary_float, float_compare, + float_overflow, arity_checks, elixir_binaries, find_best, @@ -771,6 +773,39 @@ do_float_compare(X) -> _T -> Y > 0 end. +float_overflow(_Config) -> + Res1 = id((1 bsl 1023) * two()), + Res1 = float_overflow_1(), + + Res2 = id((-1 bsl 1023) * two()), + Res2 = float_overflow_2(), + + ok. + +%% GH-7178: There would be an overflow when converting a number range +%% to a float range. +float_overflow_1() -> + round( + try + round(float(1 bsl 1023)) * two() + catch + _:_ -> + 0.0 + end + ). + +float_overflow_2() -> + round( + try + round(float(-1 bsl 1023)) * two() + catch + _:_ -> + 0.0 + end + ). + +two() -> 2. + arity_checks(_Config) -> %% ERL-549: an unsafe optimization removed a test_arity instruction, %% causing the following to return 'broken' instead of 'ok'. |