Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
0561-Eliminate-infinite-loop-in-the-Erlang-comp...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0561-Eliminate-infinite-loop-in-the-Erlang-compiler.patch of Package erlang
From 7ed952628caa2470c9cce8678aea3b7d2e0f26dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Wed, 16 Nov 2022 13:09:50 +0100 Subject: [PATCH] Eliminate infinite loop in the Erlang compiler Closes #6474 --- lib/compiler/src/beam_ssa_bc_size.erl | 33 ++++++++++++++++--- .../compilation_SUITE_data/infinite_loop.erl | 10 ++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/compiler/src/beam_ssa_bc_size.erl b/lib/compiler/src/beam_ssa_bc_size.erl index a93fe8f2f3..6505bf88b7 100644 --- a/lib/compiler/src/beam_ssa_bc_size.erl +++ b/lib/compiler/src/beam_ssa_bc_size.erl @@ -71,7 +71,8 @@ opt_function(Id, StMap) -> opt_blks([{L,#b_blk{is=Is}=Blk}|Blks], ParamInfo, StMap, AnyChange, Count0, Acc0) -> case Is of [#b_set{op=bs_init_writable,dst=Dst}] -> - Bs = #{st_map => StMap, Dst => {writable,#b_literal{val=0}}}, + Bs = #{st_map => StMap, Dst => {writable,#b_literal{val=0}}, + seen => sets:new([{version,2}])}, try opt_writable(Bs, L, Blk, Blks, ParamInfo, Count0, Acc0) of {Acc,Count} -> opt_blks(Blks, ParamInfo, StMap, changed, Count, Acc) @@ -153,10 +154,32 @@ call_size_func(#b_set{anno=Anno,op=call,args=[Name|Args],dst=Dst}, Bs) -> %% and there is no need to analyze it. Bs#{Dst => any}; true -> - NewBs = NewBs0#{Name => self, st_map => StMap}, - Map0 = #{0 => NewBs}, - Result = calc_size(Linear, Map0), - Bs#{Dst => Result} + Seen0 = map_get(seen, Bs), + case sets:is_element(Name, Seen0) of + true -> + %% This can happen if there is a call such as: + %% + %% foo(<< 0 || false >>) + %% + %% Essentially, this is reduced to: + %% + %% foo(<<>>) + %% + %% This sub pass will then try to analyze + %% the code in foo/1 and everything it + %% calls. To prevent an infinite loop in + %% case there is mutual recursion between + %% some of the functions called by foo/1, + %% give up if function that has already + %% been analyzed is called again. + throw(not_possible); + false -> + Seen = sets:add_element(Name, Seen0), + NewBs = NewBs0#{Name => self, st_map => StMap, seen => Seen}, + Map0 = #{0 => NewBs}, + Result = calc_size(Linear, Map0), + Bs#{Dst => Result} + end end; #{} -> case Name of diff --git a/lib/compiler/test/compilation_SUITE_data/infinite_loop.erl b/lib/compiler/test/compilation_SUITE_data/infinite_loop.erl index 6d9135bb01..8fb9125c77 100644 --- a/lib/compiler/test/compilation_SUITE_data/infinite_loop.erl +++ b/lib/compiler/test/compilation_SUITE_data/infinite_loop.erl @@ -20,3 +20,13 @@ foobar() -> barfoo() -> barfoo(). + +%% GH-6474. The compiler would go into an infinite loop. + +bc_infinite_loop() -> + mutually_recursive(<<0 || false>>). + +mutually_recursive(X) -> + %% This LC will be implemented as mutually recursive functions. + %% Analyzing them would cause an infinite loop. + [0 || _ <- [], <<_>> <= X]. -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor