Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions erts/emulator/beam/external.c
Original file line number Diff line number Diff line change
Expand Up @@ -2026,11 +2026,25 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Eterm bin, B2TContext *ctx)
break;

case B2TDecodeInit:
if (is_non_value(ctx->trap_bin) && ctx->b2ts.extsize > ctx->reds) {
/* dec_term will maybe trap, allocate space for magic bin
before result term to make it easy to trim with HRelease.
*/
ctx = b2t_export_context(p, ctx);
if (is_non_value(ctx->trap_bin)) {
if (ctx->b2ts.extsize > ctx->reds) {
/* dec_term will maybe trap, allocate space for magic bin
* before result term to make it easy to trim with HRelease.
*/
ctx = b2t_export_context(p, ctx);
}
else {
/*
* We will probably not trap. To ensure we don't,
* artificially increase our available reductions.
* This is a workaround for GH-11404. Calling HAlloc()
* in b2t_export_context() after factory has been created
* causes problems.
*/
const SWord consumed = initial_reds - ctx->reds;
ctx->reds = (INT_MAX / B2T_MEMCPY_FACTOR);
initial_reds = ctx->reds + consumed;
}
}
ctx->u.dc.ep = ctx->b2ts.extp;
ctx->u.dc.res = (Eterm) (UWord) NULL;
Expand Down Expand Up @@ -2114,6 +2128,7 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Eterm bin, B2TContext *ctx)
}while (ctx->reds > 0 || ctx->state >= B2TDone);

if (is_non_value(ctx->trap_bin)) {
ASSERT(ctx->state < B2TDecode);
ctx = b2t_export_context(p, ctx);
ASSERT(is_value(ctx->trap_bin));
}
Expand Down
19 changes: 19 additions & 0 deletions erts/emulator/test/binary_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
bad_binary_to_term_2/1,safe_binary_to_term2/1,
bad_binary_to_term/1, bad_terms/1, more_bad_terms/1,
big_binary_to_term/1,
binary_to_term_trap_crash/1,
otp_5484/1,otp_5933/1,
ordering/1,unaligned_order/1,gc_test/1,
bit_sized_binary_sizes/1,
Expand Down Expand Up @@ -99,6 +100,7 @@ all() ->
bad_binary_to_term_2, safe_binary_to_term2,
bad_binary_to_term, bad_terms, t_hash, bad_size,
big_binary_to_term,
binary_to_term_trap_crash,
sub_bin_copy, bad_term_to_binary, t2b_system_limit,
term_to_iovec, more_bad_terms,
unsorted_map_in_map,
Expand Down Expand Up @@ -1951,6 +1953,23 @@ trapping_loop2(Bif,Args,N) ->
apply(erlang,Bif,Args),
trapping_loop2(Bif, Args, N-1).

%% GH-11404: Bug caused SEGV or failed ASSERT.
binary_to_term_trap_crash(Config) ->
Term = {0,"1234567890123456",0,0,0,0,0,0,
[1 bsl 47], [], {127,0,0,1},
0,[],[],[],[],[],[],[],[],[],[],0,[],"123456789",[],[],0,0,
0,[],0,[],[],[],[],[],1,[],[],[],[],[],[],0,0,"123",[],0,[],
1,[],[],[],0,0,{0,0},0,[],0,0,0,[],[],0,[],0,0,[]},
Bin = term_to_binary(Term),
CONTEXT_REDS = erlang:system_info(context_reductions),
[begin
erlang:yield(),
erlang:bump_reductions(I),
binary_to_term(Bin)
end
|| I <- lists:seq(1,CONTEXT_REDS)],
ok.

large(Config) when is_list(Config) ->
List = lists:flatten(lists:map(fun (_) ->
[0,1,2,3,4,5,6,7,8]
Expand Down
Loading