File 2114-v3_kernel-Eliminate-crash-for-pattern-matching.patch of Package erlang

From 5d5f8e3a3df0f1d74357cac767c100d1e31a8fe4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 24 Feb 2020 07:02:37 +0100
Subject: [PATCH 12/30] v3_kernel: Eliminate crash for pattern matching

The following example would crash v3_kernel:

    foo(<<42>>) -> place;
    foo(<<V:0>>) -> V.
---
 lib/compiler/src/v3_kernel.erl       | 10 +++++++---
 lib/compiler/test/bs_match_SUITE.erl | 11 +++++++++++
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index ca788bb40e..ae0ac97778 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -2216,8 +2216,9 @@ fix_count_without_variadic_segment(N) -> N.
 %% If we have more than 16 clauses, then it is better
 %% to branch multiple times than getting a large integer.
 %% We also abort if we have nothing to squeeze.
-squeeze_clauses(Clauses, Size, Count) when Count >= 16; Size == 1 -> Clauses;
-squeeze_clauses(Clauses, Size, _Count) -> squeeze_clauses(Clauses, Size).
+squeeze_clauses(Clauses, Size, Count) when Count >= 16; Size =< 1 -> Clauses;
+squeeze_clauses(Clauses, Size, _Count) ->
+    squeeze_clauses(Clauses, Size).
 
 squeeze_clauses([#iclause{pats=[#k_bin_seg{seg=#k_literal{}} = BinSeg | Pats]} = Clause | Clauses], Size) ->
     [Clause#iclause{pats=[squeeze_segments(BinSeg, 0, 0, Size) | Pats]} |
@@ -2228,7 +2229,10 @@ squeeze_clauses([], _Size) ->
 squeeze_segments(#k_bin_seg{size=Sz, seg=#k_literal{val=Val}=Lit} = BinSeg, Acc, Size, 1) ->
     BinSeg#k_bin_seg{size=Sz#k_int{val=Size + 8}, seg=Lit#k_literal{val=(Acc bsl 8) bor Val}};
 squeeze_segments(#k_bin_seg{seg=#k_literal{val=Val},next=Next}, Acc, Size, Count) ->
-    squeeze_segments(Next, (Acc bsl 8) bor Val, Size + 8, Count - 1).
+    squeeze_segments(Next, (Acc bsl 8) bor Val, Size + 8, Count - 1);
+squeeze_segments(#k_bin_end{}, Acc, Size, Count) ->
+    error({Acc,Size,Count}).
+
 
 flat_reverse([Head | Tail], Acc) -> flat_reverse(Tail, flat_reverse_1(Head, Acc));
 flat_reverse([], Acc) -> Acc.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 4f910d70df..cd3b4db923 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -1307,6 +1307,17 @@ zero_width(Config) when is_list(Config) ->
 	<<256:8>> -> ct:fail(should_not_match);
 	_ -> ok
     end,
+
+    %% Would crash in the segment squeezing functions in v3_kernel.
+    F = fun (<<42>>) -> star;
+            (<<V:0>>) -> V;
+            (_) -> no_match
+        end,
+    star = F(<<42>>),
+    0 = F(<<>>),
+    no_match = F(<<1>>),
+    no_match = F(whatever),
+
     ok.
 
 
-- 
2.16.4

openSUSE Build Service is sponsored by