File 0343-cerl-Fix-crash-on-undefined-segment-size.patch of Package erlang
From ec44a576c8e00810bfb4129fab0b7c5fb9feb065 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Mon, 5 Jun 2023 13:35:34 +0200
Subject: [PATCH] cerl: Fix crash on 'undefined' segment size
Fixes #7325
---
lib/compiler/src/cerl.erl | 29 ++++++++++---------
.../test/small_SUITE_data/results/bs_segments | 2 ++
.../test/small_SUITE_data/src/bs_segments.erl | 6 +++-
3 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl
index f824703a8a..7e4e5af98c 100644
--- a/lib/compiler/src/cerl.erl
+++ b/lib/compiler/src/cerl.erl
@@ -2385,21 +2385,22 @@ bitstr_size(Node) ->
-spec bitstr_bitsize(c_bitstr()) -> 'all' | 'any' | 'utf' | non_neg_integer().
bitstr_bitsize(Node) ->
- Size = Node#c_bitstr.size,
+ #c_bitstr{size=Size,type=Type,unit=Unit} = Node,
case is_literal(Size) of
- true ->
- case concrete(Size) of
- all ->
- all;
- undefined ->
- %% just an assertion below
- "utf" ++ _ = atom_to_list(concrete(Node#c_bitstr.type)),
- utf;
- S when is_integer(S) ->
- S * concrete(Node#c_bitstr.unit)
- end;
- false ->
- any
+ true ->
+ case {concrete(Size), concrete(Type)} of
+ {all, binary} ->
+ all;
+ {undefined, T} when T =:= utf8; T =:= utf16; T =:= utf32 ->
+ utf;
+ {S, _} when is_integer(S), S >= 0 ->
+ S * concrete(Unit);
+ {_, _} ->
+ %% Bogus literal size, fails in runtime.
+ any
+ end;
+ false ->
+ any
end.
diff --git a/lib/dialyzer/test/small_SUITE_data/results/bs_segments b/lib/dialyzer/test/small_SUITE_data/results/bs_segments
index 0c3c9a0717..83436d91b6 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/bs_segments
+++ b/lib/dialyzer/test/small_SUITE_data/results/bs_segments
@@ -1,3 +1,5 @@
+bs_segments.erl:10:1: Function f/0 has no local return
+bs_segments.erl:11:10: Binary construction will fail since the size field 'undefined' in segment 0 has type 'undefined'
bs_segments.erl:6:1: Function t/1 has no local return
bs_segments.erl:6:1: The pattern <<_>> can never match the type any()
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl b/lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl
index b1b8a2e866..95d9d1263b 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl
@@ -1,7 +1,11 @@
-module(bs_segments).
--export([t/1]).
+-export([t/1, f/0]).
%% GH-7138: bogus segment sizes crashed the analysis.
t(<<_:undefined>>) ->
ok.
+
+%% GH-7325: variant of the above.
+f() ->
+ <<0:(undefined)>>.
--
2.35.3