File 8121-Eliminate-an-unsafe-optimization-of-list-matching.patch of Package erlang
From f441ac970f7d6e930822c61ebdab3e40c0d38485 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 26 Feb 2024 07:33:13 +0100
Subject: [PATCH] Eliminate an unsafe optimization of list matching
In rare circumstances, the compiler could do an unsafe rewrite of
list matching operations. For example:
[PrevRow | _] = Rows,
[_ | PrevRowT] = PrevRow,
. . .
Provided that the type analysis pass had figured out that `Rows` is
always a list of at least two elements, the compiler would essentially
rewrite the code to:
[PrevRow | PrevRowT] = Rows,
. . .
Fixes #8187
---
lib/compiler/src/beam_z.erl | 4 ++--
lib/compiler/test/bif_SUITE.erl | 17 +++++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/lib/compiler/src/beam_z.erl b/lib/compiler/src/beam_z.erl
index 9f467676e5..71160d47fa 100644
--- a/lib/compiler/src/beam_z.erl
+++ b/lib/compiler/src/beam_z.erl
@@ -85,9 +85,9 @@ undo_renames([{bif,raise,_,_,_}=I|Is0]) ->
(_) -> true
end, Is0),
[I|undo_renames(Is)];
-undo_renames([{get_hd,Src,Hd},{get_tl,Src,Tl}|Is]) ->
+undo_renames([{get_hd,Src,Hd},{get_tl,Src,Tl}|Is]) when Src =/= Hd ->
get_list(Src, Hd, Tl, Is);
-undo_renames([{get_tl,Src,Tl},{get_hd,Src,Hd}|Is]) ->
+undo_renames([{get_tl,Src,Tl},{get_hd,Src,Hd}|Is]) when Src =/= Tl ->
get_list(Src, Hd, Tl, Is);
undo_renames([{bs_put,_,{bs_put_binary,1,_},
[{atom,all},{literal,<<>>}]}|Is]) ->
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index a23d728715..4137f43f91 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -23,6 +23,7 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
+ unsafe_get_list/1,
beam_validator/1,trunc_and_friends/1,cover_safe_and_pure_bifs/1,
min_max/1]).
@@ -37,6 +38,7 @@ all() ->
groups() ->
[{p,test_lib:parallel(),
[beam_validator,
+ unsafe_get_list,
trunc_and_friends,
cover_safe_and_pure_bifs,
min_max
@@ -57,6 +59,21 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+unsafe_get_list(_Config) ->
+ [[1], [1], [1]] = create_rows(id(3)),
+ ok.
+
+create_rows(Num) -> create_rows(Num, [[1]]).
+
+create_rows(1, Rows) ->
+ Rows;
+create_rows(Num, [PrevRow | _] = Rows) ->
+ [_PrevRowH | PrevRowT] = PrevRow,
+ [] = first(PrevRowT, PrevRow),
+ create_rows(Num - 1, [[1] | Rows]).
+
+first(Fst, _Snd) -> Fst.
+
%% Cover code in beam_validator.
beam_validator(Config) ->
--
2.35.3