summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2020-02-23 17:43:56 +0100
committerBjörn Gustavsson <bjorn@erlang.org>2020-03-04 05:58:42 +0100
commit9ed20ba3b97b2c621494da0368d3570a9d0e5ffe (patch)
tree41b0ceb628abfbc5747851e19684465fbcb3fb0b
parent4de2b67cadc5f1433076f900579cc61b44c35909 (diff)
downloaderlang-9ed20ba3b97b2c621494da0368d3570a9d0e5ffe.tar.gz
v3_core: Fix compiler crash when compiling failing binary construction
The compiler would crash when compiling code such as the following because the binding of `Var` was not done because the binary construction would always fail: case <<(Var = 1),[]/utf32>> of _ when Var -> true end. (Also see 0f53ac61d9ce.)
-rw-r--r--lib/compiler/src/v3_core.erl23
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl6
2 files changed, 24 insertions, 5 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 6a93f30f81..e38cfcbaa7 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1144,11 +1144,24 @@ make_combined(Line, Val, Size) ->
{integer,Line,Size},
[integer,{unit,1},unsigned,big]}.
-expr_bin_1(Es, St) ->
- foldr(fun (E, {Ces,Esp,St0}) ->
- {Ce,Ep,St1} = bitstr(E, St0),
- {[Ce|Ces],Ep ++ Esp,St1}
- end, {[],[],St}, Es).
+expr_bin_1(Es, St0) ->
+ Res = foldr(fun (E, {Ces,Eps0,S0}) ->
+ try bitstr(E, S0) of
+ {Ce,Eps,S1} when is_list(Ces) ->
+ {[Ce|Ces],Eps ++ Eps0,S1};
+ {_Ce,Eps,S1} ->
+ {Ces,Eps ++ Eps0,S1}
+ catch
+ {bad_binary,Eps,S1} ->
+ {bad_binary,Eps ++ Eps0,S1}
+ end
+ end, {[],[],St0}, Es),
+ case Res of
+ {bad_binary,Eps,St} ->
+ throw({bad_binary,Eps,St});
+ {_,_,_}=Res ->
+ Res
+ end.
bitstr({bin_element,_,E0,Size0,[Type,{unit,Unit}|Flags]}, St0) ->
{E1,Eps0,St1} = safe(E0, St0),
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index f428c3a27f..9df5f4aa0c 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -343,6 +343,7 @@ fail(Config) when is_list(Config) ->
end),
{'EXIT',{badarg,_}} = (catch <<13:(put(?FUNCTION_NAME, 17))>>),
17 = erase(?FUNCTION_NAME),
+ {'EXIT',{badarg,_}} = (catch fail_1()),
%% Size exceeds length of binary. 'native' is redundant for
%% binaries, but when it was present sys_core_fold would not
@@ -352,6 +353,11 @@ fail(Config) when is_list(Config) ->
ok.
+fail_1() ->
+ case <<(V0 = 1),[]/utf32>> of
+ _ when V0 -> true
+ end.
+
float_bin(Config) when is_list(Config) ->
%% Some more coverage.
{<<1,2,3>>,7.0} = float_bin_1(4),