summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrik Nyblom <pan@erlang.org>2010-05-06 16:30:26 +0200
committerBjörn Gustavsson <bjorn@erlang.org>2010-05-17 15:51:50 +0200
commitababeff98d7def30898786629cc5a16ea3949a24 (patch)
tree133c19b763cd5fa79684b3db5f4f6710474e72b7
parentf197068153bdc0aa749267ea30e77bf0173172f4 (diff)
downloaderlang-ababeff98d7def30898786629cc5a16ea3949a24.tar.gz
Correct Boyer More and trapping for longest_common_suffix
Add testcases and clean up to get better code coverage.
-rw-r--r--erts/emulator/beam/erl_bif_binary.c76
-rw-r--r--erts/emulator/test/guard_SUITE.erl9
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl317
3 files changed, 366 insertions, 36 deletions
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index ea8ea2e53d..cba17ee6eb 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -260,7 +260,11 @@ static void dump_ac_node(ACNode *node, int indent, int ch);
/*
* Callback for the magic binary
*/
-static void cleanup_my_data(Binary *bp)
+static void cleanup_my_data_ac(Binary *bp)
+{
+ return;
+}
+static void cleanup_my_data_bm(Binary *bp)
{
return;
}
@@ -277,7 +281,7 @@ static ACTrie *create_acdata(MyAllocator *my, Uint len,
Uint datasize = AC_SIZE(len);
ACTrie *act;
ACNode *acn;
- Binary *mb = erts_create_magic_binary(datasize,cleanup_my_data);
+ Binary *mb = erts_create_magic_binary(datasize,cleanup_my_data_ac);
byte *data = ERTS_MAGIC_BIN_DATA(mb);
init_my_allocator(my, datasize, data);
@@ -306,7 +310,7 @@ static BMData *create_bmdata(MyAllocator *my, byte *x, Uint len,
{
Uint datasize = BM_SIZE(len);
BMData *bmd;
- Binary *mb = erts_create_magic_binary(datasize,cleanup_my_data);
+ Binary *mb = erts_create_magic_binary(datasize,cleanup_my_data_bm);
byte *data = ERTS_MAGIC_BIN_DATA(mb);
init_my_allocator(my, datasize, data);
bmd = my_alloc(my, sizeof(BMData));
@@ -708,7 +712,7 @@ static void compute_suffixes(byte *x, Sint m, Sint *suffixes)
g = m - 1;
for (i = m - 2; i >= 0; --i) {
- if (i > g && suffixes[i + m - f] < i - g) {
+ if (i > g && suffixes[i + m - 1 - f] < i - g) {
suffixes[i] = suffixes[i + m - 1 - f];
} else {
if (i < g) {
@@ -731,7 +735,7 @@ static void compute_goodshifts(BMData *bmd)
Sint m = bmd->len;
byte *x = bmd->x;
Sint i, j;
- Sint *suffixes = erts_alloc(ERTS_ALC_T_TMP, m * sizeof(Uint));
+ Sint *suffixes = erts_alloc(ERTS_ALC_T_TMP, m * sizeof(Sint));
compute_suffixes(x, m, suffixes);
@@ -1329,13 +1333,15 @@ static int parse_match_opts_list(Eterm l, Eterm bin, Uint *posp, Uint *endp)
}
if (len < 0) {
Sint lentmp = -len;
- if (-lentmp != len) {
+ /* overflow */
+ if (lentmp == len || lentmp < 0 || -lentmp != len) {
goto badarg;
}
len = lentmp;
pos -= len;
}
- if (((pos + len) - len) != pos) {
+ /* overflow */
+ if ((pos + len) < pos || (len > 0 && (pos + len) == pos)) {
goto badarg;
}
*endp = len + pos;
@@ -1367,10 +1373,9 @@ static BIF_RETTYPE binary_match_trap(BIF_ALIST_3)
BIF_TRAP3(&binary_match_trap_export, BIF_P, BIF_ARG_1, result,
BIF_ARG_3);
default:
- goto badarg;
+ /* Cannot badarg in the trap */
+ erl_exit(1, "Internal error in binary_match_trap.");
}
- badarg:
- BIF_ERROR(BIF_P,BADARG);
}
static BIF_RETTYPE binary_matches_trap(BIF_ALIST_3)
@@ -1387,10 +1392,9 @@ static BIF_RETTYPE binary_matches_trap(BIF_ALIST_3)
BIF_TRAP3(&binary_matches_trap_export, BIF_P, BIF_ARG_1, result,
BIF_ARG_3);
default:
- goto badarg;
+ /* Cannot badarg in the trap */
+ erl_exit(1, "Internal error in binary_matches_trap.");
}
- badarg:
- BIF_ERROR(BIF_P,BADARG);
}
@@ -1425,7 +1429,12 @@ BIF_RETTYPE binary_match_3(BIF_ALIST_3)
}
type = tp[1];
bin = ((ProcBin *) binary_val(tp[2]))->val;
- if (ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data) {
+ if (type == am_bm &&
+ ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_bm) {
+ goto badarg;
+ }
+ if (type == am_ac &&
+ ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_ac) {
goto badarg;
}
bin_term = tp[2];
@@ -1482,7 +1491,12 @@ BIF_RETTYPE binary_matches_3(BIF_ALIST_3)
}
type = tp[1];
bin = ((ProcBin *) binary_val(tp[2]))->val;
- if (ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data) {
+ if (type == am_bm &&
+ ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_bm) {
+ goto badarg;
+ }
+ if (type == am_ac &&
+ ERTS_MAGIC_BIN_DESTRUCTOR(bin) != cleanup_my_data_ac) {
goto badarg;
}
bin_term = tp[2];
@@ -1547,7 +1561,8 @@ BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen)
}
if (len < 0) {
Sint lentmp = -len;
- if (-lentmp != len) {
+ /* overflow */
+ if (lentmp == len || lentmp < 0 || -lentmp != len) {
goto badarg;
}
len = lentmp;
@@ -1556,7 +1571,8 @@ BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen)
}
pos -= len;
}
- if (((pos + len) - len) != pos) {
+ /* overflow */
+ if ((pos + len) < pos || (len > 0 && (pos + len) == pos)){
goto badarg;
}
if ((orig_size = binary_size(binary)) < pos ||
@@ -1634,7 +1650,8 @@ BIF_RETTYPE erts_gc_binary_part(Process *p, Eterm *reg, Eterm live, int range_is
}
if (len < 0) {
Sint lentmp = -len;
- if (-lentmp != len) {
+ /* overflow */
+ if (lentmp == len || lentmp < 0 || -lentmp != len) {
goto badarg;
}
len = lentmp;
@@ -1643,7 +1660,8 @@ BIF_RETTYPE erts_gc_binary_part(Process *p, Eterm *reg, Eterm live, int range_is
}
pos -= len;
}
- if (((pos + len) - len) != pos) {
+ /* overflow */
+ if ((pos + len) < pos || (len > 0 && (pos + len) == pos)) {
goto badarg;
}
if ((orig_size = binary_size(binary)) < pos ||
@@ -1926,6 +1944,7 @@ static BIF_RETTYPE do_longest_common(Process *p, Eterm list, int direction)
unsigned char *tmp = cd[i].buff;
cd[i].buff = erts_alloc(ERTS_ALC_T_BINARY_BUFFER, cd[i].bufflen);
memcpy(cd[i].buff,tmp,cd[i].bufflen);
+ cd[i].type = CL_TYPE_HEAP;
}
}
hp = HAlloc(p, PROC_BIN_SIZE);
@@ -1975,7 +1994,7 @@ static BIF_RETTYPE do_longest_common_trap(Process *p, Eterm bin_term, Eterm curr
ASSERT(res == CL_RESTART);
/* Copy all heap binaries that are not already copied (aligned) */
BUMP_ALL_REDS(p);
- BIF_TRAP3(&binary_longest_prefix_trap_export, p, bin_term, epos, orig_list);
+ BIF_TRAP3(trapper, p, bin_term, epos, orig_list);
}
}
@@ -2104,16 +2123,15 @@ BIF_RETTYPE binary_at_2(BIF_ALIST_2)
static int do_bin_to_list(Process *p, byte *bytes, Uint bit_offs,
Uint start, Sint *lenp, Eterm *termp)
{
- Uint reds = get_reds(p, BIN_TO_LIST_LOOP_FACTOR);
+ Uint reds = get_reds(p, BIN_TO_LIST_LOOP_FACTOR); /* reds can never be 0 */
Uint len = *lenp;
Uint loops;
Eterm *hp;
Eterm term = *termp;
Uint n;
- if (reds == 0) {
- return BIN_TO_LIST_TRAP;
- }
+ ASSERT(reds > 0);
+
loops = MIN(reds,len);
BUMP_REDS(p, loops / BIN_TO_LIST_LOOP_FACTOR);
@@ -2170,8 +2188,8 @@ static BIF_RETTYPE binary_bin_to_list_trap(BIF_ALIST_3)
len = (Sint) ptr[2];
ERTS_GET_BINARY_BYTES(BIF_ARG_1,bytes,bit_offs,bit_size);
- if(do_bin_to_list(BIF_P, bytes, bit_offs, start, &len, &res) ==
- BIN_TO_LIST_OK) {
+ if (do_bin_to_list(BIF_P, bytes, bit_offs, start, &len, &res) ==
+ BIN_TO_LIST_OK) {
BIF_RET(res);
}
return do_trap_bin_to_list(BIF_P,BIF_ARG_1,start,len,res);
@@ -2201,7 +2219,8 @@ static BIF_RETTYPE binary_bin_to_list_common(Process *p,
}
if (len < 0) {
Sint lentmp = -len;
- if (-lentmp != len) {
+ /* overflow */
+ if (lentmp == len || lentmp < 0 || -lentmp != len) {
goto badarg;
}
len = lentmp;
@@ -2210,7 +2229,8 @@ static BIF_RETTYPE binary_bin_to_list_common(Process *p,
}
pos -= len;
}
- if (((pos + len) - len) != pos) {
+ /* overflow */
+ if ((pos + len) < pos || (len > 0 && (pos + len) == pos)) {
goto badarg;
}
sz = binary_size(bin);
diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl
index fa311badf1..62de615a90 100644
--- a/erts/emulator/test/guard_SUITE.erl
+++ b/erts/emulator/test/guard_SUITE.erl
@@ -146,6 +146,15 @@ mask_error(Else) ->
guard_bif_binary_part(doc) ->
["Test the binary_part/2,3 guard BIF's extensively"];
guard_bif_binary_part(Config) when is_list(Config) ->
+ %% Overflow tests that need to be unoptimized
+ ?line badarg =
+ ?MASK_ERROR(
+ binary_part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
+ -16#7FFFFFFFFFFFFFFF-1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary_part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
+ 16#7FFFFFFFFFFFFFFF})),
F = fun(X) ->
Master = self(),
{Pid,Ref} = spawn_monitor( fun() ->
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 31f29eb9e1..4394348c78 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -2,7 +2,7 @@
-export([all/1, interesting/1,random_ref_comp/1,random_ref_sr_comp/1,
random_ref_fla_comp/1,parts/1, bin_to_list/1, list_to_bin/1,
- copy/1, referenced/1,guard/1,encode_decode/1]).
+ copy/1, referenced/1,guard/1,encode_decode/1,badargs/1,longest_common_trap/1]).
-export([random_number/1, make_unaligned/1]).
@@ -46,11 +46,269 @@ fin_per_testcase(_Case, Config) ->
all(suite) -> [interesting,random_ref_fla_comp,random_ref_sr_comp,
random_ref_comp,parts,bin_to_list, list_to_bin, copy,
- referenced,guard,encode_decode].
+ referenced,guard,encode_decode,badargs,longest_common_trap].
-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
+badargs(doc) ->
+ ["Tests various badarg exceptions in the module"];
+badargs(Config) when is_list(Config) ->
+ ?line badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3:3>>])),
+ ?line badarg = ?MASK_ERROR(binary:compile_pattern([<<1,2,3>>|<<1,2>>])),
+ ?line badarg = ?MASK_ERROR(binary:compile_pattern(<<1,2,3:3>>)),
+ ?line badarg = ?MASK_ERROR(binary:compile_pattern(<<>>)),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3:3>>,<<1>>)),
+ ?line badarg = ?MASK_ERROR(binary:matches(<<1,2,3:3>>,<<1>>)),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{0,1},1}])),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scape,{0,1}}])),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{0,1,1}}])),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,0,1}])),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,[0,1]}])),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{0.1,1}}])),
+ ?line badarg = ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{1,1.1}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{16#FF,
+ 16#FFFFFFFFFFFFFFFF}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{16#FFFFFFFFFFFFFFFF,
+ -16#7FFFFFFFFFFFFFFF-1}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:match(<<1,2,3>>,<<1>>,
+ [{scope,{16#FFFFFFFFFFFFFFFF,
+ 16#7FFFFFFFFFFFFFFF}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:part(<<1,2,3>>,{16#FF,
+ 16#FFFFFFFFFFFFFFFF})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
+ -16#7FFFFFFFFFFFFFFF-1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:part(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
+ 16#7FFFFFFFFFFFFFFF})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:part(make_unaligned(<<1,2,3>>),{1,1,1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary_part(make_unaligned(<<1,2,3>>),{1,1,1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFF,
+ -16#7FFFFFFFFFFFFFFF-1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary_part(make_unaligned(<<1,2,3>>),{16#FF,
+ 16#FFFFFFFFFFFFFFFF})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary_part(make_unaligned(<<1,2,3>>),{16#FFFFFFFFFFFFFFFF,
+ 16#7FFFFFFFFFFFFFFF})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>,{16#FF,
+ 16#FFFFFFFFFFFFFFFF})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
+ -16#7FFFFFFFFFFFFFFF-1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>,{16#FFFFFFFFFFFFFFFF,
+ 16#7FFFFFFFFFFFFFFF})),
+ ?line [1,2,3] =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>)),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>,[])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>,{1,2,3})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>,{1.0,1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3>>,{1,1.0})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3:3>>,{1,1})),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list(<<1,2,3:3>>)),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:bin_to_list([1,2,3])),
+
+ ?line nomatch =
+ ?MASK_ERROR(binary:match(<<1,2,3>>,<<1>>,[{scope,{0,0}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:match(<<1,2,3>>,{bm,<<>>},[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:match(<<1,2,3>>,[],[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:match(<<1,2,3>>,{ac,<<>>},[{scope,{0,1}}])),
+ ?line {bm,BMMagic} = binary:compile_pattern([<<1,2,3>>]),
+ ?line {ac,ACMagic} = binary:compile_pattern([<<1,2,3>>,<<4,5>>]),
+ ?line badarg =
+ ?MASK_ERROR(binary:match(<<1,2,3>>,{bm,ACMagic},[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:match(<<1,2,3>>,{ac,BMMagic},[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:match(<<1,2,3>>,
+ {bm,ets:match_spec_compile([{'_',[],['$_']}])},
+ [{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:match(<<1,2,3>>,
+ {ac,ets:match_spec_compile([{'_',[],['$_']}])},
+ [{scope,{0,1}}])),
+ ?line nomatch =
+ ?MASK_ERROR(binary:matches(<<1,2,3>>,<<1>>,[{scope,{0,0}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:matches(<<1,2,3>>,{bm,<<>>},[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:matches(<<1,2,3>>,[],[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:matches(<<1,2,3>>,{ac,<<>>},[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:matches(<<1,2,3>>,{bm,ACMagic},[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:matches(<<1,2,3>>,{ac,BMMagic},[{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:matches(<<1,2,3>>,
+ {bm,ets:match_spec_compile([{'_',[],['$_']}])},
+ [{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(
+ binary:matches(<<1,2,3>>,
+ {ac,ets:match_spec_compile([{'_',[],['$_']}])},
+ [{scope,{0,1}}])),
+ ?line badarg =
+ ?MASK_ERROR(binary:longest_common_prefix(
+ [<<0:10000,1,2,4,1:3>>,
+ <<0:10000,1,2,3>>])),
+ ?line badarg =
+ ?MASK_ERROR(binary:longest_common_suffix(
+ [<<0:10000,1,2,4,1:3>>,
+ <<0:10000,1,2,3>>])),
+ ?line badarg =
+ ?MASK_ERROR(binary:encode_unsigned(-1)),
+ ?line badarg =
+ ?MASK_ERROR(binary:encode_unsigned(-16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)),
+ ok.
+
+longest_common_trap(doc) ->
+ ["Whitebox test to force special trap conditions in longest_common_{prefix,suffix}"];
+longest_common_trap(Config) when is_list(Config) ->
+ ?line erts_debug:set_internal_state(available_internal_state,true),
+ ?line io:format("oldlimit: ~p~n",
+ [erts_debug:set_internal_state(binary_loop_limit,10)]),
+ erlang:bump_reductions(10000000),
+ ?line _ = binary:longest_common_prefix(
+ [<<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>]),
+ ?line _ = binary:longest_common_prefix(
+ [<<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,3>>,
+ <<0:10000,1,3,3>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,4>>,
+ <<0:10000,1,2,3>>,
+ <<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ <<0:10000,1,2,4>>]),
+ erlang:bump_reductions(10000000),
+ ?line _ = binary:longest_common_suffix(
+ [<<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,3,3,0:10000,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ <<1,2,4,0:10000>>]),
+ ?line _ = binary:longest_common_suffix(
+ [<<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<1,2,4,0:10000>>,
+ <<0,0,0,0,0,0,0,0,0,0,0,0,0,0>>,
+ <<1,2,4,0:10000>>]),
+ Subj = subj(),
+ Len = byte_size(Subj),
+ ?line Len = binary:longest_common_suffix(
+ [Subj,Subj,Subj]),
+ ?line io:format("limit was: ~p~n",
+ [erts_debug:set_internal_state(binary_loop_limit,
+ default)]),
+ ?line erts_debug:set_internal_state(available_internal_state,false),
+ ok.
+
+subj() ->
+ Me = self(),
+ spawn(fun() ->
+ X0 = iolist_to_binary([
+ "1234567890",
+ %lists:seq(16#21, 16#7e),
+ lists:duplicate(100, $x)
+ ]),
+ Me ! X0,
+ receive X -> X end
+ end),
+ X0 = receive A -> A end,
+ <<X1:32/binary,_/binary>> = X0,
+ Subject= <<X1/binary>>,
+ Subject.
+
+
interesting(doc) ->
["Try some interesting patterns"];
interesting(Config) when is_list(Config) ->
@@ -332,7 +590,8 @@ encode_decode(doc) ->
["test binary:encode_unsigned/1,2 and binary:decode_unsigned/1,2"];
encode_decode(Config) when is_list(Config) ->
?line random:seed({1271,769940,559934}),
- ?line ok = encode_decode_loop({1,100},1000),
+ ?line ok = encode_decode_loop({1,200},1000), % Need to be long enough
+ % to create offheap binaries
ok.
encode_decode_loop(_Range,0) ->
@@ -437,13 +696,35 @@ copy(Config) when is_list(Config) ->
?line erts_debug:set_internal_state(available_internal_state,true),
?line io:format("oldlimit: ~p~n",
[erts_debug:set_internal_state(binary_loop_limit,10)]),
+ ?line Subj = subj(),
+ ?line XX = binary:copy(Subj,1000),
+ ?line XX = binref:copy(Subj,1000),
?line ok = random_copy(1000),
+ ?line kill_copy_loop(1000),
?line io:format("limit was: ~p~n",
[erts_debug:set_internal_state(binary_loop_limit,
default)]),
?line erts_debug:set_internal_state(available_internal_state,false),
ok.
+kill_copy_loop(0) ->
+ ok;
+kill_copy_loop(N) ->
+ {Pid,Ref} = spawn_monitor(fun() ->
+ ok = random_copy(1000)
+ end),
+ receive
+ after 10 ->
+ ok
+ end,
+ exit(Pid,kill),
+ receive
+ {'DOWN',Ref,process,Pid,_} ->
+ kill_copy_loop(N-1)
+ after 1000 ->
+ exit(did_not_die)
+ end.
+
random_copy(0) ->
ok;
random_copy(N) ->
@@ -590,6 +871,8 @@ random_ref_comp(Config) when is_list(Config) ->
io:format("Number of successes: ~p~n",[get(success_counter)]),
?line do_random_match_comp3(5000,{1,40},{30,1000}),
io:format("Number of successes: ~p~n",[get(success_counter)]),
+ ?line do_random_match_comp4(5000,{1,40},{30,1000}),
+ io:format("Number of successes: ~p~n",[get(success_counter)]),
?line do_random_matches_comp(5000,{1,40},{30,1000}),
io:format("Number of successes: ~p~n",[get(success_counter)]),
?line do_random_matches_comp2(5000,{1,40},{30,1000}),
@@ -597,6 +880,7 @@ random_ref_comp(Config) when is_list(Config) ->
?line do_random_matches_comp3(5,{1,40},{30,1000}),
?line erts_debug:set_internal_state(available_internal_state,true),
?line io:format("oldlimit: ~p~n",[ erts_debug:set_internal_state(binary_loop_limit,100)]),
+ ?line do_random_match_comp(5000,{1,40},{30,1000}),
?line do_random_matches_comp3(5,{1,40},{30,1000}),
?line io:format("limit was: ~p~n",[ erts_debug:set_internal_state(binary_loop_limit,default)]),
?line erts_debug:set_internal_state(available_internal_state,false),
@@ -748,7 +1032,8 @@ do_matches_comp(N,H) ->
A = ?MASK_ERROR(binref:matches(H,N)),
B = ?MASK_ERROR(binref:matches(H,binref:compile_pattern(N))),
C = ?MASK_ERROR(binary:matches(H,N)),
- D = ?MASK_ERROR(binary:matches(make_unaligned(H),binary:compile_pattern(N))),
+ D = ?MASK_ERROR(binary:matches(make_unaligned(H),
+ binary:compile_pattern([make_unaligned2(X) || X <- N]))),
if
A =/= nomatch ->
put(success_counter,get(success_counter)+1);
@@ -792,25 +1077,36 @@ do_random_match_comp3(N,NeedleRange,HaystackRange) ->
true = do_match_comp3(Needles,Haystack),
do_random_match_comp3(N-1,NeedleRange,HaystackRange).
+do_random_match_comp4(0,_,_) ->
+ ok;
+do_random_match_comp4(N,NeedleRange,HaystackRange) ->
+ NumNeedles = element(2,HaystackRange) div element(2,NeedleRange),
+ Haystack = random_string(HaystackRange),
+ Needles = [random_string(NeedleRange) ||
+ _ <- lists:duplicate(NumNeedles,a)],
+ true = do_match_comp3(Needles,Haystack),
+ do_random_match_comp4(N-1,NeedleRange,HaystackRange).
+
do_match_comp(N,H) ->
A = ?MASK_ERROR(binref:match(H,N)),
B = ?MASK_ERROR(binref:match(H,binref:compile_pattern([N]))),
C = ?MASK_ERROR(binary:match(make_unaligned(H),N)),
D = ?MASK_ERROR(binary:match(H,binary:compile_pattern([N]))),
+ E = ?MASK_ERROR(binary:match(H,binary:compile_pattern(make_unaligned(N)))),
if
A =/= nomatch ->
put(success_counter,get(success_counter)+1);
true ->
ok
end,
- case {(A =:= B), (B =:= C),(C =:= D)} of
- {true,true,true} ->
+ case {(A =:= B), (B =:= C),(C =:= D),(D =:= E)} of
+ {true,true,true,true} ->
true;
_ ->
io:format("Failed to match ~s (needle) against ~s (haystack)~n",
[N,H]),
- io:format("A:~p,~nB:~p,~n,C:~p,~n,D:~p.~n",
- [A,B,C,D]),
+ io:format("A:~p,~nB:~p,~n,C:~p,~n,D:~p,E:~p.~n",
+ [A,B,C,D,E]),
exit(mismatch)
end.
@@ -969,5 +1265,10 @@ make_unaligned(Bin0) when is_binary(Bin0) ->
Sz = byte_size(Bin0),
<<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
Bin.
+make_unaligned2(Bin0) when is_binary(Bin0) ->
+ Bin1 = <<31:5,Bin0/binary,0:3>>,
+ Sz = byte_size(Bin0),
+ <<31:5,Bin:Sz/binary,0:3>> = id(Bin1),
+ Bin.
id(I) -> I.