File 0491-Don-t-match-bad-float-values-when-the-value-is-ignor.patch of Package erlang

From b79d1fbdfbea6442e2c98510aefc01f62cacd180 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 12 Oct 2020 07:50:22 +0200
Subject: [PATCH 2/3] Don't match bad float values when the value is ignored

When the matched out value was ignored when matching a float value,
the match would always succeed. For example, the following matches
would succeed:

    <<_:1/float>> = Bin
    <<_/float>> = NaN
---
 lib/compiler/src/beam_ssa_opt.erl         | 4 +++-
 lib/compiler/src/beam_ssa_pre_codegen.erl | 6 ++++++
 lib/compiler/test/bs_bincomp_SUITE.erl    | 5 +++++
 lib/compiler/test/bs_match_SUITE.erl      | 5 +++++
 4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index d77ad0cddf..787408a894 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -1515,7 +1515,9 @@ bsm_skip_is([I0|Is], Extracted) ->
         #b_set{op=bs_match,
                dst=Ctx,
                args=[#b_literal{val=T}=Type,PrevCtx|Args0]}
-          when T =/= string, T =/= skip ->
+          when T =/= float, T =/= string, T =/= skip ->
+            %% Note that it is never safe to skip matching
+            %% of floats, even if the size is known to be correct.
             I = case cerl_sets:is_element(Ctx, Extracted) of
                     true ->
                         I0;
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index c9f6ad9513..efab700dbb 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -921,6 +921,12 @@ sanitize_instr({bif,Bif}, [#b_literal{val=Lit1},#b_literal{val=Lit2}], _I) ->
         error:_ ->
             ok
     end;
+sanitize_instr(bs_match, Args, I) ->
+    %% Matching of floats are never changed to a bs_skip even when the
+    %% value is never used, because the match can always fail (for example,
+    %% if it is a NaN).
+    [#b_literal{val=float}|_] = Args,           %Assertion.
+    {ok,I#b_set{op=bs_get}};
 sanitize_instr(get_hd, [#b_literal{val=[Hd|_]}], _I) ->
     {value,Hd};
 sanitize_instr(get_tl, [#b_literal{val=[_|Tl]}], _I) ->
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index 48c91f856c..2218b007d8 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -194,6 +194,12 @@
 
 nomatch(Config) when is_list(Config) ->
     <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>,
+
+    <<>> = << <<"a">> || <<_:1/float>> <= Bin>>,
+
+    NaN = <<(-1):32>>,
+    <<>> = << <<"a">> || <<_:32/float>> <= NaN >>,
+
     ok.
 
 sizes(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 0bfd6c1fb8..8748cc8f46 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -1261,6 +1261,11 @@ bad_size(Config) when is_list(Config) ->
     {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)),
     Binary = <<1,2,3>>,
     {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)),
+    NaN = <<(-1):32>>,
+    {'EXIT',{{badmatch,<<>>},_}} = (catch <<42.0:1/float>> = id(<<>>)),
+    {'EXIT',{{badmatch,NaN},_}} = (catch <<42.0:32/float>> = id(NaN)),
+    {'EXIT',{{badmatch,<<1:1>>},_}} = (catch <<_:1/float>> = id(<<1:1>>)),
+    {'EXIT',{{badmatch,NaN},_}} = (catch <<_:32/float>> = id(NaN)),
     ok.
 
 haystack(Config) when is_list(Config) ->
-- 
2.26.2

openSUSE Build Service is sponsored by