summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2021-09-01 08:13:05 +0200
committerBjörn Gustavsson <bjorn@erlang.org>2021-09-01 12:51:26 +0200
commit81805d631b6e196f2a71abc58b0c469186bec58e (patch)
treedad796d8b814311c861e1a9747f46ca4639b994f
parent6d5a5f31c36bbdaad21585d25974177bd1b75e66 (diff)
downloaderlang-81805d631b6e196f2a71abc58b0c469186bec58e.tar.gz
Make binary_to_term/1 more resilent against bad binaries
binary_to_term/1 could crash the runtime system when given a corrupted binary containing the external representation of maps. This commit fixes two issues: * There could multiple frees of the same memory area for a corrupted term containing both large maps and small maps. * Heap space would be allocated according to the number of elements the map was supposed to contain, even if the binary was clearly too short to contain that many elements.
-rw-r--r--erts/emulator/beam/external.c5
-rw-r--r--erts/emulator/test/binary_SUITE.erl16
2 files changed, 20 insertions, 1 deletions
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index c8d0bf7f40..feb7cd7a49 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -4248,7 +4248,6 @@ dec_term_atom_common:
(void) PSTACK_POP(hamt_array);
} while (!PSTACK_IS_EMPTY(hamt_array));
- PSTACK_DESTROY(hamt_array);
}
/* Iterate through all the (flat)maps and check for validity and sort keys
@@ -4260,6 +4259,9 @@ dec_term_atom_common:
if (!erts_validate_and_sort_flatmap((flatmap_t*)next))
goto error;
}
+
+ /* Now that no more errors can occur, the stacks can be destroyed safely. */
+ PSTACK_DESTROY(hamt_array);
WSTACK_DESTROY(flat_maps);
ASSERT((Eterm*)*dbg_resultp != NULL);
@@ -4846,6 +4848,7 @@ init_done:
if (n <= MAP_SMALL_MAP_LIMIT) {
heap_size += 3 + n + 1 + n;
} else {
+ CHKSIZE(2*n); /* Conservative size check */
heap_size += HASHMAP_ESTIMATED_HEAP_SIZE(n);
}
break;
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 06db9d3ff3..c4ebe2ab3b 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -1408,6 +1408,22 @@ test_terms(Test_Func) ->
Test_Func(FF = fun binary_SUITE:all/0),
Test_Func(lists:duplicate(32, FF)),
+ %% Maps.
+ SmallMap = #{a => 1, b => 2, c => 3},
+ LargeMap1 = maps:from_list([{list_to_atom(integer_to_list(36#cafe+N*N*N, 36)),N} ||
+ N <- lists:seq(1, 33)]),
+ LargeMap2 = maps:from_list([{list_to_atom(integer_to_list(36#dead+N, 36)),N} ||
+ N <- lists:seq(1, 50)]),
+ MapWithMap = LargeMap1#{SmallMap => a, LargeMap1 => LargeMap2, LargeMap2 => LargeMap1,
+ [LargeMap1,LargeMap2] => LargeMap1,
+ <<"abc">> => SmallMap, <<"qrs">> => LargeMap1,
+ <<"xyz">> => LargeMap2 },
+ Test_Func(#{}),
+ Test_Func(SmallMap),
+ Test_Func(LargeMap1),
+ Test_Func(LargeMap2),
+ Test_Func(MapWithMap),
+
ok.
test_floats(Test_Func) ->