summaryrefslogtreecommitdiff
path: root/lib/compiler
diff options
context:
space:
mode:
authorFrej Drejhammar <frej.drejhammar@gmail.com>2023-02-15 12:51:45 +0100
committerFrej Drejhammar <frej.drejhammar@gmail.com>2023-02-15 13:43:03 +0100
commit1752215fb66b6aa7129c7c2dec0f65bd28d26107 (patch)
tree3b7397a43339cef0c08feb598fee796c53cd5698 /lib/compiler
parent2b397d7e5580480dc32fa9751db95f4b89ff029e (diff)
downloaderlang-1752215fb66b6aa7129c7c2dec0f65bd28d26107.tar.gz
compiler: Avoid crash in private-append optimization
Avoid a crash in the private-append optimization due to attempting to rewrite a literal which isn't a bitstring. As value tracking is done without type information, it can happen that when following def chains, we encounter literals which are not bitstrings. We should never schedule a literal which isn't a bitstring for rewriting when the complete literal is what we are tracking, i.e. when the element is `self`. Closes #6847
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/beam_ssa_private_append.erl7
-rw-r--r--lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl16
2 files changed, 23 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_ssa_private_append.erl b/lib/compiler/src/beam_ssa_private_append.erl
index 0ace5cca62..19c38854f7 100644
--- a/lib/compiler/src/beam_ssa_private_append.erl
+++ b/lib/compiler/src/beam_ssa_private_append.erl
@@ -168,6 +168,13 @@ get_results(SSA, Element, Fun, DefSt) ->
get_results([{_,#b_blk{last=#b_ret{arg=#b_var{}=V}}}|Rest],
Acc, Element, Fun, DefSt) ->
get_results(Rest, [{V,Element}|Acc], Element, Fun, DefSt);
+get_results([{_,#b_blk{last=#b_ret{arg=#b_literal{val=Lit}}}}|Rest],
+ Acc, Element=self, Fun, DefSt) when not is_bitstring(Lit) ->
+ %% As value tracking is done without type information, we can
+ %% follow def chains which don't terminate in a bitstring. This is
+ %% harmless, but we should ignore them and not, later on, try to
+ %% patch them to a bs_writable_binary.
+ get_results(Rest, Acc, Element, Fun, DefSt);
get_results([{Lbl,#b_blk{last=#b_ret{arg=#b_literal{}}}}|Rest],
Acc, Element, Fun, DefSt0) ->
DefSt = add_literal(Fun, {ret,Lbl,Element}, DefSt0),
diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl
index d0ac4fb5c8..ddc091384d 100644
--- a/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl
+++ b/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl
@@ -57,6 +57,8 @@
transformable30/1,
transformable31a/1,
transformable31b/1,
+ transformable32/0,
+ transformable32/1,
not_transformable1/2,
not_transformable2/1,
@@ -748,6 +750,20 @@ transformable31([], Acc, a) when is_binary(Acc) ->
transformable31([], Acc, b) when is_tuple(Acc) ->
<<>>.
+%% Check that we don't crash (Github issue #6847) while attempting to
+%% patch the empty list, but also that the literal <<>> becomes a
+%% bs_init_writable.
+transformable32() ->
+ <<(transformable32(ok))/binary>>.
+
+transformable32(#{}) ->
+%ssa% (_) when post_ssa_opt ->
+%ssa% A = bs_init_writable(_),
+%ssa% ret(A).
+ [];
+transformable32(_) ->
+ <<>>.
+
% Should not be transformed as we can't know the alias status of Acc
not_transformable1([H|T], Acc) ->
%ssa% (_, Arg1) when post_ssa_opt ->