1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(binary_SUITE).
22
23%% Tests binaries and the BIFs:
24%%	list_to_binary/1
25%%      iolist_to_binary/1
26%%      list_to_bitstring/1
27%%	binary_to_list/1
28%%	binary_to_list/3
29%%	binary_to_term/1
30%%  	binary_to_term/2
31%%      bitstring_to_list/1
32%%	term_to_binary/1
33%%      erlang:external_size/1
34%%	size(Binary)
35%%      iolist_size/1
36%%	split_binary/2
37%%      hash(Binary, N)
38%%      phash(Binary, N)
39%%      phash2(Binary, N)
40%%
41
42-include_lib("common_test/include/ct.hrl").
43-include_lib("common_test/include/ct_event.hrl").
44
45-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
46	 init_per_group/2,end_per_group/2,
47	 init_per_testcase/2, end_per_testcase/2,
48	 copy_terms/1, conversions/1, deep_lists/1, deep_bitstr_lists/1,
49	 bad_list_to_binary/1, bad_binary_to_list/1,
50	 t_split_binary/1, bad_split/1,
51	 terms/1, terms_float/1, float_middle_endian/1,
52         b2t_used_big/1, t2b_deterministic/1,
53	 external_size/1, t_iolist_size/1,
54         t_iolist_size_huge_list/1,
55         t_iolist_size_huge_bad_arg_list/1,
56         t_iolist_size_shallow_trapping/1,
57         t_iolist_size_shallow_short_lists/1,
58         t_iolist_size_shallow_tiny_lists/1,
59         t_iolist_size_deep_trapping/1,
60         t_iolist_size_deep_short_lists/1,
61         t_iolist_size_deep_tiny_lists/1,
62	 t_hash/1,
63         sub_bin_copy/1,
64	 bad_size/1,
65	 bad_term_to_binary/1,
66	 bad_binary_to_term_2/1,safe_binary_to_term2/1,
67	 bad_binary_to_term/1, bad_terms/1, more_bad_terms/1,
68	 otp_5484/1,otp_5933/1,
69	 ordering/1,unaligned_order/1,gc_test/1,
70	 bit_sized_binary_sizes/1,
71	 otp_6817/1,deep/1,
72         term2bin_tuple_fallbacks/1,
73         robustness/1,otp_8117/1,
74	 otp_8180/1, trapping/1, large/1,
75	 error_after_yield/1, cmp_old_impl/1,
76         t2b_system_limit/1,
77         term_to_iovec/1]).
78
79%% Internal exports.
80-export([sleeper/0,trapping_loop/4]).
81
82suite() -> [{ct_hooks,[ts_install_cth]},
83	    {timetrap,{minutes,4}}].
84
85all() ->
86    [copy_terms, conversions, deep_lists, deep_bitstr_lists,
87     t_split_binary, bad_split,
88     bad_list_to_binary, bad_binary_to_list, terms,
89     terms_float, float_middle_endian, external_size, t_iolist_size,
90     t_iolist_size_huge_list,
91     t_iolist_size_huge_bad_arg_list,
92     {group, iolist_size_benchmarks},
93     b2t_used_big, t2b_deterministic,
94     bad_binary_to_term_2, safe_binary_to_term2,
95     bad_binary_to_term, bad_terms, t_hash, bad_size,
96     sub_bin_copy, bad_term_to_binary, t2b_system_limit,
97     term_to_iovec, more_bad_terms,
98     otp_5484, otp_5933,
99     ordering, unaligned_order, gc_test,
100     bit_sized_binary_sizes, otp_6817, otp_8117, deep,
101     term2bin_tuple_fallbacks,
102     robustness, otp_8180, trapping, large,
103     error_after_yield, cmp_old_impl].
104
105groups() ->
106    [
107     {
108      iolist_size_benchmarks,
109      [],
110      [t_iolist_size_shallow_trapping,
111       t_iolist_size_shallow_short_lists,
112       t_iolist_size_shallow_tiny_lists,
113       t_iolist_size_deep_trapping,
114       t_iolist_size_deep_short_lists,
115       t_iolist_size_deep_tiny_lists
116      ]
117     }
118    ].
119
120init_per_suite(Config) ->
121    A0 = case application:start(sasl) of
122	     ok -> [sasl];
123	     _ -> []
124	 end,
125    A = case application:start(os_mon) of
126	     ok -> [os_mon|A0];
127	     _ -> A0
128	 end,
129    [{started_apps, A}|Config].
130
131end_per_suite(Config) ->
132    As = proplists:get_value(started_apps, Config),
133    lists:foreach(fun (A) -> application:stop(A) end, As),
134    Config.
135
136
137init_per_group(_GroupName, Config) ->
138    Config.
139
140end_per_group(_GroupName, Config) ->
141    Config.
142
143init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
144    Config.
145
146end_per_testcase(_Func, _Config) ->
147    ok.
148
149-define(heap_binary_size, 64).
150
151copy_terms(Config) when is_list(Config) ->
152    Self = self(),
153    Pid = spawn_link(fun() -> copy_server(Self) end),
154    F = fun(Term) ->
155		Pid ! Term,
156		receive
157		    Term -> ok;
158		    Other ->
159			io:format("Sent: ~P\nGot back:~P", [Term,12,Other,12]),
160			ct:fail(bad_term)
161		end
162	end,
163    test_terms(F),
164    ok.
165
166copy_server(Parent) ->
167    receive
168	Term ->
169	    Parent ! Term,
170	    copy_server(Parent)
171    end.
172
173%% Tests list_to_binary/1, binary_to_list/1 and size/1,
174%% using flat lists.
175
176conversions(Config) when is_list(Config) ->
177    test_bin([]),
178    test_bin([1]),
179    test_bin([1, 2]),
180    test_bin([1, 2, 3]),
181    test_bin(lists:seq(0, ?heap_binary_size)),
182    test_bin(lists:seq(0, ?heap_binary_size+1)),
183    test_bin(lists:seq(0, 255)),
184    test_bin(lists:duplicate(50000, $@)),
185
186    %% Binary in list.
187    List = [1,2,3,4,5],
188    B1 = make_sub_binary(list_to_binary(List)),
189    5 = size(B1),
190    5 = size(make_unaligned_sub_binary(B1)),
191    40 = bit_size(B1),
192    40 = bit_size(make_unaligned_sub_binary(B1)),
193    B2 = list_to_binary([42,B1,19]),
194    B2 = list_to_binary([42,make_unaligned_sub_binary(B1),19]),
195    B2 = iolist_to_binary(B2),
196    B2 = iolist_to_binary(make_unaligned_sub_binary(B2)),
197    7 = size(B2),
198    7 = size(make_sub_binary(B2)),
199    56 = bit_size(B2),
200    56 = bit_size(make_sub_binary(B2)),
201    [42,1,2,3,4,5,19] = binary_to_list(B2),
202    [42,1,2,3,4,5,19] = binary_to_list(make_sub_binary(B2)),
203    [42,1,2,3,4,5,19] = binary_to_list(make_unaligned_sub_binary(B2)),
204    [42,1,2,3,4,5,19] = bitstring_to_list(B2),
205    [42,1,2,3,4,5,19] = bitstring_to_list(make_sub_binary(B2)),
206    [42,1,2,3,4,5,19] = bitstring_to_list(make_unaligned_sub_binary(B2)),
207
208    ok.
209
210test_bin(List) ->
211    Size = length(List),
212    Bin = list_to_binary(List),
213    Bin = iolist_to_binary(List),
214    Bin = list_to_bitstring(List),
215    Size = iolist_size(List),
216    Size = iolist_size(Bin),
217    Size = iolist_size(make_unaligned_sub_binary(Bin)),
218    Size = size(Bin),
219    Size = size(make_sub_binary(Bin)),
220    Size = size(make_unaligned_sub_binary(Bin)),
221    List = binary_to_list(Bin),
222    List = binary_to_list(make_sub_binary(Bin)),
223    List = binary_to_list(make_unaligned_sub_binary(Bin)),
224    List = bitstring_to_list(Bin),
225    List = bitstring_to_list(make_unaligned_sub_binary(Bin)).
226
227%% Tests list_to_binary/1, iolist_to_binary/1, list_to_bitstr/1, binary_to_list/1,3,
228%% bitstr_to_list/1, and size/1, using deep lists.
229
230deep_lists(Config) when is_list(Config) ->
231    test_deep_list(["abc"]),
232    test_deep_list([[12,13,[123,15]]]),
233    test_deep_list([[12,13,[lists:seq(0, 255), []]]]),
234    ok.
235
236test_deep_list(List) ->
237    FlatList = lists:flatten(List),
238    Size = length(FlatList),
239    Bin = list_to_binary(List),
240    Bin = iolist_to_binary(List),
241    Bin = iolist_to_binary(Bin),
242    Bin = list_to_bitstring(List),
243    Size = size(Bin),
244    Size = iolist_size(List),
245    Size = iolist_size(FlatList),
246    Size = iolist_size(Bin),
247    Bitsize = bit_size(Bin),
248    Bitsize = 8*Size,
249    FlatList = binary_to_list(Bin),
250    FlatList = bitstring_to_list(Bin),
251    io:format("testing plain binary..."),
252    t_binary_to_list_3(FlatList, Bin, 1, Size),
253    io:format("testing unaligned sub binary..."),
254    t_binary_to_list_3(FlatList, make_unaligned_sub_binary(Bin), 1, Size).
255
256t_binary_to_list_3(List, Bin, From, To) ->
257    going_up(List, Bin, From, To),
258    going_down(List, Bin, From, To),
259    going_center(List, Bin, From, To).
260
261going_up(List, Bin, From, To) when From =< To ->
262    List = binary_to_list(Bin, From, To),
263    going_up(tl(List), Bin, From+1, To);
264going_up(_List, _Bin, From, To) when From > To ->
265    ok.
266
267going_down(List, Bin, From, To) when To > 0->
268    compare(List, binary_to_list(Bin, From, To), To-From+1),
269    going_down(List, Bin, From, To-1);
270going_down(_List, _Bin, _From, _To) ->
271    ok.
272
273going_center(List, Bin, From, To) when From >= To ->
274    compare(List, binary_to_list(Bin, From, To), To-From+1),
275    going_center(tl(List), Bin, From+1, To-1);
276going_center(_List, _Bin, _From, _To) ->
277    ok.
278
279compare([X|Rest1], [X|Rest2], Left) when Left > 0 ->
280    compare(Rest1, Rest2, Left-1);
281compare([_X|_], [_Y|_], _Left) ->
282    ct:fail("compare fail");
283compare(_List, [], 0) ->
284    ok.
285
286deep_bitstr_lists(Config) when is_list(Config) ->
287    {<<7:3>>,[<<7:3>>]} = test_deep_bitstr([<<7:3>>]),
288    {<<42,5:3>>=Bin,[42,<<5:3>>]=List} = test_deep_bitstr([42,<<5:3>>]),
289    {Bin,List} = test_deep_bitstr([42|<<5:3>>]),
290    {Bin,List} = test_deep_bitstr([<<42,5:3>>]),
291    {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>|<<5:3>>]),
292    {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>,<<5:3>>]),
293    {Bin,List} = test_deep_bitstr([[<<1:3>>,<<10:5>>],[],<<5:3>>]),
294    {Bin,List} = test_deep_bitstr([[[<<1:3>>]|<<10:5>>],[],<<5:3>>]),
295    {Bin,List} = test_deep_bitstr([[<<0:1>>,<<0:1>>,[],<<1:1>>,<<10:5>>],
296					 <<1:1>>,<<0:1>>,<<1:1>>]),
297    ok.
298
299test_deep_bitstr(List) ->
300    %%{'EXIT',{badarg,_}} = list_to_binary(List),
301    Bin = list_to_bitstring(List),
302    {Bin,bitstring_to_list(Bin)}.
303
304bad_list_to_binary(Config) when is_list(Config) ->
305    test_bad_bin(<<1:1>>),
306    test_bad_bin(atom),
307    test_bad_bin(42),
308    test_bad_bin([1|2]),
309    test_bad_bin([256]),
310    test_bad_bin([255, [256]]),
311    test_bad_bin([-1]),
312    test_bad_bin([atom_in_list]),
313    test_bad_bin([[<<8>>]|bad_tail]),
314
315    {'EXIT',{badarg,_}} = (catch list_to_binary(id(<<1,2,3>>))),
316    {'EXIT',{badarg,_}} = (catch list_to_binary(id([<<42:7>>]))),
317    {'EXIT',{badarg,_}} = (catch list_to_bitstring(id(<<1,2,3>>))),
318
319    %% Funs used to be implemented as a type of binary internally.
320    test_bad_bin(fun(X, Y) -> X*Y end),
321    test_bad_bin([1,fun(X) -> X + 1 end,2|fun() -> 0 end]),
322    test_bad_bin([fun(X) -> X + 1 end]),
323
324    %% Test iolists that do not fit in the address space.
325    %% Unfortunately, it would be too slow to test in a 64-bit emulator.
326    case erlang:system_info(wordsize) of
327	4 -> huge_iolists();
328	_ -> ok
329    end.
330
331huge_iolists() ->
332    FourGigs = 1 bsl 32,
333    Sizes = [FourGigs+N || N <- lists:seq(0, 64)] ++
334	[1 bsl N || N <- lists:seq(33, 37)],
335    Base = <<0:(1 bsl 20)/unit:8>>,
336    [begin
337	 L = build_iolist(Sz, Base),
338	 {'EXIT',{system_limit,_}} = (catch list_to_binary([L])),
339	 {'EXIT',{system_limit,_}} = (catch list_to_bitstring([L])),
340	 {'EXIT',{system_limit,_}} = (catch binary:list_to_bin([L])),
341	 {'EXIT',{system_limit,_}} = (catch iolist_to_binary(L))
342	 end || Sz <- Sizes],
343    ok.
344
345test_bad_bin(List) ->
346    {'EXIT',{badarg,_}} = (catch list_to_binary(List)),
347    {'EXIT',{badarg,_}} = (catch iolist_to_binary(List)),
348    {'EXIT',{badarg,_}} = (catch list_to_bitstring(List)),
349    {'EXIT',{badarg,_}} = (catch iolist_size(List)).
350
351%% Tries binary_to_list/1,3 with bad arguments.
352bad_binary_to_list(Config) when is_list(Config) ->
353    bad_bin_to_list(fun(X) -> X * 42 end),
354
355    GoodBin = list_to_binary(lists:seq(1, 10)),
356    bad_bin_to_list(fun(X) -> X * 44 end, 1, 2),
357    bad_bin_to_list(GoodBin, 0, 1),
358    bad_bin_to_list(GoodBin, 2, 1),
359    bad_bin_to_list(GoodBin, 11, 11),
360    {'EXIT',{badarg,_}} = (catch binary_to_list(id(<<42:7>>))),
361    ok.
362
363bad_bin_to_list(BadBin) ->
364    {'EXIT',{badarg,_}} = (catch binary_to_list(BadBin)),
365    {'EXIT',{badarg,_}} = (catch bitstring_to_list(BadBin)).
366
367bad_bin_to_list(Bin, First, Last) ->
368    {'EXIT',{badarg,_}} = (catch binary_to_list(Bin, First, Last)).
369
370
371%% Tries to split a binary at all possible positions.
372
373t_split_binary(Config) when is_list(Config) ->
374    L = lists:seq(0, ?heap_binary_size-5), %Heap binary.
375    B = list_to_binary(L),
376    split(L, B, size(B)),
377
378    %% Sub binary of heap binary.
379    split(L, make_sub_binary(B), size(B)),
380    {X,Y} = split_binary(B, size(B) div 2),
381    split(binary_to_list(X), X, size(X)),
382
383    %% Unaligned sub binary of heap binary.
384    split(L, make_unaligned_sub_binary(B), size(B)),
385    {X,Y} = split_binary(B, size(B) div 2),
386    split(binary_to_list(X), X, size(X)),
387
388    %% Reference-counted binary.
389    L2 = lists:seq(0, ?heap_binary_size+1),
390    B2 = list_to_binary(L2),
391    split(L2, B2, size(B2)),
392
393    %% Sub binary of reference-counted binary.
394    split(L2, make_sub_binary(B2), size(B2)),
395    {X2,Y2} = split_binary(B2, size(B2) div 2),
396    split(binary_to_list(X2), X2, size(X2)),
397
398    %% Unaligned sub binary of reference-counted binary.
399    split(L2, make_unaligned_sub_binary(B2), size(B2)),
400    {X2,Y2} = split_binary(B2, size(B2) div 2),
401    split(binary_to_list(X2), X2, size(X2)),
402
403    ok.
404
405split(L, B, Pos) when Pos > 0 ->
406    {B1, B2} = split_binary(B, Pos),
407    B1 = list_to_binary(lists:sublist(L, 1, Pos)),
408    B2 = list_to_binary(lists:nthtail(Pos, L)),
409    split(L, B, Pos-1);
410split(_L, _B, 0) ->
411    ok.
412
413%% Tries split_binary/2 with bad arguments.
414bad_split(Config) when is_list(Config) ->
415    GoodBin = list_to_binary([1,2,3]),
416    bad_split(GoodBin, -1),
417    bad_split(GoodBin, 4),
418    bad_split(GoodBin, a),
419
420    %% Funs are a kind of binaries.
421    bad_split(fun(_X) -> 1 end, 1),
422    ok.
423
424bad_split(Bin, Pos) ->
425    {'EXIT',{badarg,_}} = (catch split_binary(Bin, Pos)).
426
427%% Test hash/2 with different type of binaries.
428t_hash(Config) when is_list(Config) ->
429    test_hash([]),
430    test_hash([253]),
431    test_hash(lists:seq(1, ?heap_binary_size)),
432    test_hash(lists:seq(1, ?heap_binary_size+1)),
433    test_hash([X rem 256 || X <- lists:seq(1, 312)]),
434    ok.
435
436test_hash(List) ->
437    Bin = list_to_binary(List),
438    Sbin = make_sub_binary(List),
439    Unaligned = make_unaligned_sub_binary(Sbin),
440    test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash/2),
441    test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash2/2).
442
443test_hash_1(Bin, Sbin, Unaligned, Hash) when is_function(Hash, 2) ->
444    N = 65535,
445    case {Hash(Bin, N),Hash(Sbin, N),Hash(Unaligned, N)} of
446	{H,H,H} -> ok;
447	{H1,H2,H3} ->
448	    ct:fail("Different hash values: ~p, ~p, ~p\n", [H1,H2,H3])
449    end.
450
451%% Try bad arguments to size/1.
452bad_size(Config) when is_list(Config) ->
453    {'EXIT',{badarg,_}} = (catch size(fun(X) -> X + 33 end)),
454    ok.
455
456bad_term_to_binary(Config) when is_list(Config) ->
457    T = id({a,b,c}),
458    {'EXIT',{badarg,_}} = (catch term_to_binary(T, not_a_list)),
459    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [blurf])),
460    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [iovec])),
461    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,-1}])),
462    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,10}])),
463    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,cucumber}])),
464    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed}])),
465    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{version,1}|bad_tail])),
466    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,-1}])),
467    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,x}])),
468
469    ok.
470
471t2b_system_limit(Config) when is_list(Config) ->
472    case erlang:system_info(wordsize) of
473        8 ->
474            case proplists:get_value(system_total_memory,
475                                     memsup:get_system_memory_data()) of
476                Memory when is_integer(Memory),
477                            Memory > 6*1024*1024*1024 ->
478                    do_t2b_system_limit();
479                _ ->
480                    {skipped, "Not enough memory on this machine"}
481            end;
482        4 ->
483            {skipped, "Only interesting on 64-bit builds"}
484    end.
485
486do_t2b_system_limit() ->
487    F = fun() ->
488                io:format("Creating HugeBin~n", []),
489                Bits = (1 bsl 32) + 1,
490                HugeBin = <<0:Bits/unit:8>>,
491                test_t2b_system_limit(HugeBin, term_to_binary,
492                                      fun erlang:term_to_binary/1,
493                                      fun erlang:term_to_binary/2),
494                test_t2b_system_limit(HugeBin, term_to_iovec,
495                                      fun erlang:term_to_iovec/1,
496                                      fun erlang:term_to_iovec/2),
497                garbage_collect(),
498                ok
499        end,
500    Opts = [{args, "-pa " ++ filename:dirname(code:which(?MODULE))}],
501    {ok,Node} = test_server:start_node(?FUNCTION_NAME, slave, Opts),
502    erpc:call(Node, F).
503
504test_t2b_system_limit(HugeBin, Name, F1, F2) ->
505    io:format("Testing ~p(HugeBin)~n", [Name]),
506    {'EXIT',{system_limit,[{erlang,Name,[HugeBin],_}|_]}} =
507        t2b_eval(fun() -> F1(HugeBin) end),
508
509    io:format("Testing ~p(HugeBin, [compressed])~n", [Name]),
510    {'EXIT',{system_limit,[{erlang,Name,[HugeBin,[compressed]],_}|_]}} =
511        t2b_eval(fun() -> F2(HugeBin, [compressed]) end),
512
513    %% Check that it works also after we have trapped...
514    io:format("Creating HugeListBin~n", []),
515    HugeListBin = [lists:duplicate(2000000, 2000000), HugeBin],
516
517    io:format("Testing ~p(HugeListBin)~n", [Name]),
518    {'EXIT',{system_limit,[{erlang,Name,[HugeListBin],_}|_]}} =
519        t2b_eval(fun() -> F1(HugeListBin) end),
520
521    io:format("Testing ~p(HugeListBin, [compressed])~n", [Name]),
522    {'EXIT',{system_limit,[{erlang,Name,[HugeListBin,[compressed]],_}|_]}} =
523        t2b_eval(fun() -> F2(HugeListBin, [compressed]) end),
524
525    ok.
526
527t2b_eval(F) ->
528    Result = (catch F()),
529    io:put_chars(io_lib:format("~P\n", [Result,100])),
530    Result.
531
532term_to_iovec(Config) when is_list(Config) ->
533    Bin = list_to_binary(lists:duplicate(1000,100)),
534    Bin2 = list_to_binary(lists:duplicate(65,100)),
535    check_term_to_iovec({[Bin, atom, Bin, 1244, make_ref(), Bin]}),
536    check_term_to_iovec(Bin),
537    check_term_to_iovec([Bin,Bin,Bin,Bin]),
538    check_term_to_iovec(blipp),
539    check_term_to_iovec(lists:duplicate(1000,100)),
540    check_term_to_iovec([[Bin2]]),
541    check_term_to_iovec([erlang:ports(), Bin, erlang:processes()]),
542    ok.
543
544check_term_to_iovec(Term) ->
545    IoVec1 = erlang:term_to_iovec(Term),
546    ok = check_is_iovec(IoVec1),
547    IoVec2 = erlang:term_to_iovec(Term, []),
548    ok = check_is_iovec(IoVec2),
549    B = erlang:term_to_binary(Term),
550    IoVec1Bin = erlang:iolist_to_binary(IoVec1),
551    IoVec2Bin = erlang:iolist_to_binary(IoVec2),
552    try
553        B = IoVec1Bin
554    catch
555        _:_ ->
556            io:format("Binary: ~p~n", [B]),
557            io:format("I/O vec1 binary: ~p~n", [IoVec1Bin]),
558            io:format("I/O vec1: ~p~n", [IoVec1]),
559            ct:fail(not_same_result)
560    end,
561    try
562        B = IoVec2Bin
563    catch
564        _:_ ->
565            io:format("Binary: ~p~n", [B]),
566            io:format("I/O vec2 binary: ~p~n", [IoVec2Bin]),
567            io:format("I/O vec2: ~p~n", [IoVec2]),
568            ct:fail(not_same_result)
569    end.
570
571check_is_iovec([]) ->
572    ok;
573check_is_iovec([B|Bs]) when is_binary(B) ->
574    check_is_iovec(Bs).
575
576%% Tests binary_to_term/1 and term_to_binary/1.
577
578terms(Config) when is_list(Config) ->
579    TestFun = fun(Term) ->
580                      S = io_lib:format("~p", [Term]),
581                      io:put_chars(S),
582
583		      Bin = term_to_binary(Term),
584		      case erlang:external_size(Bin) of
585			  Sz when is_integer(Sz), size(Bin) =< Sz ->
586			      ok
587		      end,
588
589                      Bin1 = term_to_binary(Term, [{minor_version, 1}]),
590                      case erlang:external_size(Bin1, [{minor_version, 1}]) of
591                          Sz1 when is_integer(Sz1), size(Bin1) =< Sz1 ->
592                              ok
593                      end,
594
595                      BinDet = term_to_binary(Term, [deterministic]),
596                      case erlang:external_size(Bin) of
597                          DetSz when is_integer(DetSz), byte_size(Bin) =< DetSz ->
598                              ok
599                      end,
600
601		      Term = binary_to_term_stress(Bin),
602		      Term = binary_to_term_stress(Bin, [safe]),
603		      Term = binary_to_term_stress(BinDet),
604                      Bin_sz = byte_size(Bin),
605		      {Term,Bin_sz} = binary_to_term_stress(Bin, [used]),
606
607                      BinE = <<Bin/binary, 1, 2, 3>>,
608		      {Term,Bin_sz} = binary_to_term_stress(BinE, [used]),
609
610		      BinU = make_unaligned_sub_binary(Bin),
611		      Term = binary_to_term_stress(BinU),
612		      Term = binary_to_term_stress(BinU, []),
613		      Term = binary_to_term_stress(BinU, [safe]),
614		      {Term,Bin_sz} = binary_to_term_stress(BinU, [used]),
615
616                      BinUE = make_unaligned_sub_binary(BinE),
617		      {Term,Bin_sz} = binary_to_term_stress(BinUE, [used]),
618
619		      BinC = erlang:term_to_binary(Term, [compressed]),
620                      BinC_sz = byte_size(BinC),
621		      true = BinC_sz =< size(Bin),
622		      Term = binary_to_term_stress(BinC),
623		      {Term, BinC_sz} = binary_to_term_stress(BinC, [used]),
624
625		      Bin = term_to_binary(Term, [{compressed,0}]),
626		      terms_compression_levels(Term, size(Bin), 1),
627
628		      BinUC = make_unaligned_sub_binary(BinC),
629		      Term = binary_to_term_stress(BinUC),
630                      {Term,BinC_sz} = binary_to_term_stress(BinUC, [used]),
631
632                      BinCE = <<BinC/binary, 1, 2, 3>>,
633		      {Term,BinC_sz} = binary_to_term_stress(BinCE, [used]),
634
635		      BinUCE = make_unaligned_sub_binary(BinCE),
636		      Term = binary_to_term_stress(BinUCE),
637                      {Term,BinC_sz} = binary_to_term_stress(BinUCE, [used])
638	      end,
639    test_terms(TestFun),
640    ok.
641
642%% Test binary_to_term(_, [used]) returning a big Used integer.
643b2t_used_big(_Config) ->
644    case erlang:system_info(wordsize) of
645        8 ->
646            {skipped, "This is not a 32-bit machine"};
647        4 ->
648            %% Use a long utf8 atom for large external format but compact on heap.
649            BigAtom = binary_to_atom(<< <<16#F0908D88:32>> || _ <- lists:seq(1,255) >>,
650                                     utf8),
651            Atoms = (1 bsl 17) + (1 bsl 9),
652            BigAtomList = lists:duplicate(Atoms, BigAtom),
653            BigBin = term_to_binary(BigAtomList),
654            {BigAtomList, Used} = binary_to_term(BigBin, [used]),
655            2 = erts_debug:size(Used),
656            Used = byte_size(BigBin),
657            Used = 1 + 1 + 4 + Atoms*(1+2+4*255) + 1,
658            ok
659    end.
660
661terms_compression_levels(Term, UncompressedSz, Level) when Level < 10 ->
662    BinC = erlang:term_to_binary(Term, [{compressed,Level}]),
663    Term = binary_to_term_stress(BinC),
664    Sz = byte_size(BinC),
665    true = Sz =< UncompressedSz,
666    terms_compression_levels(Term, UncompressedSz, Level+1);
667terms_compression_levels(_, _, _) -> ok.
668
669terms_float(Config) when is_list(Config) ->
670    test_floats(fun(Term) ->
671			      Bin0 = term_to_binary(Term, [{minor_version,0}]),
672			      Term = binary_to_term_stress(Bin0),
673			      Bin1 = term_to_binary(Term),
674			      Bin1 = term_to_binary(Term, [{minor_version,1}]),
675			      Term = binary_to_term_stress(Bin1),
676			      true = size(Bin1) < size(Bin0),
677                  Size0 = erlang:external_size(Term, [{minor_version, 0}]),
678                  Size1 = erlang:external_size(Term),
679                  Size11 = erlang:external_size(Term, [{minor_version, 1}]),
680                  true = (Size1 =:= Size11),
681                  true = Size1 < Size0
682		      end).
683
684float_middle_endian(Config) when is_list(Config) ->
685    %% Testing for roundtrip is not enough.
686    <<131,70,63,240,0,0,0,0,0,0>> = term_to_binary(1.0, [{minor_version,1}]),
687    1.0 = binary_to_term_stress(<<131,70,63,240,0,0,0,0,0,0>>).
688
689%% Test term_to_binary(Term, [deterministic]).
690t2b_deterministic(_Config) ->
691    _ = rand:uniform(),				%Seed generator
692    io:format("Seed: ~p", [rand:export_seed()]),
693    Map0 = t2b_deterministic_1(100, #{1 => a, 1.0 => b}),
694
695    Map1 = maps:merge(make_map(10000), Map0),
696    test_deterministic(Map1),
697
698    case total_memory() of
699        Amount when Amount > 15 ->
700            t2b_deterministic_heavy(Map0);
701        _ ->
702            {comment,"heavy tests skipped"}
703    end.
704
705t2b_deterministic_heavy(Map0) ->
706    Map1 = maps:merge(make_map(1_000_000), Map0),
707    test_deterministic(Map1),
708
709    %% If the external representation of the term to be encoded is
710    %% estimated to fit in a heap binary (64 bytes), the internal
711    %% enc_term_int() function that does the actual encoding will be
712    %% called without an context and thus is unable to trap. In the
713    %% DEBUG build of the runtime system, maps with more than 3
714    %% elements will be large maps, and depending on the keys and
715    %% values, it is possible that a large map can fit in 64
716    %% bytes. Therefore, the encoding code for deterministic maps must
717    %% cannot assume that there always exists a context.
718
719    lists:foreach(fun(N) ->
720                          Map = maps:from_list([{E,E} || E <- lists:seq(1, N)]),
721                          test_deterministic(Map)
722                  end, lists:seq(4, 16)),
723
724    %% Test that terminating a process that is encoding a huge map
725    %% will neither crash the runtime system nor leak memory. (Run the
726    %% test with memory sanitizer or valgrind to catch potential memory
727    %% leaks.)
728    erlang:trace_pattern({erlang, term_to_binary, 2}, true, []),
729    Map = huge_map(1_000_000, []),
730    rinse_and_repeat(2, Map).
731
732rinse_and_repeat(Wait, Map) ->
733    {Pid,Ref} = spawn_monitor(fun() ->
734                                      receive go -> ok end,
735                                      term_to_binary(Map, [deterministic])
736                              end),
737    erlang:trace(Pid, true, [call,arity]),
738
739    Pid ! go,
740    receive
741        {trace,Pid,call,{erlang,term_to_binary,2}} ->
742            %% Wait a short period to avoid killing term_to_binary/2 during
743            %% size calculation part.
744            receive after Wait -> ok end,
745            exit(Pid, kill);
746        Other ->
747            error(Other)
748    end,
749
750    receive
751        {'DOWN',Ref,process,Pid,Reason} ->
752            case Reason of
753                normal ->
754                    %% The encoding operation finished before the process
755                    %% was forcefully killed. Done.
756                    ok;
757                killed ->
758                    %% The process was killed in term_to_binary/2. We
759                    %% can't know whether it was killed too early, so
760                    %% we will try again with a slightly longer time.
761                    rinse_and_repeat(Wait + Wait div 2, Map)
762            end;
763        Other2 ->
764            error(Other2)
765    end.
766
767huge_map(0, Acc) ->
768    maps:from_list(Acc);
769huge_map(N, Acc) ->
770    %% Create awkward keys to slow down the sorting.
771    Key = <<N:127/big>>,
772    huge_map(N-1, [{Key,N}|Acc]).
773
774t2b_deterministic_1(0, Map) ->
775    Map;
776t2b_deterministic_1(N, Map0) ->
777    test_deterministic(Map0),
778    Map = Map0#{random_term() => N},
779    t2b_deterministic_1(N - 1, Map).
780
781test_deterministic(Map) ->
782    Bin = term_to_binary(Map, [deterministic]),
783    Map = binary_to_term(Bin),
784
785    %% Make sure that the keys for the map are ordered.
786    List0 = maps:to_list(Map),
787    List = lists:sort(fun(A, B) -> erts_internal:cmp_term(A, B) =< 0 end, List0),
788    List = decode_ext_map(Bin),
789    ok.
790
791decode_ext_map(MapBin) ->
792    MapTag = 116,
793    ListTag = 108,
794    NilTag = 106,
795
796    %% Rewrite the map to a list before decoding to preserve the order
797    %% the map elements.
798    <<131,MapTag,Size:32,Bin0/binary>> = MapBin,
799    ListBin = <<131,ListTag,(2*Size):32,Bin0/binary,NilTag>>,
800    List = binary_to_term(ListBin),
801    decode_ext_map_1(List).
802
803decode_ext_map_1([Key,Val|T]) ->
804    [{Key,Val}|decode_ext_map_1(T)];
805decode_ext_map_1([]) -> [].
806
807make_map(N) ->
808    maps:from_list([{I,I*I} || I <- lists:seq(1, N)]).
809
810random_term() ->
811    case rand:uniform(11) of
812        1 ->
813            list_to_atom(integer_to_list(36#aaaa + rand:uniform(100) * 23, 36));
814        2 ->
815            rand:uniform();
816        3 ->
817            rand:uniform(10000000);
818        4 ->
819            (1 bsl rand:uniform(128)) + rand:uniform(10000000);
820        5 ->
821            self();
822        6 ->
823            make_ref();
824        7 ->
825            random_list();
826        8 ->
827            list_to_tuple(random_list());
828        9 ->
829            [];
830        10 ->
831            make_map(33);
832        11 ->
833            make_map(rand:uniform(10))
834    end.
835
836random_list() ->
837    [random_term() || _ <- lists:seq(1, rand:uniform(10)-1)].
838
839external_size(Config) when is_list(Config) ->
840    %% Build a term whose external size only fits in a big num (on 32-bit CPU).
841    external_size_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF),
842
843    %% Test that the same binary aligned and unaligned has the same external size.
844    Bin = iolist_to_binary([1,2,3,96]),
845    Unaligned = make_unaligned_sub_binary(Bin),
846    case {erlang:external_size(Bin),erlang:external_size(Unaligned)} of
847	{X,X} -> ok;
848	{Sz1,Sz2} ->
849	    ct:fail("  Aligned size: ~p\n"
850                    "Unaligned size: ~p\n", [Sz1,Sz2])
851    end,
852    true = (erlang:external_size(Bin) =:= erlang:external_size(Bin, [{minor_version, 1}])),
853    true = (erlang:external_size(Unaligned) =:= erlang:external_size(Unaligned, [{minor_version, 1}])).
854
855external_size_1(Term, Size0, Limit) when Size0 < Limit ->
856    case erlang:external_size(Term) of
857	Size when is_integer(Size), Size0 < Size ->
858	    io:format("~p", [Size]),
859	    external_size_1([Term|Term], Size, Limit)
860    end;
861external_size_1(_, _, _) -> ok.
862
863t_iolist_size(Config) when is_list(Config) ->
864    _ = rand:uniform(),				%Seed generator
865    io:format("Seed: ~p", [rand:export_seed()]),
866
867    Base = <<0:(1 bsl 20)/unit:8>>,
868    Powers = [1 bsl N || N <- lists:seq(2, 37)],
869    Sizes0 = [[N - rand:uniform(N div 2),
870	       lists:seq(N-2, N+2),
871	       N+N div 2,
872	       N + rand:uniform(N div 2)] ||
873		 N <- Powers],
874
875    %% Test sizes around 1^32 more thoroughly.
876    FourGigs = 1 bsl 32,
877    Sizes1 = [FourGigs+N || N <- lists:seq(-8, 40)] ++ Sizes0,
878    Sizes2 = lists:flatten(Sizes1),
879    Sizes = lists:usort(Sizes2),
880    io:format("~p sizes:", [length(Sizes)]),
881    io:format("~p\n", [Sizes]),
882    _ = [Sz = iolist_size(build_iolist(Sz, Base)) || Sz <- Sizes],
883    ok.
884
885build_iolist(N, Base) when N < 16 ->
886    case rand:uniform(3) of
887	1 ->
888	    <<Bin:N/binary,_/binary>> = Base,
889	    Bin;
890	_ ->
891	    lists:seq(1, N)
892    end;
893build_iolist(N, Base) when N =< byte_size(Base) ->
894    case rand:uniform(3) of
895	1 ->
896	    <<Bin:N/binary,_/binary>> = Base,
897	    Bin;
898	2 ->
899	    <<Bin:N/binary,_/binary>> = Base,
900	    [Bin];
901	3 ->
902	    case N rem 2 of
903		0 ->
904		    L = build_iolist(N div 2, Base),
905		    [L,L];
906		1 ->
907		    L = build_iolist(N div 2, Base),
908		    [L,L,45]
909	    end
910    end;
911build_iolist(N0, Base) ->
912    Small = rand:uniform(15),
913    Seq = lists:seq(1, Small),
914    N = N0 - Small,
915    case N rem 2 of
916	0 ->
917	    L = build_iolist(N div 2, Base),
918	    [L,L|Seq];
919	1 ->
920	    L = build_iolist(N div 2, Base),
921	    [47,L,L|Seq]
922    end.
923
924approx_4GB_bin() ->
925    Bin = lists:duplicate(4194304, 255),
926    BinRet = erlang:iolist_to_binary(lists:duplicate(1124, Bin)),
927    BinRet.
928
929duplicate_iolist(IOList, 0) ->
930    IOList;
931duplicate_iolist(IOList, NrOfTimes) ->
932    duplicate_iolist([IOList, IOList], NrOfTimes - 1).
933
934t_iolist_size_huge_list(Config)  when is_list(Config) ->
935    run_when_enough_resources(
936      fun() ->
937              {TimeToCreateIOList, IOList} = timer:tc(fun()->duplicate_iolist(approx_4GB_bin(), 32) end),
938              {IOListSizeTime, CalculatedSize} = timer:tc(fun()->erlang:iolist_size(IOList) end),
939              20248183924657750016 = CalculatedSize,
940              {comment, io_lib:format("Time to create iolist: ~f s. Time to calculate size: ~f s.",
941                                      [TimeToCreateIOList / 1000000, IOListSizeTime / 1000000])}
942      end).
943
944t_iolist_size_huge_bad_arg_list(Config)  when is_list(Config) ->
945    run_when_enough_resources(
946      fun() ->
947              P = self(),
948              spawn_link(fun()-> IOListTmp = duplicate_iolist(approx_4GB_bin(), 32),
949                                 IOList = [IOListTmp, [badarg]],
950                                 {'EXIT',{badarg,_}} = (catch erlang:iolist_size(IOList)),
951                                 P ! ok
952                         end),
953              receive ok -> ok end
954         end).
955
956%% iolist_size tests for shallow lists
957
958t_iolist_size_shallow_trapping(Config) when is_list(Config) ->
959    Lengths = [2000, 20000, 200000, 200000, 2000000, 20000000],
960    run_iolist_size_test_and_benchmark(Lengths, fun make_shallow_iolist/2).
961
962t_iolist_size_shallow_short_lists(Config) when is_list(Config) ->
963    Lengths = lists:duplicate(15000, 300),
964    run_iolist_size_test_and_benchmark(Lengths, fun make_shallow_iolist/2).
965
966t_iolist_size_shallow_tiny_lists(Config) when is_list(Config) ->
967    Lengths = lists:duplicate(250000, 18),
968    run_iolist_size_test_and_benchmark(Lengths, fun make_shallow_iolist/2).
969
970make_shallow_iolist(SizeDiv2, LastItem) ->
971    lists:map(
972      fun(I) ->
973              case I of
974                  SizeDiv2 -> [1, LastItem];
975                  _ -> [1, 1]
976              end
977      end,
978      lists:seq(1, SizeDiv2)).
979
980%% iolist_size tests for deep lists
981
982t_iolist_size_deep_trapping(Config) when is_list(Config) ->
983    Lengths = [2000, 20000, 200000, 200000, 2000000, 10000000],
984    run_iolist_size_test_and_benchmark(Lengths, fun make_deep_iolist/2).
985
986t_iolist_size_deep_short_lists(Config) when is_list(Config) ->
987    Lengths = lists:duplicate(10000, 300),
988    run_iolist_size_test_and_benchmark(Lengths, fun make_deep_iolist/2).
989
990t_iolist_size_deep_tiny_lists(Config) when is_list(Config) ->
991    Lengths = lists:duplicate(150000, 18),
992    run_iolist_size_test_and_benchmark(Lengths, fun make_deep_iolist/2).
993
994make_deep_iolist(1, LastItem) ->
995    [1, LastItem];
996make_deep_iolist(Depth, LastItem) ->
997    [[1, 1], make_deep_iolist(Depth - 1, LastItem)].
998
999% Helper functions for iolist_size tests
1000
1001run_iolist_size_test_and_benchmark(Lengths, ListGenerator) ->
1002    run_when_enough_resources(
1003      fun() ->
1004              GoodListsWithSizes =
1005                  lists:map(fun(Length) -> {Length*2, ListGenerator(Length, 1)} end, Lengths),
1006              BadListsWithSizes =
1007                  lists:map(fun(Length) -> {Length*2, ListGenerator(Length, bad)} end, Lengths),
1008              erlang:garbage_collect(),
1009              report_throughput(
1010                fun() ->
1011                        lists:foreach(
1012                          fun(_)->
1013                                  lists:foreach(
1014                                    fun({Size, List}) -> Size = iolist_size(List) end,
1015                                    GoodListsWithSizes),
1016                                  lists:foreach(
1017                                    fun({_, List}) -> {'EXIT',_} = (catch (iolist_size(List))) end,
1018                                    BadListsWithSizes)
1019                          end,
1020                          lists:seq(1,3))
1021                end,
1022                lists:sum(Lengths)*4)
1023      end).
1024
1025report_throughput(Fun, NrOfItems) ->
1026    Parent = self(),
1027    spawn(fun() -> Parent ! timer:tc(Fun) end),
1028    {Time, _} = receive D -> D end,
1029    ItemsPerMicrosecond = NrOfItems / Time,
1030    ct_event:notify(#event{ name = benchmark_data, data = [{value, ItemsPerMicrosecond}]}),
1031    {comment, io_lib:format("Items per microsecond: ~p, Nr of items: ~p, Benchmark time: ~p seconds)",
1032                            [ItemsPerMicrosecond, NrOfItems, Time/1000000])}.
1033
1034total_memory() ->
1035    %% Total memory in GB.
1036    try
1037	MemoryData = memsup:get_system_memory_data(),
1038	case lists:keysearch(total_memory, 1, MemoryData) of
1039	    {value, {total_memory, TM}} ->
1040		TM div (1024*1024*1024);
1041	    false ->
1042		{value, {system_total_memory, STM}} =
1043		    lists:keysearch(system_total_memory, 1, MemoryData),
1044		STM div (1024*1024*1024)
1045	end
1046    catch
1047	_ : _ ->
1048	    undefined
1049    end.
1050
1051run_when_enough_resources(Fun) ->
1052    case {total_memory(), erlang:system_info(wordsize)} of
1053        {Mem, 8} when is_integer(Mem) andalso Mem >= 15 ->
1054            Fun();
1055        {Mem, WordSize} ->
1056            {skipped,
1057             io_lib:format("Not enough resources (System Memory >= ~p, Word Size = ~p)",
1058                           [Mem, WordSize])}
1059    end.
1060
1061
1062%% OTP-4053
1063bad_binary_to_term_2(Config) when is_list(Config) ->
1064    {ok, N} = test_server:start_node(plopp, slave, []),
1065    R = rpc:call(N, erlang, binary_to_term, [<<131,111,255,255,255,0>>]),
1066    case R of
1067	      {badrpc, {'EXIT', _}} ->
1068		  ok;
1069	      _Other ->
1070		  ct:fail({rpcresult, R})
1071	  end,
1072    test_server:stop_node(N),
1073    ok.
1074
1075%% Try bad input to binary_to_term/1.
1076bad_binary_to_term(Config) when is_list(Config) ->
1077    bad_bin_to_term(an_atom),
1078    bad_bin_to_term({an,tuple}),
1079    bad_bin_to_term({a,list}),
1080    bad_bin_to_term(fun() -> self() end),
1081    bad_bin_to_term(fun(X) -> 42*X end),
1082    bad_bin_to_term(fun(X, Y) -> {X,Y} end),
1083    bad_bin_to_term(fun(X, Y, Z) -> {X,Y,Z} end),
1084    bad_bin_to_term(bit_sized_binary(term_to_binary({you,should,'not',see,this,term}))),
1085
1086    %% Bad float.
1087    bad_bin_to_term(<<131,70,-1:64>>),
1088
1089    %% Truncated UTF8 character (ERL-474)
1090    bad_bin_to_term(<<131,119,1,194,163>>),
1091    ok.
1092
1093bad_bin_to_term(BadBin) ->
1094    {'EXIT',{badarg,_}} = (catch binary_to_term_stress(BadBin)).
1095
1096bad_bin_to_term(BadBin,Opts) ->
1097    {'EXIT',{badarg,_}} = (catch binary_to_term_stress(BadBin,Opts)).
1098
1099%% Test safety options for binary_to_term/2
1100safe_binary_to_term2(Config) when is_list(Config) ->
1101    bad_bin_to_term(<<131,100,0,14,"undefined_atom">>, [safe]),
1102    bad_bin_to_term(<<131,100,0,14,"other_bad_atom">>, [safe]),
1103    BadHostAtom = <<100,0,14,"badguy@badhost">>,
1104    Empty = <<0,0,0,0>>,
1105    BadRef = <<131,114,0,3,BadHostAtom/binary,0,<<0,0,0,255>>/binary,
1106	      Empty/binary,Empty/binary>>,
1107    bad_bin_to_term(BadRef, [safe]), % good ref, with a bad atom
1108    fullsweep_after = binary_to_term_stress(<<131,100,0,15,"fullsweep_after">>, [safe]), % should be a good atom
1109    BadExtFun = <<131,113,100,0,4,98,108,117,101,100,0,4,109,111,111,110,97,3>>,
1110    bad_bin_to_term(BadExtFun, [safe]),
1111    ok.
1112
1113%% Tests bad input to binary_to_term/1.
1114
1115bad_terms(Config) when is_list(Config) ->
1116    test_terms(fun corrupter/1),
1117    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,0,11,22,33>>)),
1118    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,9,11,22,33>>)),
1119    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,0:32,1,11,22,33>>)),
1120    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,-1:32,1,11,22,33>>)),
1121    ok.
1122
1123corrupter(Term) ->
1124    try
1125	      S = io_lib:format("About to corrupt: ~P", [Term,12]),
1126	      io:put_chars(S)
1127	  catch
1128	      error:badarg ->
1129		  io:format("About to corrupt: <<bit-level-binary:~p",
1130			    [bit_size(Term)])
1131	  end,
1132    Bin = term_to_binary(Term),
1133    corrupter(Bin, size(Bin)-1),
1134    CompressedBin = term_to_binary(Term, [compressed]),
1135    corrupter(CompressedBin, size(CompressedBin)-1).
1136
1137corrupter(Bin, Pos) when Pos >= 0 ->
1138    {ShorterBin, Rest} = split_binary(Bin, Pos),
1139    catch binary_to_term_stress(ShorterBin), %% emulator shouldn't crash
1140    MovedBin = list_to_binary([ShorterBin]),
1141    catch binary_to_term_stress(MovedBin), %% emulator shouldn't crash
1142
1143    %% Bit faults, shouldn't crash
1144    <<Byte,Tail/binary>> = Rest,
1145    Fun = fun(M) -> FaultyByte = Byte bxor M,
1146		    catch binary_to_term_stress(<<ShorterBin/binary,
1147					  FaultyByte, Tail/binary>>) end,
1148    lists:foreach(Fun,[1,2,4,8,16,32,64,128,255]),
1149    corrupter(Bin, Pos-1);
1150corrupter(_Bin, _) ->
1151    ok.
1152
1153more_bad_terms(Config) when is_list(Config) ->
1154    Data = proplists:get_value(data_dir, Config),
1155    BadFile = filename:join(Data, "bad_binary"),
1156    ok = io:format("File: ~s\n", [BadFile]),
1157    case file:read_file(BadFile) of
1158	      {ok,Bin} ->
1159		  {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin)),
1160		  ok;
1161	      Other ->
1162		  ct:fail(Other)
1163	  end.
1164
1165otp_5484(Config) when is_list(Config) ->
1166    {'EXIT',_} =
1167	(catch
1168	     binary_to_term_stress(
1169	       <<131,
1170		104,2,				%Tuple, 2 elements
1171		103,				%Pid
1172		100,0,20,"wslin1427198@wslin14",
1173		%% Obviously bad values follow.
1174		255,255,255,255,
1175		255,255,255,255,
1176		255,
1177		106>>)),
1178
1179    {'EXIT',_} =
1180	(catch
1181	     binary_to_term_stress(
1182	       <<131,
1183		104,2,				%Tuple, 2 elements
1184		103,				%Pid
1185		106,				%[] instead of atom.
1186		0,0,0,17,
1187		0,0,0,135,
1188		2,
1189		106>>)),
1190
1191    {'EXIT',_} =
1192	(catch
1193	     binary_to_term_stress(
1194	       %% A old-type fun in a list containing a bad creator pid.
1195	       <<131,108,0,0,0,1,117,0,0,0,0,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,255,255,0,25,255,0,0,0,0,100,0,1,116,97,0,98,6,142,121,72,106>>)),
1196
1197    {'EXIT',_} =
1198	(catch
1199	     binary_to_term_stress(
1200	       %% A new-type fun in a list containing a bad creator pid.
1201	       %%
1202	       <<131,
1203		108,0,0,0,1,			%List, 1 element
1204		112,0,0,0,66,0,52,216,81,158,148,250,237,109,185,9,208,60,202,156,244,218,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,6,142,121,72,
1205		103,				%Pid.
1206		106,				%[] instead of an atom.
1207		0,0,0,27,0,0,0,0,0,106>>)),
1208
1209    {'EXIT',_} =
1210	(catch
1211	     binary_to_term_stress(
1212	       %% A new-type fun in a list containing a bad module.
1213	       <<131,
1214		108,0,0,0,1,			%List, 1 element
1215		112,0,0,0,70,0,224,90,4,101,48,28,110,228,153,48,239,169,232,77,108,145,0,0,0,0,0,0,0,2,
1216		%%100,0,1,116,
1217		107,0,1,64,			%String instead of atom (same length).
1218		97,0,98,6,64,82,230,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)),
1219
1220    {'EXIT',_} =
1221	(catch
1222	     binary_to_term_stress(
1223	       %% A new-type fun in a list containing a bad index.
1224	       <<131,
1225		108,0,0,0,1,			%List, 1 element
1226		112,0,0,0,70,0,224,90,4,101,48,28,110,228,153,48,239,169,232,77,108,145,0,0,0,0,0,0,0,2,
1227		100,0,1,116,
1228		%%97,0,				%Integer: 0.
1229		104,0,				%Tuple {} instead of integer.
1230		98,6,64,82,230,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)),
1231
1232    {'EXIT',_} =
1233	(catch
1234	     binary_to_term_stress(
1235	       %% A new-type fun in a list containing a bad unique value.
1236	       <<131,
1237		108,0,0,0,1,			%List, 1 element
1238		112,0,0,0,70,0,224,90,4,101,48,28,110,228,153,48,239,169,232,77,108,145,0,0,0,0,0,0,0,2,
1239		100,0,1,116,
1240		97,0,				%Integer: 0.
1241		%%98,6,64,82,230,		%Integer.
1242		100,0,2,64,65,			%Atom instead of integer.
1243		103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)),
1244
1245    %% An absurdly large atom.
1246    {'EXIT',_} =
1247	(catch binary_to_term_stress(iolist_to_binary([<<131,100,65000:16>>|
1248						lists:duplicate(65000, 42)]))),
1249
1250    %% Longer than 255 characters.
1251    {'EXIT',_} =
1252	(catch binary_to_term_stress(iolist_to_binary([<<131,100,256:16>>|
1253						lists:duplicate(256, 42)]))),
1254
1255    %% OTP-7218. Thanks to Matthew Dempsky. Also make sure that we
1256    %% cover the other error cases for external funs (EXPORT_EXT).
1257    {'EXIT',_} =
1258	(catch binary_to_term_stress(
1259		 <<131,
1260		  113,				%EXPORT_EXP
1261		  97,13,			%Integer: 13
1262		  97,13,			%Integer: 13
1263		  97,13>>)),			%Integer: 13
1264    {'EXIT',_} =
1265	(catch binary_to_term_stress(
1266		 <<131,
1267		  113,				%EXPORT_EXP
1268		  100,0,1,64,			%Atom: '@'
1269		  97,13,			%Integer: 13
1270		  97,13>>)),			%Integer: 13
1271    {'EXIT',_} =
1272	(catch binary_to_term_stress(
1273		 <<131,
1274		  113,				%EXPORT_EXP
1275		  100,0,1,64,			%Atom: '@'
1276		  100,0,1,64,			%Atom: '@'
1277		  106>>)),			%NIL
1278    {'EXIT',_} =
1279	(catch binary_to_term_stress(
1280		 <<131,
1281		  113,				%EXPORT_EXP
1282		  100,0,1,64,			%Atom: '@'
1283		  100,0,1,64,			%Atom: '@'
1284		  98,255,255,255,255>>)),	%Integer: -1
1285    {'EXIT',_} =
1286	(catch binary_to_term_stress(
1287		 <<131,
1288		  113,				%EXPORT_EXP
1289		  100,0,1,64,			%Atom: '@'
1290		  100,0,1,64,			%Atom: '@'
1291		  113,97,13,97,13,97,13>>)),	%fun 13:13/13
1292
1293    %% Bad funs.
1294    {'EXIT',_} = (catch binary_to_term_stress(fake_fun(0, lists:seq(0, 256)))),
1295    ok.
1296
1297fake_fun(Arity, Env0) ->
1298    Uniq = erlang:md5([]),
1299    Index = 0,
1300    NumFree = length(Env0),
1301    Mod = list_to_binary(?MODULE_STRING),
1302    OldIndex = 0,
1303    OldUniq = 16#123456,
1304    <<131,Pid/binary>> = term_to_binary(self()),
1305    Env1 = [term_to_binary(Term) || Term <- Env0],
1306    Env = << <<Bin/binary>> || <<131,Bin/binary>> <- Env1 >>,
1307    B = <<Arity,Uniq/binary,Index:32,NumFree:32,
1308	 $d,(byte_size(Mod)):16,Mod/binary,	%Module.
1309	 $a,OldIndex:8,
1310	 $b,OldUniq:32,
1311	 Pid/binary,Env/binary>>,
1312    <<131,$p,(byte_size(B)+4):32,B/binary>>.
1313
1314
1315%% More bad terms submitted by Matthias Lang.
1316otp_5933(Config) when is_list(Config) ->
1317    try_bad_lengths(<<131,$m>>),		%binary
1318    try_bad_lengths(<<131,$n>>),		%bignum
1319    try_bad_lengths(<<131,$o>>),		%huge bignum
1320    ok.
1321
1322try_bad_lengths(B) ->
1323    try_bad_lengths(B, 16#FFFFFFFF).
1324
1325try_bad_lengths(B, L) when L > 16#FFFFFFF0 ->
1326    Bin = <<B/binary,L:32>>,
1327    io:format("~p\n", [Bin]),
1328    {'EXIT',_} = (catch binary_to_term_stress(Bin)),
1329    try_bad_lengths(B, L-1);
1330try_bad_lengths(_, _) -> ok.
1331
1332
1333otp_6817(Config) when is_list(Config) ->
1334    process_flag(min_heap_size, 20000),		%Use the heap, not heap fragments.
1335
1336    %% Floats are only validated when the heap fragment has been allocated.
1337    BadFloat = <<131,99,53,46,48,$X,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,101,45,48,49,0,0,0,0,0>>,
1338    otp_6817_try_bin(BadFloat),
1339
1340    %% {Binary,BadFloat}: When the error in float is discovered, a refc-binary
1341    %% has been allocated and the list of refc-binaries goes through the
1342    %% limbo area between the heap top and stack.
1343    BinAndFloat =
1344	<<131,104,2,109,0,0,1,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
1345	 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,
1346	 46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,
1347	 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
1348	 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,
1349	 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
1350	 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
1351	 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,
1352	 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
1353	 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
1354	 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
1355	 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,
1356	 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48,
1357	 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>,
1358    otp_6817_try_bin(BinAndFloat),
1359
1360    %% {Fun,BadFloat}
1361    FunAndFloat =
1362	<<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84,
1363	 71,8,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,5,175,169,123,103,100,0,13,110,111,
1364	 110,111,100,101,64,110,111,104,111,115,116,0,0,0,41,0,0,0,0,0,99,50,46,55,48,
1365	 $Y,57,57,57,57,57,57,57,57,57,57,57,57,57,54,52,52,55,101,43,48,48,0,0,0,0,0>>,
1366    otp_6817_try_bin(FunAndFloat),
1367
1368    %% [ExternalPid|BadFloat]
1369    ExtPidAndFloat =
1370	<<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101,
1371	 114,0,0,0,36,0,0,0,0,2,99,48,46,$@,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
1372	 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>,
1373    otp_6817_try_bin(ExtPidAndFloat),
1374    ok.
1375
1376otp_6817_try_bin(Bin) ->
1377    erlang:garbage_collect(),
1378
1379    %% If the bug is present, the heap pointer will moved when the invalid term
1380    %% is found and we will have a linked list passing through the limbo area
1381    %% between the heap top and the stack pointer.
1382    catch binary_to_term_stress(Bin),
1383
1384    %% If the bug is present, we will overwrite the pointers in the limbo area.
1385    Filler = erlang:make_tuple(1024, 16#3FA),
1386    id(Filler),
1387
1388    %% Will crash if the bug is present.
1389    erlang:garbage_collect().
1390
1391%% Some bugs in binary_to_term when 32-bit integers are negative.
1392otp_8117(Config) when is_list(Config) ->
1393    [otp_8117_do(Op,-(1 bsl N)) || Op <- ['fun',named_fun,list,tuple],
1394				   N <- lists:seq(0,31)],
1395    ok.
1396
1397otp_8117_do('fun',Neg) ->
1398    % Fun with negative num_free
1399    FunBin = term_to_binary(fun() -> ok end),
1400    <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
1401    bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
1402otp_8117_do(named_fun,Neg) ->
1403    % Named fun with negative num_free
1404    FunBin = term_to_binary(fun F() -> F end),
1405    <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
1406    bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
1407otp_8117_do(list,Neg) ->
1408    %% List with negative length
1409    bad_bin_to_term(<<131,104,2,108,Neg:32,97,11,104,1,97,12,97,13,106,97,14>>);
1410otp_8117_do(tuple,Neg) ->
1411    %% Tuple with negative arity
1412    bad_bin_to_term(<<131,104,2,105,Neg:32,97,11,97,12,97,13,97,14>>).
1413
1414
1415%% Tests ordering of binaries.
1416ordering(Config) when is_list(Config) ->
1417    B1 = list_to_binary([7,8,9]),
1418    B2 = make_sub_binary([1,2,3,4]),
1419    B3 = list_to_binary([1,2,3,5]),
1420    Unaligned = make_unaligned_sub_binary(B2),
1421
1422    %% From R8 binaries are compared as strings.
1423
1424    false = B1 == B2,
1425    false = B1 =:= B2,
1426    true = B1 /= B2,
1427    true = B1 =/= B2,
1428
1429    true = B1 > B2,
1430    true = B2 < B3,
1431    true = B2 =< B1,
1432    true = B2 =< B3,
1433
1434    true = B2 =:= Unaligned,
1435    true = B2 == Unaligned,
1436    true = Unaligned < B3,
1437    true = Unaligned =< B3,
1438
1439    %% Binaries are greater than all other terms.
1440
1441    true = B1 > 0,
1442    true = B1 > 39827491247298471289473333333333333333333333333333,
1443    true = B1 > -3489274937438742190467869234328742398347,
1444    true = B1 > 3.14,
1445    true = B1 > [],
1446    true = B1 > [a],
1447    true = B1 > {a},
1448    true = B1 > self(),
1449    true = B1 > make_ref(),
1450    true = B1 > xxx,
1451    true = B1 > fun() -> 1 end,
1452    true = B1 > fun erlang:send/2,
1453
1454    Path = proplists:get_value(priv_dir, Config),
1455    AFile = filename:join(Path, "vanilla_file"),
1456    Port = open_port(AFile, [out]),
1457    true = B1 > Port,
1458
1459    true = B1 >= 0,
1460    true = B1 >= 39827491247298471289473333333333333333333333333333,
1461    true = B1 >= -3489274937438742190467869234328742398347,
1462    true = B1 >= 3.14,
1463    true = B1 >= [],
1464    true = B1 >= [a],
1465    true = B1 >= {a},
1466    true = B1 >= self(),
1467    true = B1 >= make_ref(),
1468    true = B1 >= xxx,
1469    true = B1 >= fun() -> 1 end,
1470    true = B1 >= fun erlang:send/2,
1471    true = B1 >= Port,
1472
1473    ok.
1474
1475%% Test that comparison between binaries with different alignment work.
1476unaligned_order(Config) when is_list(Config) ->
1477    L = lists:seq(0, 7),
1478    [test_unaligned_order(I, J) || I <- L, J <- L],
1479    ok.
1480
1481test_unaligned_order(I, J) ->
1482    Align = {I,J},
1483    io:format("~p ~p", [I,J]),
1484    true = test_unaligned_order_1('=:=', <<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
1485					<<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
1486					Align),
1487    false = test_unaligned_order_1('=/=', <<1,2,3>>, <<1,2,3>>, Align),
1488    true = test_unaligned_order_1('==', <<4,5,6>>, <<4,5,6>>, Align),
1489    false = test_unaligned_order_1('/=', <<1,2,3>>, <<1,2,3>>, Align),
1490
1491    true = test_unaligned_order_1('<', <<1,2>>, <<1,2,3>>, Align),
1492    true = test_unaligned_order_1('=<', <<1,2>>, <<1,2,3>>, Align),
1493    true = test_unaligned_order_1('=<', <<1,2,7,8>>, <<1,2,7,8>>, Align),
1494    ok.
1495
1496test_unaligned_order_1(Op, A, B, {Aa,Ba}) ->
1497    erlang:Op(unaligned_sub_bin(A, Aa), unaligned_sub_bin(B, Ba)).
1498
1499test_terms(Test_Func) ->
1500    Test_Func(atom),
1501    Test_Func(''),
1502    Test_Func('a'),
1503    Test_Func('ab'),
1504    Test_Func('abc'),
1505    Test_Func('abcd'),
1506    Test_Func('abcde'),
1507    Test_Func('abcdef'),
1508    Test_Func('abcdefg'),
1509    Test_Func('abcdefgh'),
1510
1511    Test_Func(fun() -> ok end),
1512    X = id([a,{b,c},c]),
1513    Y = id({x,y,z}),
1514    Z = id(1 bsl 8*257),
1515    Test_Func(fun() -> X end),
1516    Test_Func(fun() -> {X,Y} end),
1517    Test_Func([fun() -> {X,Y,Z} end,
1518		     fun() -> {Z,X,Y} end,
1519		     fun() -> {Y,Z,X} end]),
1520
1521    Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}),
1522    Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}},
1523		     {1,2,3}}),
1524
1525    Test_Func(1),
1526    Test_Func(42),
1527    Test_Func(-23),
1528    Test_Func(256),
1529    Test_Func(25555),
1530    Test_Func(-3333),
1531
1532    Test_Func(1.0),
1533
1534    Test_Func(183749783987483978498378478393874),
1535    Test_Func(-37894183749783987483978498378478393874),
1536    Very_Big = very_big_num(),
1537    Test_Func(Very_Big),
1538    Test_Func(-Very_Big+1),
1539
1540    Test_Func([]),
1541    Test_Func("abcdef"),
1542    Test_Func([a, b, 1, 2]),
1543    Test_Func([a|b]),
1544
1545    Test_Func({}),
1546    Test_Func({1}),
1547    Test_Func({a, b}),
1548    Test_Func({a, b, c}),
1549    Test_Func(list_to_tuple(lists:seq(0, 255))),
1550    Test_Func(list_to_tuple(lists:seq(0, 256))),
1551
1552    Test_Func(make_ref()),
1553    Test_Func([make_ref(), make_ref()]),
1554
1555    Test_Func(make_port()),
1556
1557    Test_Func(make_pid()),
1558
1559    Test_Func(Bin0 = list_to_binary(lists:seq(0, 14))),
1560    Test_Func(Bin1 = list_to_binary(lists:seq(0, ?heap_binary_size))),
1561    Test_Func(Bin2 = list_to_binary(lists:seq(0, ?heap_binary_size+1))),
1562    Test_Func(Bin3 = list_to_binary(lists:seq(0, 255))),
1563
1564    Test_Func(make_unaligned_sub_binary(Bin0)),
1565    Test_Func(make_unaligned_sub_binary(Bin1)),
1566    Test_Func(make_unaligned_sub_binary(Bin2)),
1567    Test_Func(make_unaligned_sub_binary(Bin3)),
1568
1569    Test_Func(make_sub_binary(lists:seq(42, 43))),
1570    Test_Func(make_sub_binary([42,43,44])),
1571    Test_Func(make_sub_binary([42,43,44,45])),
1572    Test_Func(make_sub_binary([42,43,44,45,46])),
1573    Test_Func(make_sub_binary([42,43,44,45,46,47])),
1574    Test_Func(make_sub_binary([42,43,44,45,46,47,48])),
1575    Test_Func(make_sub_binary(lists:seq(42, 49))),
1576    Test_Func(make_sub_binary(lists:seq(0, 14))),
1577    Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))),
1578    Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))),
1579    Test_Func(make_sub_binary(lists:seq(0, 255))),
1580
1581    Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))),
1582    Test_Func(make_unaligned_sub_binary([42,43,44])),
1583    Test_Func(make_unaligned_sub_binary([42,43,44,45])),
1584    Test_Func(make_unaligned_sub_binary([42,43,44,45,46])),
1585    Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])),
1586    Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])),
1587    Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))),
1588    Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))),
1589    Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))),
1590    Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))),
1591    Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))),
1592
1593    %% Bit level binaries.
1594    Test_Func(<<1:1>>),
1595    Test_Func(<<2:2>>),
1596    Test_Func(<<42:10>>),
1597    Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
1598
1599    Test_Func(F = fun(A) -> 42*A end),
1600    Test_Func(lists:duplicate(32, F)),
1601
1602    Test_Func(FF = fun binary_SUITE:all/0),
1603    Test_Func(lists:duplicate(32, FF)),
1604
1605    %% Maps.
1606    SmallMap = #{a => 1, b => 2, c => 3},
1607    LargeMap1 = maps:from_list([{list_to_atom(integer_to_list(36#cafe+N*N*N, 36)),N} ||
1608                                   N <- lists:seq(1, 33)]),
1609    LargeMap2 = maps:from_list([{list_to_atom(integer_to_list(36#dead+N, 36)),N} ||
1610                                   N <- lists:seq(1, 50)]),
1611    MapWithMap = LargeMap1#{SmallMap => a, LargeMap1 => LargeMap2, LargeMap2 => LargeMap1,
1612                            [LargeMap1,LargeMap2] => LargeMap1,
1613                            <<"abc">> => SmallMap, <<"qrs">> => LargeMap1,
1614                            <<"xyz">> => LargeMap2 },
1615    Test_Func(#{}),
1616    Test_Func(SmallMap),
1617    Test_Func(LargeMap1),
1618    Test_Func(LargeMap2),
1619    Test_Func(MapWithMap),
1620
1621    ok.
1622
1623test_floats(Test_Func) ->
1624    Test_Func(5.5),
1625    Test_Func(-15.32),
1626    Test_Func(1.2435e25),
1627    Test_Func(1.2333e-20),
1628    Test_Func(199.0e+15),
1629    ok.
1630
1631very_big_num() ->
1632    very_big_num(33, 1).
1633
1634very_big_num(Left, Result) when Left > 0 ->
1635    very_big_num(Left-1, Result*256);
1636very_big_num(0, Result) ->
1637    Result.
1638
1639make_port() ->
1640    hd(erlang:ports()).
1641
1642make_pid() ->
1643    spawn_link(?MODULE, sleeper, []).
1644
1645sleeper() ->
1646    receive after infinity -> ok end.
1647
1648
1649%% Test that binaries are garbage collected properly.
1650gc_test(Config) when is_list(Config) ->
1651    %% Note: This test is only relevant for REFC binaries.
1652    %% Therefore, we take care that all binaries are REFC binaries.
1653    true = 192 > ?heap_binary_size,
1654    B = list_to_binary(lists:seq(1, 192)),
1655    Self = self(),
1656    F1 = fun() ->
1657		 gc(),
1658		 {binary,[]} = process_info(self(), binary),
1659		 Self ! {self(),done}
1660	 end,
1661    F = fun() ->
1662		receive go -> ok end,
1663		{binary,[{_,192,1}]} = process_info(self(), binary),
1664		gc(),
1665		{B1,B2} = my_split_binary(B, 68),
1666		gc(),
1667		gc(),
1668		{binary,L1} = process_info(self(), binary),
1669		[Binfo1,Binfo2,Binfo3] = L1,
1670		{_,192,3} = Binfo1 = Binfo2 = Binfo3,
1671		192 = size(B),
1672		68 = size(B1),
1673		124 = size(B2),
1674		F1()
1675	end,
1676    gc(),
1677    gc(),
1678    192 = size(B),
1679    gc_test1(spawn_opt(erlang, apply, [F,[]], [link,{fullsweep_after,0}])).
1680
1681gc_test1(Pid) ->
1682    gc(),
1683    Pid ! go,
1684    receive
1685	{Pid,done} -> ok
1686    after 10000 ->
1687	    ct:fail("timeout")
1688    end.
1689
1690%% Like split binary, but returns REFC binaries. Only useful for gc_test/1.
1691
1692my_split_binary(B, Pos) ->
1693    Self = self(),
1694    Ref = make_ref(),
1695    spawn(fun() -> Self ! {Ref,split_binary(B, Pos)} end),
1696    receive
1697	{Ref,Result} -> Result
1698    end.
1699
1700gc() ->
1701    erlang:garbage_collect(),
1702    gc1().
1703gc1() -> ok.
1704
1705bit_sized_binary_sizes(Config) when is_list(Config) ->
1706    [bsbs_1(A) || A <- lists:seq(1, 8)],
1707    ok.
1708
1709bsbs_1(A) ->
1710    BinSize = 32+A,
1711    io:format("A: ~p BinSize: ~p", [A,BinSize]),
1712    Bin = binary_to_term_stress(<<131,$M,5:32,A,0,0,0,0,0>>),
1713    BinSize = bit_size(Bin).
1714
1715%% lists:foldl(_,_,lists:seq(_,_)) with less heap consumption
1716lists_foldl_seq(Fun, Acc0, N, To) when N =< To ->
1717    Acc1 = Fun(N, Acc0),
1718    lists_foldl_seq(Fun, Acc1, N+1, To);
1719
1720lists_foldl_seq(_, Acc, _, _) ->
1721    Acc.
1722
1723deep(Config) when is_list(Config) ->
1724    deep_roundtrip(lists_foldl_seq(fun(E, A) ->
1725					   [E,A]
1726				   end, [], 1, 1000000)),
1727    erlang:garbage_collect(),
1728    deep_roundtrip(lists_foldl_seq(fun(E, A) ->
1729					   {E,A}
1730				   end, [], 1, 1000000)),
1731    erlang:garbage_collect(),
1732    deep_roundtrip(lists_foldl_seq(fun(E, A) ->
1733					   fun() -> {E,A} end
1734				   end, [], 1, 1000000)),
1735    erlang:garbage_collect(),
1736    ok.
1737
1738deep_roundtrip(T) ->
1739    B = term_to_binary(T),
1740    T = binary_to_term(B).
1741
1742term2bin_tuple_fallbacks(Config) when is_list(Config) ->
1743    erts_debug:set_internal_state(available_internal_state, true),
1744
1745    term2bin_tf(fun ?MODULE:all/1),
1746    term2bin_tf(<<1:1>>),
1747    term2bin_tf(<<90,80:7>>),
1748
1749    erts_debug:set_internal_state(available_internal_state, false),
1750    ok.
1751
1752term2bin_tf(Term) ->
1753    Tuple = case Term of
1754                Fun when is_function(Fun) ->
1755                    {type, external} = erlang:fun_info(Fun, type),
1756                    {module,M} = erlang:fun_info(Fun, module),
1757                    {name,F} = erlang:fun_info(Fun, name),
1758                    {M,F};
1759                BS when bit_size(BS) rem 8 =/= 0 ->
1760                    Bits = bit_size(BS) rem 8,
1761                    {<<BS/bitstring, 0:(8-Bits)>>, Bits}
1762            end,
1763    Tuple = binary_to_term_stress(erts_debug:get_internal_state({term_to_binary_tuple_fallbacks,Term})).
1764
1765%% Test non-standard encodings never generated by term_to_binary/1
1766%% but recognized by binary_to_term/1.
1767
1768robustness(Config) when is_list(Config) ->
1769    [] = binary_to_term_stress(<<131,107,0,0>>),	%Empty string.
1770    [] = binary_to_term_stress(<<131,108,0,0,0,0,106>>),	%Zero-length list.
1771
1772    %% {[],a} where [] is a zero-length list.
1773    {[],a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,106,100,0,1,97>>),
1774
1775    %% {42,a} where 42 is a zero-length list with 42 in the tail.
1776    {42,a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,97,42,100,0,1,97>>),
1777
1778    %% {{x,y},a} where {x,y} is a zero-length list with {x,y} in the tail.
1779    {{x,y},a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,
1780				      104,2,100,0,1,120,100,0,1,
1781				      121,100,0,1,97>>),
1782
1783    %% Bignums fitting in 32 bits.
1784    16#7FFFFFFF = binary_to_term_stress(<<131,98,127,255,255,255>>),
1785    -1 = binary_to_term_stress(<<131,98,255,255,255,255>>),
1786
1787    ok.
1788
1789%% OTP-8180: Test several terms that have been known to crash the emulator.
1790%% (Thanks to Scott Lystig Fritchie.)
1791otp_8180(Config) when is_list(Config) ->
1792    Data = proplists:get_value(data_dir, Config),
1793    Wc = filename:join(Data, "zzz.*"),
1794    Files = filelib:wildcard(Wc),
1795    [run_otp_8180(F) || F <- Files],
1796    ok.
1797
1798run_otp_8180(Name) ->
1799    io:format("~s", [Name]),
1800    {ok,Bins} = file:consult(Name),
1801    [begin
1802	 io:format("~p\n", [Bin]),
1803	 {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin))
1804     end || Bin <- Bins],
1805    ok.
1806
1807%% Test that exit and GC during trapping term_to_binary and binary_to_term
1808%% does not crash.
1809trapping(Config) when is_list(Config)->
1810    do_trapping(5, term_to_binary,
1811		fun() -> [lists:duplicate(2000000,2000000)] end),
1812    do_trapping(5, binary_to_term,
1813		fun() -> [term_to_binary(lists:duplicate(2000000,2000000))] end),
1814    do_trapping(5, binary_to_list,
1815		fun() -> [list_to_binary(lists:duplicate(2000000,$x))] end),
1816    do_trapping(5, list_to_binary,
1817		fun() -> [lists:duplicate(2000000,$x)] end),
1818    do_trapping(5, bitstring_to_list,
1819		fun() -> [list_to_bitstring([lists:duplicate(2000000,$x),<<7:4>>])] end),
1820    do_trapping(5, list_to_bitstring,
1821		fun() -> [[lists:duplicate(2000000,$x),<<7:4>>]] end)
1822    .
1823
1824do_trapping(0, _, _) ->
1825    ok;
1826do_trapping(N, Bif, ArgFun) ->
1827    io:format("N=~p: Do ~p ~s gc.\n", [N, Bif, case N rem 2 of 0 -> "with"; 1 -> "without" end]),
1828    Pid = spawn(?MODULE,trapping_loop,[Bif, ArgFun, 1000, self()]),
1829    receive ok -> ok end,
1830    Ref = make_ref(),
1831    case N rem 2 of
1832	0 ->
1833            erlang:garbage_collect(Pid, [{async,Ref}]),
1834            receive after 1 -> ok end;
1835	1 -> void
1836    end,
1837    exit(Pid, kill),
1838    case N rem 2 of
1839	0 ->
1840            receive {garbage_collect, Ref, _} -> ok end;
1841	1 ->
1842            void
1843    end,
1844    receive after 1 -> ok end,
1845    do_trapping(N-1, Bif, ArgFun).
1846
1847trapping_loop(Bif, ArgFun, N, Pid) ->
1848    Args = ArgFun(),
1849    Pid ! ok,
1850    trapping_loop2(Bif,Args,N).
1851trapping_loop2(_,_,0) ->
1852    ok;
1853trapping_loop2(Bif,Args,N) ->
1854    apply(erlang,Bif,Args),
1855    trapping_loop2(Bif, Args, N-1).
1856
1857large(Config) when is_list(Config) ->
1858    List = lists:flatten(lists:map(fun (_) ->
1859					   [0,1,2,3,4,5,6,7,8]
1860				   end,
1861				   lists:seq(1, 131072))),
1862    Bin = list_to_binary(List),
1863    List = binary_to_list(Bin),
1864    PartList = lists:reverse(tl(tl(lists:reverse(tl(tl(List)))))),
1865    PartList = binary_to_list(Bin, 3, length(List)-2),
1866    ListBS = List ++ [<<7:4>>],
1867    ListBS = bitstring_to_list(list_to_bitstring(ListBS)),
1868    BitStr1 = list_to_bitstring(lists:duplicate(1024*1024, [<<1,5:3>>])),
1869    BitStr1 = list_to_bitstring(bitstring_to_list(BitStr1)),
1870    BitStr2 = list_to_bitstring([lists:duplicate(512*1024, [<<1,5:3>>]),
1871				Bin]),
1872    BitStr2 = list_to_bitstring(bitstring_to_list(BitStr2)),
1873    ok.
1874
1875error_after_yield(Config) when is_list(Config) ->
1876    L2BTrap = {erts_internal, list_to_binary_continue, 1},
1877    error_after_yield(badarg, erlang, list_to_binary, 1, fun () -> [[mk_list(1000000), oops]] end, L2BTrap),
1878    error_after_yield(badarg, erlang, iolist_to_binary, 1, fun () -> [[list2iolist(mk_list(1000000)), oops]] end, L2BTrap),
1879    error_after_yield(badarg, erlang, list_to_bitstring, 1, fun () -> [[list2bitstrlist(mk_list(1000000)), oops]] end, L2BTrap),
1880    error_after_yield(badarg, binary, list_to_bin, 1, fun () -> [[mk_list(1000000), oops]] end, L2BTrap),
1881
1882    B2TTrap = {erts_internal, binary_to_term_trap, 1},
1883
1884    error_after_yield(badarg, erlang, binary_to_term, 1, fun () -> [error_after_yield_bad_ext_term()] end, B2TTrap),
1885    error_after_yield(badarg, erlang, binary_to_term, 2, fun () -> [error_after_yield_bad_ext_term(), [safe]] end, B2TTrap),
1886
1887    case erlang:system_info(wordsize) of
1888	4 ->
1889	    SysLimitSz = 1 bsl 32,
1890	    error_after_yield(system_limit, erlang, list_to_binary, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap),
1891	    error_after_yield(system_limit, erlang, iolist_to_binary, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap),
1892	    error_after_yield(system_limit, erlang, list_to_bitstring, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap),
1893	    error_after_yield(system_limit, binary, list_to_bin, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap);
1894	8 ->
1895	    % Takes waaaay to long time to test system_limit on 64-bit archs...
1896	    ok
1897    end,
1898    ok.
1899
1900error_after_yield(Type, M, F, AN, AFun, TrapFunc) ->
1901    io:format("Testing ~p for ~p:~p/~p~n", [Type, M, F, AN]),
1902    Tracer = self(),
1903    {Pid, Mon} = spawn_monitor(fun () ->
1904				       A = AFun(),
1905				       try
1906					   erlang:yield(),
1907					   erlang:trace(self(),true,[running,{tracer,Tracer}]),
1908					   apply(M, F, A),
1909					   exit({unexpected_success, {M, F, A}})
1910				       catch
1911					   error:Type:Stk ->
1912					       erlang:trace(self(),false,[running,{tracer,Tracer}]),
1913					       %% We threw the exception from the native
1914					       %% function we trapped to, but we want
1915					       %% the BIF that originally was called
1916					       %% to appear in the stack trace.
1917					       [{M, F, A, _} | _] = Stk
1918				       end
1919			       end),
1920    receive
1921	{'DOWN', Mon, process, Pid, Reason} ->
1922	    normal = Reason
1923    end,
1924    TD = erlang:trace_delivered(Pid),
1925    receive
1926	{trace_delivered, Pid, TD} ->
1927	    NoYields = error_after_yield_sched(Pid, TrapFunc, 0),
1928	    io:format("No of yields: ~p~n", [NoYields]),
1929	    true =  NoYields > 2
1930    end,
1931    ok.
1932
1933error_after_yield_sched(P, TrapFunc, N) ->
1934    receive
1935	{trace, P, out, TrapFunc} ->
1936	    receive
1937		{trace, P, in, TrapFunc} ->
1938		    error_after_yield_sched(P, TrapFunc, N+1)
1939	    after 0 ->
1940		    exit(trap_sched_mismatch)
1941	    end;
1942	{trace, P, out, Func} ->
1943	    receive
1944		{trace, P, in, Func} ->
1945		    error_after_yield_sched(P, TrapFunc, N)
1946	    after 0 ->
1947		    exit(other_sched_mismatch)
1948	    end
1949    after 0 ->
1950	    N
1951    end.
1952
1953error_after_yield_bad_ext_term() ->
1954    TupleSz = 2000000,
1955    <<131, % Version magic
1956      AtomExt/binary>> = term_to_binary(an_atom_we_use_for_this),
1957    BadAtomExt = [100, %% ATOM_EXT
1958		  255, 255, % Invalid size of 65535 bytes
1959		  "oops"],
1960
1961    %% Produce a large tuple where the last element is invalid
1962    list_to_binary([131, %% Version magic
1963		    105, %% LARGE_TUPLE_EXT
1964		    <<TupleSz:32/big>>, %% Tuple size
1965		    lists:duplicate(TupleSz-1, AtomExt), %% Valid atoms
1966		    BadAtomExt]). %% Invalid atom at the end
1967
1968cmp_old_impl(Config) when is_list(Config) ->
1969    %% This test was originally a comparison with the non yielding
1970    %% implementation in R16B. Since OTP 22 we can't talk distribution with such
1971    %% old nodes (< 19). The test case it kept but compares with previous major
1972    %% version for semantic regression test.
1973    Cookie = atom_to_list(erlang:get_cookie()),
1974    Rel = (integer_to_list(list_to_integer(erlang:system_info(otp_release)) - 1)
1975           ++ "_latest"),
1976    case test_server:is_release_available(Rel) of
1977	false ->
1978	    {skipped, "No OTP "++Rel++" available"};
1979	true ->
1980	    {ok, Node} = test_server:start_node(list_to_atom(atom_to_list(?MODULE)++"_"++Rel),
1981				       peer,
1982				       [{args, " -setcookie "++Cookie},
1983					{erl, [{release, Rel}]}]),
1984
1985	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(1))]}),
1986	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(10))]}),
1987	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(100))]}),
1988	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(1000))]}),
1989	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(10000))]}),
1990	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(100000))]}),
1991	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(1000000))]}),
1992	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(10000000))]}),
1993	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list_lb(10000000))]}),
1994
1995	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(1))]}),
1996	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(10))]}),
1997	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(100))]}),
1998	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(1000))]}),
1999	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(10000))]}),
2000	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(100000))]}),
2001	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(1000000))]}),
2002	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(10000000))]}),
2003
2004	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(1))]}),
2005	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(10))]}),
2006	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(100))]}),
2007	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(1000))]}),
2008	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(10000))]}),
2009	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(100000))]}),
2010	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(1000000))]}),
2011	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(10000000))]}),
2012
2013	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1)))]}),
2014	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10)))]}),
2015	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(100)))]}),
2016	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1000)))]}),
2017	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10000)))]}),
2018	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(100000)))]}),
2019	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1000000)))]}),
2020	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10000000)))]}),
2021
2022	    test_server:stop_node(Node),
2023
2024	    ok
2025    end.
2026
2027%% OTP-16265
2028%% This testcase is mainly targeted toward --enable-sharing-preserving.
2029sub_bin_copy(Config) when is_list(Config) ->
2030    Papa = self(),
2031    Echo = spawn_link(fun() -> echo(Papa) end),
2032    HeapBin = list_to_binary(lists:seq(1,3)),
2033    sub_bin_copy_1(HeapBin, Echo),
2034    ProcBin = list_to_binary(lists:seq(1,65)),
2035    sub_bin_copy_1(ProcBin, Echo),
2036    unlink(Echo),
2037    exit(Echo, kill),
2038    ok.
2039
2040sub_bin_copy_1(RealBin, Echo) ->
2041    Bits = bit_size(RealBin) - 1,
2042    <<SubBin:Bits/bits, _/bits>> = RealBin,
2043
2044    %% Send (copy) messages consisting of combinations of both
2045    %% the SubBin and the RealBin it refers to.
2046    [begin
2047         Echo ! Combo,
2048         {_, Combo} = {Combo, receive M -> M end}
2049     end
2050     || Len <- lists:seq(2,5), Combo <- combos([RealBin, SubBin], Len)],
2051    ok.
2052
2053combos(_, 0) ->
2054    [[]];
2055combos(Elements, Len) ->
2056    [[E | C] || E <- Elements, C <- combos(Elements,Len-1)].
2057
2058echo(Papa) ->
2059    receive M -> Papa ! M end,
2060    echo(Papa).
2061
2062
2063%% Utilities.
2064
2065huge_iolist(Lim) ->
2066    Sz = 1024,
2067    huge_iolist(list_to_binary(mk_list(Sz)), Sz, Lim).
2068
2069huge_iolist(X, Sz, Lim) when Sz >= Lim ->
2070    X;
2071huge_iolist(X, Sz, Lim) ->
2072    huge_iolist([X, X], Sz*2, Lim).
2073
2074cmp_node(Node, {M, F, A}) ->
2075    ResN = rpc:call(Node, M, F, A),
2076    Res = apply(M, F, A),
2077    case ResN =:= Res of
2078        true ->
2079            ok;
2080        false ->
2081            io:format("~p: ~p~n~p: ~p~n",
2082                      [Node, ResN, node(), Res]),
2083            ct:fail(different_results)
2084    end.
2085
2086make_sub_binary(Bin) when is_binary(Bin) ->
2087    {_,B} = split_binary(list_to_binary([0,1,3,Bin]), 3),
2088    B;
2089make_sub_binary(List) ->
2090    make_sub_binary(list_to_binary(List)).
2091
2092make_unaligned_sub_binary(Bin0) when is_binary(Bin0) ->
2093    Bin1 = <<0:3,Bin0/binary,31:5>>,
2094    Sz = size(Bin0),
2095    <<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
2096    Bin;
2097make_unaligned_sub_binary(List) ->
2098    make_unaligned_sub_binary(list_to_binary(List)).
2099
2100%% Add 1 bit to the size of the binary.
2101bit_sized_binary(Bin0) ->
2102    Bin = <<Bin0/binary,1:1>>,
2103    BitSize = bit_size(Bin),
2104    BitSize = 8*size(Bin) + 1,
2105    Bin.
2106
2107unaligned_sub_bin(Bin, 0) -> Bin;
2108unaligned_sub_bin(Bin0, Offs) ->
2109    F = rand:uniform(256),
2110    Roffs = 8-Offs,
2111    Bin1 = <<F:Offs,Bin0/binary,F:Roffs>>,
2112    Sz = size(Bin0),
2113    <<_:Offs,Bin:Sz/binary,_:Roffs>> = id(Bin1),
2114    Bin.
2115
2116id(I) -> I.
2117
2118
2119%% Stress binary_to_term with different initial reductions
2120binary_to_term_stress(Bin) ->
2121    binary_to_term_stress(Bin, no_opts).
2122
2123binary_to_term_stress(Bin, Opts) ->
2124    Reds = get_reds(),
2125    T = b2t(erlang:system_info(context_reductions),
2126	    Bin, Opts, catch_binary_to_term(Bin, Opts)),
2127    set_reds(Reds),
2128    T = case Opts of
2129	    no_opts -> binary_to_term(Bin);
2130	    _ ->       binary_to_term(Bin,Opts)
2131	end.
2132
2133catch_binary_to_term(Bin, no_opts) ->
2134    try binary_to_term(Bin)
2135    catch
2136	error:badarg -> binary_to_term_throws_badarg
2137    end;
2138catch_binary_to_term(Bin, Opts) ->
2139    try binary_to_term(Bin, Opts)
2140    catch
2141	error:badarg -> binary_to_term_throws_badarg
2142    end.
2143
2144b2t(0, _Bin, _Opts, Term) ->
2145    Term;
2146b2t(Reds, Bin, Opts, Term) ->
2147    set_reds(Reds),
2148    Term = catch_binary_to_term(Bin,Opts),
2149    b2t(Reds div 3, Bin, Opts, Term).
2150
2151set_reds(Reds) ->
2152    try	erts_debug:set_internal_state(reds_left, Reds)
2153    catch
2154	error:undef ->
2155	    erts_debug:set_internal_state(available_internal_state, true),
2156	    set_reds(Reds)
2157    end.
2158
2159get_reds() ->
2160    try	erts_debug:get_internal_state(reds_left)
2161    catch
2162	error:undef ->
2163	    erts_debug:set_internal_state(available_internal_state, true),
2164	    get_reds()
2165    end.
2166
2167-define(LARGE_BIN, (512*1024+10)).
2168-define(LARGE_BIN_LIM, (1024*1024)).
2169
2170mk_list(0, Acc) ->
2171    Acc;
2172mk_list(Sz, Acc) ->
2173    mk_list(Sz-1, [$A+(Sz band 63) | Acc]).
2174
2175mk_list(Sz) when Sz >= ?LARGE_BIN_LIM ->
2176    SzLeft = Sz - ?LARGE_BIN,
2177    SzHd = SzLeft div 2,
2178    SzTl = SzLeft - SzHd,
2179    [mk_list(SzHd, []), erlang:list_to_binary(mk_list(?LARGE_BIN, [])), mk_list(SzTl, [])];
2180mk_list(Sz) ->
2181    mk_list(Sz, []).
2182
2183mk_list_lb(Sz) when Sz >= ?LARGE_BIN_LIM ->
2184    SzLeft = Sz - ?LARGE_BIN,
2185    SzHd = SzLeft div 2,
2186    SzTl = SzLeft - SzHd,
2187    [mk_list(SzHd, []), erlang:list_to_binary(mk_list(?LARGE_BIN, [])), mk_list(SzTl, [])];
2188mk_list_lb(Sz) ->
2189    mk_list(Sz, []).
2190
2191
2192list2iolist(List) ->
2193    list2iolist(List, []).
2194
2195list2iolist([], Acc) ->
2196    Acc;
2197list2iolist([X0, X1, X2, X3, X4, X5 | Xs], Acc) when is_integer(X0), 0 =< X0, X0 < 256,
2198						     is_integer(X1), 0 =< X1, X1 < 256,
2199						     is_integer(X2), 0 =< X2, X2 < 256,
2200						     is_integer(X3), 0 =< X3, X3 < 256,
2201						     is_integer(X4), 0 =< X4, X4 < 256,
2202						     is_integer(X5), 0 =< X5, X5 < 256 ->
2203    NewAcc = case (X0+X1+X2+X3+X4+X5) band 3 of
2204		 0 ->
2205		     [Acc, [[[[[[[[[[[[X0,[],<<"">>,X1]]]]]]]]],[X2,X3]],[],[],[],[],X4],X5]];
2206		 1 ->
2207		     [Acc, [], erlang:list_to_binary([X0, X1, X2, X3, X4, X5])];
2208		 2 ->
2209		     [Acc, [[[[X0|erlang:list_to_binary([X1])],[X2|erlang:list_to_binary([X3])],[X4|erlang:list_to_binary([X5])]]]|<<"">>]];
2210		 3 ->
2211		     [Acc, X0, X1, X2, <<"">>, [], X3, X4 | erlang:list_to_binary([X5])]
2212	     end,
2213    list2iolist(Xs, NewAcc);
2214list2iolist([X | Xs], Acc) ->
2215    list2iolist(Xs, [Acc,X]).
2216
2217list2bitstrlist(List) ->
2218    [list2bitstrlist(List, []), <<4:7>>].
2219
2220list2bitstrlist([], Acc) ->
2221    Acc;
2222list2bitstrlist([X0, X1, X2, X3, X4, X5 | Xs], Acc) when is_integer(X0), 0 =< X0, X0 < 256,
2223						     is_integer(X1), 0 =< X1, X1 < 256,
2224						     is_integer(X2), 0 =< X2, X2 < 256,
2225						     is_integer(X3), 0 =< X3, X3 < 256,
2226						     is_integer(X4), 0 =< X4, X4 < 256,
2227						     is_integer(X5), 0 =< X5, X5 < 256 ->
2228    NewAcc = case (X0+X1+X2+X3+X4+X5) band 3 of
2229		 0 ->
2230		     [Acc, [[[[[[[[[[[[X0,[],<<"">>,X1]]]]]]]]],[X2,X3]],[],[],[],[],X4],X5]];
2231		 1 ->
2232		     [Acc, [], <<X0:X1>>, <<X2:X3>>, <<X4:X5>>];
2233		 2 ->
2234		     [Acc, [[[[X0|<<X1:X2>>],X3]],[X4|erlang:list_to_binary([X5])]|<<"">>]];
2235		 3 ->
2236		     [Acc, X0, X1, X2, <<"">>, [], X3, X4 | erlang:list_to_binary([X5])]
2237	     end,
2238    list2bitstrlist(Xs, NewAcc);
2239list2bitstrlist([X | Xs], Acc) ->
2240    list2bitstrlist(Xs, [Acc,X]).
2241