File 0803-Fix-crash-when-compiling-is_list-1-call.patch of Package erlang

From f9a3fa9366209ba05d902f387fb47ace7273b9a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 31 Jul 2023 06:06:56 +0200
Subject: [PATCH] Fix crash when compiling is_list/1 call

Fixes #7504
---
 lib/compiler/src/beam_ssa_codegen.erl | 17 +++++++++++++++--
 lib/compiler/test/beam_type_SUITE.erl | 15 +++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
index 9f6169829b..6f6de99962 100644
--- a/lib/compiler/src/beam_ssa_codegen.erl
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -1270,9 +1270,22 @@ cg_block([#cg_set{op=is_tagged_tuple,anno=Anno,dst=Bool,args=Args0}], {Bool,Fail
             [Src,{integer,Arity},Tag] = beam_args(Args0, St),
             {[{test,is_tagged_tuple,ensure_label(Fail, St),[Src,Arity,Tag]}],St}
     end;
-cg_block([#cg_set{op=is_nonempty_list,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
+cg_block([#cg_set{op=is_nonempty_list,dst=Bool0,args=Args0}=Set], {Bool0,Fail0}, St) ->
+    Fail = ensure_label(Fail0, St),
     Args = beam_args(Args0, St),
-    {[{test,is_nonempty_list,ensure_label(Fail, St),Args}],St};
+    case beam_args([Bool0|Args0], St) of
+        [{z,0}|Args] ->
+            {[{test,is_nonempty_list,Fail,Args}],St};
+        [Dst|Args] ->
+            %% This instruction was a call to is_list/1, which was
+            %% rewritten to an is_nonempty_list test by
+            %% beam_ssa_type. BEAM has no is_nonempty_list instruction
+            %% that will return a boolean, so we must revert it to an
+            %% is_list/1 call.
+            #cg_set{anno=#{was_bif_is_list := true}} = Set, %Assertion.
+            {[{bif,is_list,Fail0,Args,Dst},
+              {test,is_eq_exact,Fail,[Dst,{atom,true}]}],St}
+    end;
 cg_block([#cg_set{op=has_map_field,dst=Dst0,args=Args0}], {Dst0,Fail0}, St) ->
     Fail = ensure_label(Fail0, St),
     case beam_args([Dst0|Args0], St) of
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 94f1b8b0a6..f65dce28c3 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -1094,6 +1094,11 @@ cs_2({bar,baz}) ->
 is_list_opt(_Config) ->
     true = is_list_opt_1(id(<<"application/a2l">>)),
     false = is_list_opt_1(id(<<"">>)),
+
+    ok = is_list_opt_3(id([])),
+    true = is_list_opt_3(id([a])),
+    {'EXIT',{badarg,_}} = catch is_list_opt_3(id(no_list)),
+
     ok.
 
 is_list_opt_1(Type) ->
@@ -1105,5 +1110,14 @@ is_list_opt_1(Type) ->
 is_list_opt_2(<<"application/a2l">>) -> [<<"a2l">>];
 is_list_opt_2(_Type) -> nil.
 
+is_list_opt_3([]) ->
+    ok;
+is_list_opt_3(A) ->
+    %% The call to is_list/1 would be optimized to an is_nonempty_list
+    %% instruction, which only exists as a guard test that cannot
+    %% produce boolean value.
+    _ = (Bool = is_list(A)) orelse binary_to_integer(<<"">>),
+    Bool.
+
 id(I) ->
     I.
-- 
2.35.3

openSUSE Build Service is sponsored by