From 1752215fb66b6aa7129c7c2dec0f65bd28d26107 Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Wed, 15 Feb 2023 12:51:45 +0100 Subject: [PATCH] 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 --- lib/compiler/src/beam_ssa_private_append.erl | 7 +++++++ .../beam_ssa_check_SUITE_data/private_append.erl | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/compiler/src/beam_ssa_private_append.erl b/lib/compiler/src/beam_ssa_private_append.erl index 0ace5cca622a..19c38854f707 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 d0ac4fb5c848..ddc091384dea 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 ->