From ee0ca14382e76d97285e64b3396fbb87f33e23da Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 18 Nov 2013 16:56:40 +0100 Subject: erts: Fix bugs in binary_to_term for invalid bitstrings <<131, 77, Len:32, Bits:8, Data/binary>> badarg if Bits > 8 Used to return internally inconsistent bitstring badarg if Len==0 and Bits > 0 Used to return invalid *huge* binary (size = (Uint)-1) badarg if Bits==0 and Len > 0 Used to return valid binary as if Bits was 8 --- erts/doc/src/erl_ext_dist.xml | 6 +++--- erts/emulator/beam/erl_binary.h | 2 +- erts/emulator/beam/external.c | 8 +++++--- erts/emulator/test/binary_SUITE.erl | 14 +++++++------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml index c6849f3326..64a201cc8f 100644 --- a/erts/doc/src/erl_ext_dist.xml +++ b/erts/doc/src/erl_ext_dist.xml @@ -1014,10 +1014,10 @@

- This term represents a bitstring whose length in bits is not a - multiple of 8 (created using the bit syntax in R12B and later). + This term represents a bitstring whose length in bits does + not have to be a multiple of 8. The Len field is an unsigned 4 byte integer (big endian). - The Bits field is the number of bits that are used + The Bits field is the number of bits (1-8) that are used in the last byte in the data field, counting from the most significant bit towards the least significant. diff --git a/erts/emulator/beam/erl_binary.h b/erts/emulator/beam/erl_binary.h index 506c4813fa..24b10cffef 100644 --- a/erts/emulator/beam/erl_binary.h +++ b/erts/emulator/beam/erl_binary.h @@ -225,7 +225,7 @@ erts_free_aligned_binary_bytes(byte* buf) ** These extra bytes where earlier (< R13B04) added by an alignment-bug ** in this code. Do we dare remove this in some major release (R14?) maybe? */ -#ifdef DEBUG +#if defined(DEBUG) || defined(VALGRIND) # define CHICKEN_PAD 0 #else # define CHICKEN_PAD (sizeof(void*) - 1) diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 1c88765381..cfdd38df73 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -3007,7 +3007,9 @@ dec_term_atom_common: n = get_int32(ep); bitsize = ep[4]; - ep += 5; + if (((bitsize==0) != (n==0)) || bitsize > 8) + goto error; + ep += 5; if (n <= ERL_ONHEAP_BIN_LIMIT) { ErlHeapBin* hb = (ErlHeapBin *) hp; @@ -3035,10 +3037,10 @@ dec_term_atom_common: hp += PROC_BIN_SIZE; } ep += n; - if (bitsize == 0) { + if (bitsize == 8 || n == 0) { *objp = bin; } else { - sb = (ErlSubBin *) hp; + sb = (ErlSubBin *)hp; sb->thing_word = HEADER_SUB_BIN; sb->orig = bin; sb->size = n - 1; diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 08ab094019..d2c4a8ff3c 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -631,7 +631,12 @@ safe_binary_to_term2(Config) when is_list(Config) -> bad_terms(suite) -> []; bad_terms(Config) when is_list(Config) -> - ?line test_terms(fun corrupter/1). + ?line test_terms(fun corrupter/1), + {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,0,11,22,33>>)), + {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,9,11,22,33>>)), + {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,0:32,1,11,22,33>>)), + ok. + corrupter(Term) when is_function(Term); is_function(hd(Term)); @@ -1221,14 +1226,9 @@ gc() -> gc1() -> ok. bit_sized_binary_sizes(Config) when is_list(Config) -> - ?line [bsbs_1(A) || A <- lists:seq(0, 7)], + ?line [bsbs_1(A) || A <- lists:seq(1, 8)], ok. -bsbs_1(0) -> - BinSize = 32+8, - io:format("A: ~p BinSize: ~p", [0,BinSize]), - Bin = binary_to_term(<<131,$M,5:32,0,0,0,0,0,0>>), - BinSize = bit_size(Bin); bsbs_1(A) -> BinSize = 32+A, io:format("A: ~p BinSize: ~p", [A,BinSize]), -- cgit v1.2.3 From f32368c4b34c86aa772a372cdb3c306a79127185 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 18 Nov 2013 16:58:43 +0100 Subject: erts: Fix bug in binary_to_term for binaries larger than 2^31 --- erts/emulator/beam/external.c | 4 ++-- erts/emulator/test/binary_SUITE.erl | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index cfdd38df73..22b0a02937 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -2970,7 +2970,7 @@ dec_term_atom_common: n = get_int32(ep); ep += 4; - if (n <= ERL_ONHEAP_BIN_LIMIT) { + if ((unsigned)n <= ERL_ONHEAP_BIN_LIMIT) { ErlHeapBin* hb = (ErlHeapBin *) hp; hb->thing_word = header_heap_bin(n); @@ -3010,7 +3010,7 @@ dec_term_atom_common: if (((bitsize==0) != (n==0)) || bitsize > 8) goto error; ep += 5; - if (n <= ERL_ONHEAP_BIN_LIMIT) { + if ((unsigned)n <= ERL_ONHEAP_BIN_LIMIT) { ErlHeapBin* hb = (ErlHeapBin *) hp; hb->thing_word = header_heap_bin(n); diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index d2c4a8ff3c..a340a805b5 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -635,6 +635,7 @@ bad_terms(Config) when is_list(Config) -> {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,0,11,22,33>>)), {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,9,11,22,33>>)), {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,0:32,1,11,22,33>>)), + {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,-1:32,1,11,22,33>>)), ok. -- cgit v1.2.3