File 2662-Fix-unsafe-binary-optimization.patch of Package erlang

From 04a5cf70838f393387735e17c9ca3cd126701000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Thu, 19 Mar 2026 09:43:23 +0100
Subject: [PATCH] Fix unsafe binary optimization

The optimization introduced in 7318e9cbea60f8 could sometimes rewrite
matching of a binary segment to matching of an integer segment.

Resolves #10878
---
 lib/compiler/src/beam_core_to_ssa.erl | 12 ++++++---
 lib/compiler/test/bs_match_SUITE.erl  | 35 +++++++++++++++++++++++++--
 2 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/lib/compiler/src/beam_core_to_ssa.erl b/lib/compiler/src/beam_core_to_ssa.erl
index 8d0bf840f9..fa9725a98f 100644
--- a/lib/compiler/src/beam_core_to_ssa.erl
+++ b/lib/compiler/src/beam_core_to_ssa.erl
@@ -1877,10 +1877,14 @@ group_keeping_order_fun(C1) ->
                         {{S,U,T1,_,Next}, {S,U,_T2,_,Next}}
                           when T1 =:= integer; T1 =:= binary ->
                             %% The patterns in clauses `C1` and `C`
-                            %% match the same number of bits, meaning
-                            %% that clause `C` clause will not be
-                            %% reached if clause `C1` succeeds.
-                            true;
+                            %% match the same number of bits. If the
+                            %% value for clause `C1` is a variable,
+                            %% clause `C1` will always be reached and
+                            %% clause `C` will never be reached.
+                            case arg_arg(clause_arg(C1)) of
+                                #cg_bin_seg{seg=#b_var{}} -> true;
+                                _ -> false
+                            end;
                         {_, _} ->
                             false
                     end
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index fba52fb1b4..e2b8398f02 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -58,7 +58,8 @@
          gh_6410/1,bs_match/1,
          binary_aliases/1,gh_6923/1,
          bs_test_tail/1,
-         otp_19019/1]).
+         otp_19019/1,
+         gh_10878/1]).
 
 -export([coverage_id/1,coverage_external_ignore/2]).
 
@@ -102,7 +103,8 @@ groups() ->
        gh_6410,bs_match,binary_aliases,
        gh_6923,
        bs_test_tail,
-       otp_19019]}].
+       otp_19019,
+       gh_10878]}].
 
 init_per_suite(Config) ->
     test_lib:recompile(?MODULE),
@@ -3360,6 +3362,35 @@ do_otp_19019(A) ->
         ok
     end.
 
+gh_10878(_Config) ->
+    {~"M", ~"Z"} = gh_10878_decode(id(~"MZ")),
+    ~"X" = gh_10878_decode(id(~"X=")),
+
+    0 = count_newlines(~""),
+    1 = count_newlines(~"\n"),
+    1 = count_newlines(~"abc\n"),
+    2 = count_newlines(~"abc\n\n"),
+    2 = count_newlines(~"abc\nxyz\n"),
+
+    ok.
+
+gh_10878_decode(Encoded) ->
+    case Encoded of
+        <<A:1/binary, "=">> -> A;
+        <<A:1/binary, B:1/binary>> -> {A,B}
+    end.
+
+count_newlines(Bin) ->
+    count_newlines(id(Bin), 0).
+
+count_newlines(<<$\n,B/binary>>, Count) ->
+    count_newlines(B, Count + 1);
+count_newlines(<<_:1/unit:8,B/binary>>, Count) ->
+    %% The pattern in this clause is supposed to be combined with the
+    %% pattern in the previous clause.
+    count_newlines(B, Count);
+count_newlines(<<>>, Count) ->
+    Count.
 
 %%% Utilities.
 
-- 
2.51.0

openSUSE Build Service is sponsored by