1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 1997-2013. All Rights Reserved.
    5: %%
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %%
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %%
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: -module(binary_SUITE).
   21: -compile({nowarn_deprecated_function, {erlang,hash,2}}).
   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("test_server/include/test_server.hrl").
   43: 
   44: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   45: 	 init_per_group/2,end_per_group/2, 
   46: 	 init_per_testcase/2, end_per_testcase/2,
   47: 	 copy_terms/1, conversions/1, deep_lists/1, deep_bitstr_lists/1,
   48: 	 bad_list_to_binary/1, bad_binary_to_list/1,
   49: 	 t_split_binary/1, bad_split/1,
   50: 	 terms/1, terms_float/1, float_middle_endian/1,
   51: 	 external_size/1, t_iolist_size/1,
   52: 	 t_hash/1,
   53: 	 bad_size/1,
   54: 	 bad_term_to_binary/1,
   55: 	 bad_binary_to_term_2/1,safe_binary_to_term2/1,
   56: 	 bad_binary_to_term/1, bad_terms/1, more_bad_terms/1,
   57: 	 otp_5484/1,otp_5933/1,
   58: 	 ordering/1,unaligned_order/1,gc_test/1,
   59: 	 bit_sized_binary_sizes/1,
   60: 	 otp_6817/1,deep/1,obsolete_funs/1,robustness/1,otp_8117/1,
   61: 	 otp_8180/1, ttb_trap/1]).
   62: 
   63: %% Internal exports.
   64: -export([sleeper/0,ttb_loop/2]).
   65: 
   66: suite() -> [{ct_hooks,[ts_install_cth]},
   67: 	    {timetrap,{minutes,2}}].
   68: 
   69: all() -> 
   70:     [copy_terms, conversions, deep_lists, deep_bitstr_lists,
   71:      t_split_binary, bad_split,
   72:      bad_list_to_binary, bad_binary_to_list, terms,
   73:      terms_float, float_middle_endian, external_size, t_iolist_size,
   74:      bad_binary_to_term_2, safe_binary_to_term2,
   75:      bad_binary_to_term, bad_terms, t_hash, bad_size,
   76:      bad_term_to_binary, more_bad_terms, otp_5484, otp_5933,
   77:      ordering, unaligned_order, gc_test,
   78:      bit_sized_binary_sizes, otp_6817, otp_8117, deep,
   79:      obsolete_funs, robustness, otp_8180, ttb_trap].
   80: 
   81: groups() -> 
   82:     [].
   83: 
   84: init_per_suite(Config) ->
   85:     Config.
   86: 
   87: end_per_suite(_Config) ->
   88:     ok.
   89: 
   90: init_per_group(_GroupName, Config) ->
   91:     Config.
   92: 
   93: end_per_group(_GroupName, Config) ->
   94:     Config.
   95: 
   96: init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
   97:     Config.
   98: 
   99: end_per_testcase(_Func, _Config) ->
  100:     ok.
  101: 
  102: -define(heap_binary_size, 64).
  103: 
  104: copy_terms(Config) when is_list(Config) ->
  105:     Self = self(),
  106:     ?line Pid = spawn_link(fun() -> copy_server(Self) end),
  107:     F = fun(Term) ->
  108: 		Pid ! Term,
  109: 		receive
  110: 		    Term -> ok;
  111: 		    Other ->
  112: 			io:format("Sent: ~P\nGot back:~P", [Term,12,Other,12]),
  113: 			?t:fail(bad_term)
  114: 		end
  115: 	end,
  116:     ?line test_terms(F),
  117:     ok.
  118: 
  119: copy_server(Parent) ->
  120:     receive
  121: 	Term ->
  122: 	    Parent ! Term,
  123: 	    copy_server(Parent)
  124:     end.
  125: 
  126: %% Tests list_to_binary/1, binary_to_list/1 and size/1,
  127: %% using flat lists.
  128: 
  129: conversions(suite) -> [];
  130: conversions(Config) when is_list(Config) ->
  131:     ?line test_bin([]),
  132:     ?line test_bin([1]),
  133:     ?line test_bin([1, 2]),
  134:     ?line test_bin([1, 2, 3]),
  135:     ?line test_bin(lists:seq(0, ?heap_binary_size)),
  136:     ?line test_bin(lists:seq(0, ?heap_binary_size+1)),
  137:     ?line test_bin(lists:seq(0, 255)),
  138:     ?line test_bin(lists:duplicate(50000, $@)),
  139: 
  140:     %% Binary in list.
  141:     List = [1,2,3,4,5],
  142:     ?line B1 = make_sub_binary(list_to_binary(List)),
  143:     ?line 5 = size(B1),
  144:     ?line 5 = size(make_unaligned_sub_binary(B1)),
  145:     ?line 40 = bit_size(B1),
  146:     ?line 40 = bit_size(make_unaligned_sub_binary(B1)),
  147:     ?line B2 = list_to_binary([42,B1,19]),
  148:     ?line B2 = list_to_binary([42,make_unaligned_sub_binary(B1),19]),
  149:     ?line B2 = iolist_to_binary(B2),
  150:     ?line B2 = iolist_to_binary(make_unaligned_sub_binary(B2)),
  151:     ?line 7 = size(B2),
  152:     ?line 7 = size(make_sub_binary(B2)),
  153:     ?line 56 = bit_size(B2),
  154:     ?line 56 = bit_size(make_sub_binary(B2)),
  155:     ?line [42,1,2,3,4,5,19] = binary_to_list(B2),
  156:     ?line [42,1,2,3,4,5,19] = binary_to_list(make_sub_binary(B2)),
  157:     ?line [42,1,2,3,4,5,19] = binary_to_list(make_unaligned_sub_binary(B2)),
  158:     ?line [42,1,2,3,4,5,19] = bitstring_to_list(B2),
  159:     ?line [42,1,2,3,4,5,19] = bitstring_to_list(make_sub_binary(B2)),
  160:     ?line [42,1,2,3,4,5,19] = bitstring_to_list(make_unaligned_sub_binary(B2)),
  161: 
  162:     ok.
  163: 
  164: test_bin(List) ->
  165:     ?line Size = length(List),
  166:     ?line Bin = list_to_binary(List),
  167:     ?line Bin = iolist_to_binary(List),
  168:     ?line Bin = list_to_bitstring(List),
  169:     ?line Size = iolist_size(List),
  170:     ?line Size = iolist_size(Bin),
  171:     ?line Size = iolist_size(make_unaligned_sub_binary(Bin)),
  172:     ?line Size = size(Bin),
  173:     ?line Size = size(make_sub_binary(Bin)),
  174:     ?line Size = size(make_unaligned_sub_binary(Bin)),
  175:     ?line List = binary_to_list(Bin),
  176:     ?line List = binary_to_list(make_sub_binary(Bin)),
  177:     ?line List = binary_to_list(make_unaligned_sub_binary(Bin)),
  178:     ?line List = bitstring_to_list(Bin),
  179:     ?line List = bitstring_to_list(make_unaligned_sub_binary(Bin)).
  180: 
  181: %% Tests list_to_binary/1, iolist_to_binary/1, list_to_bitstr/1, binary_to_list/1,3,
  182: %% bitstr_to_list/1, and size/1, using deep lists.
  183: 
  184: deep_lists(Config) when is_list(Config) ->
  185:     ?line test_deep_list(["abc"]),
  186:     ?line test_deep_list([[12,13,[123,15]]]),
  187:     ?line test_deep_list([[12,13,[lists:seq(0, 255), []]]]),
  188:     ok.
  189: 
  190: test_deep_list(List) ->
  191:     ?line FlatList = lists:flatten(List),
  192:     ?line Size = length(FlatList),
  193:     ?line Bin = list_to_binary(List),
  194:     ?line Bin = iolist_to_binary(List),
  195:     ?line Bin = iolist_to_binary(Bin),
  196:     ?line Bin = list_to_bitstring(List),
  197:     ?line Size = size(Bin),
  198:     ?line Size = iolist_size(List),
  199:     ?line Size = iolist_size(FlatList),
  200:     ?line Size = iolist_size(Bin),
  201:     ?line Bitsize = bit_size(Bin),
  202:     ?line Bitsize = 8*Size,
  203:     ?line FlatList = binary_to_list(Bin),
  204:     ?line FlatList = bitstring_to_list(Bin),
  205:     io:format("testing plain binary..."),
  206:     ?line t_binary_to_list_3(FlatList, Bin, 1, Size),
  207:     io:format("testing unaligned sub binary..."),
  208:     ?line t_binary_to_list_3(FlatList, make_unaligned_sub_binary(Bin), 1, Size).
  209: 
  210: t_binary_to_list_3(List, Bin, From, To) ->
  211:     ?line going_up(List, Bin, From, To),
  212:     ?line going_down(List, Bin, From, To),
  213:     ?line going_center(List, Bin, From, To).
  214: 
  215: going_up(List, Bin, From, To) when From =< To ->
  216:     ?line List = binary_to_list(Bin, From, To),
  217:     ?line going_up(tl(List), Bin, From+1, To);
  218: going_up(_List, _Bin, From, To) when From > To ->
  219:     ok.
  220:     
  221: going_down(List, Bin, From, To) when To > 0->
  222:     ?line compare(List, binary_to_list(Bin, From, To), To-From+1),
  223:     ?line going_down(List, Bin, From, To-1);
  224: going_down(_List, _Bin, _From, _To) ->
  225:     ok.
  226: 
  227: going_center(List, Bin, From, To) when From >= To ->
  228:     ?line compare(List, binary_to_list(Bin, From, To), To-From+1),
  229:     ?line going_center(tl(List), Bin, From+1, To-1);
  230: going_center(_List, _Bin, _From, _To) ->
  231:     ok.
  232: 
  233: compare([X|Rest1], [X|Rest2], Left) when Left > 0 ->
  234:     ?line compare(Rest1, Rest2, Left-1);
  235: compare([_X|_], [_Y|_], _Left) ->
  236:     ?line test_server:fail();
  237: compare(_List, [], 0) ->
  238:     ok.
  239: 
  240: deep_bitstr_lists(Config) when is_list(Config) ->
  241:     ?line {<<7:3>>,[<<7:3>>]} = test_deep_bitstr([<<7:3>>]),
  242:     ?line {<<42,5:3>>=Bin,[42,<<5:3>>]=List} = test_deep_bitstr([42,<<5:3>>]),
  243:     ?line {Bin,List} = test_deep_bitstr([42|<<5:3>>]),
  244:     ?line {Bin,List} = test_deep_bitstr([<<42,5:3>>]),
  245:     ?line {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>|<<5:3>>]),
  246:     ?line {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>,<<5:3>>]),
  247:     ?line {Bin,List} = test_deep_bitstr([[<<1:3>>,<<10:5>>],[],<<5:3>>]),
  248:     ?line {Bin,List} = test_deep_bitstr([[[<<1:3>>]|<<10:5>>],[],<<5:3>>]),
  249:     ?line {Bin,List} = test_deep_bitstr([[<<0:1>>,<<0:1>>,[],<<1:1>>,<<10:5>>],
  250: 					 <<1:1>>,<<0:1>>,<<1:1>>]),
  251:     ok.
  252: 
  253: test_deep_bitstr(List) ->
  254:     %%?line {'EXIT',{badarg,_}} = list_to_binary(List),
  255:     Bin = list_to_bitstring(List),
  256:     {Bin,bitstring_to_list(Bin)}.
  257: 
  258: bad_list_to_binary(suite) -> [];
  259: bad_list_to_binary(Config) when is_list(Config) ->
  260:     ?line test_bad_bin(atom),
  261:     ?line test_bad_bin(42),
  262:     ?line test_bad_bin([1|2]),
  263:     ?line test_bad_bin([256]),
  264:     ?line test_bad_bin([255, [256]]),
  265:     ?line test_bad_bin([-1]),
  266:     ?line test_bad_bin([atom_in_list]),
  267:     ?line test_bad_bin([[<<8>>]|bad_tail]),
  268: 
  269:     {'EXIT',{badarg,_}} = (catch list_to_binary(id(<<1,2,3>>))),
  270:     {'EXIT',{badarg,_}} = (catch list_to_binary(id([<<42:7>>]))),
  271:     {'EXIT',{badarg,_}} = (catch list_to_bitstring(id(<<1,2,3>>))),
  272:     
  273:     %% Funs used to be implemented as a type of binary internally.
  274:     ?line test_bad_bin(fun(X, Y) -> X*Y end),
  275:     ?line test_bad_bin([1,fun(X) -> X + 1 end,2|fun() -> 0 end]),
  276:     ?line test_bad_bin([fun(X) -> X + 1 end]),
  277: 
  278:     %% Test iolists that do not fit in the address space.
  279:     %% Unfortunately, it would be too slow to test in a 64-bit emulator.
  280:     case erlang:system_info(wordsize) of
  281: 	4 -> huge_iolists();
  282: 	_ -> ok
  283:     end.
  284: 
  285: huge_iolists() ->
  286:     FourGigs = 1 bsl 32,
  287:     ?line Sizes = [FourGigs+N || N <- lists:seq(0, 64)] ++
  288: 	[1 bsl N || N <- lists:seq(33, 37)],
  289:     ?line Base = <<0:(1 bsl 20)/unit:8>>,
  290:     [begin
  291: 	 L = build_iolist(Sz, Base),
  292: 	 ?line {'EXIT',{system_limit,_}} = (catch list_to_binary([L])),
  293: 	 ?line {'EXIT',{system_limit,_}} = (catch list_to_bitstring([L])),
  294: 	 ?line {'EXIT',{system_limit,_}} = (catch binary:list_to_bin([L])),
  295: 	 ?line {'EXIT',{system_limit,_}} = (catch iolist_to_binary(L))
  296: 	 end || Sz <- Sizes],
  297:     ok.
  298: 
  299: test_bad_bin(List) ->
  300:     {'EXIT',{badarg,_}} = (catch list_to_binary(List)),
  301:     {'EXIT',{badarg,_}} = (catch iolist_to_binary(List)),
  302:     {'EXIT',{badarg,_}} = (catch list_to_bitstring(List)),
  303:     {'EXIT',{badarg,_}} = (catch iolist_size(List)).
  304: 
  305: bad_binary_to_list(doc) -> "Tries binary_to_list/1,3 with bad arguments.";
  306: bad_binary_to_list(Config) when is_list(Config) ->
  307:     ?line bad_bin_to_list(fun(X) -> X * 42 end),
  308: 
  309:     GoodBin = list_to_binary(lists:seq(1, 10)),
  310:     ?line bad_bin_to_list(fun(X) -> X * 44 end, 1, 2),
  311:     ?line bad_bin_to_list(GoodBin, 0, 1),
  312:     ?line bad_bin_to_list(GoodBin, 2, 1),
  313:     ?line bad_bin_to_list(GoodBin, 11, 11),
  314:     {'EXIT',{badarg,_}} = (catch binary_to_list(id(<<42:7>>))),
  315:     ok.
  316: 
  317: bad_bin_to_list(BadBin) ->
  318:     {'EXIT',{badarg,_}} = (catch binary_to_list(BadBin)),
  319:     {'EXIT',{badarg,_}} = (catch bitstring_to_list(BadBin)).
  320: 
  321: bad_bin_to_list(Bin, First, Last) ->
  322:     {'EXIT',{badarg,_}} = (catch binary_to_list(Bin, First, Last)).
  323:     
  324:     
  325: %% Tries to split a binary at all possible positions.
  326: 
  327: t_split_binary(suite) -> [];
  328: t_split_binary(Config) when is_list(Config) ->
  329:     ?line L = lists:seq(0, ?heap_binary_size-5), %Heap binary.
  330:     ?line B = list_to_binary(L),
  331:     ?line split(L, B, size(B)),
  332: 
  333:     %% Sub binary of heap binary.
  334:     ?line split(L, make_sub_binary(B), size(B)),
  335:     {X,_Y} = split_binary(B, size(B) div 2),
  336:     ?line split(binary_to_list(X), X, size(X)),
  337: 
  338:     %% Unaligned sub binary of heap binary.
  339:     ?line split(L, make_unaligned_sub_binary(B), size(B)),
  340:     {X,_Y} = split_binary(B, size(B) div 2),
  341:     ?line split(binary_to_list(X), X, size(X)),
  342:     
  343:     %% Reference-counted binary.
  344:     ?line L2 = lists:seq(0, ?heap_binary_size+1),
  345:     ?line B2 = list_to_binary(L2),
  346:     ?line split(L2, B2, size(B2)),
  347: 
  348:     %% Sub binary of reference-counted binary.
  349:     ?line split(L2, make_sub_binary(B2), size(B2)),
  350:     {X2,_Y2} = split_binary(B2, size(B2) div 2),
  351:     ?line split(binary_to_list(X2), X2, size(X2)),
  352: 
  353:     %% Unaligned sub binary of reference-counted binary.
  354:     ?line split(L2, make_unaligned_sub_binary(B2), size(B2)),
  355:     {X2,_Y2} = split_binary(B2, size(B2) div 2),
  356:     ?line split(binary_to_list(X2), X2, size(X2)),
  357: 
  358:     ok.
  359: 
  360: split(L, B, Pos) when Pos > 0 ->
  361:     ?line {B1, B2} = split_binary(B, Pos),
  362:     ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)),
  363:     ?line B2 = list_to_binary(lists:nthtail(Pos, L)),
  364:     ?line split(L, B, Pos-1);
  365: split(_L, _B, 0) ->
  366:     ok.
  367: 
  368: bad_split(doc) -> "Tries split_binary/2 with bad arguments.";
  369: bad_split(suite) -> [];
  370: bad_split(Config) when is_list(Config) ->
  371:     GoodBin = list_to_binary([1,2,3]),
  372:     ?line bad_split(GoodBin, -1),
  373:     ?line bad_split(GoodBin, 4),
  374:     ?line bad_split(GoodBin, a),
  375: 
  376:     %% Funs are a kind of binaries.
  377:     ?line bad_split(fun(_X) -> 1 end, 1),
  378:     ok.
  379:     
  380: bad_split(Bin, Pos) ->
  381:     {'EXIT',{badarg,_}} = (catch split_binary(Bin, Pos)).
  382: 
  383: t_hash(doc) -> "Test hash/2 with different type of binaries.";
  384: t_hash(Config) when is_list(Config) ->
  385:     test_hash([]),
  386:     test_hash([253]),
  387:     test_hash(lists:seq(1, ?heap_binary_size)),
  388:     test_hash(lists:seq(1, ?heap_binary_size+1)),
  389:     test_hash([X rem 256 || X <- lists:seq(1, 312)]),
  390:     ok.
  391: 
  392: test_hash(List) ->
  393:     Bin = list_to_binary(List),
  394:     Sbin = make_sub_binary(List),
  395:     Unaligned = make_unaligned_sub_binary(Sbin),
  396:     ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:hash/2),
  397:     ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash/2),
  398:     ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash2/2).
  399: 
  400: test_hash_1(Bin, Sbin, Unaligned, Hash) when is_function(Hash, 2) ->
  401:     N = 65535,
  402:     case {Hash(Bin, N),Hash(Sbin, N),Hash(Unaligned, N)} of
  403: 	{H,H,H} -> ok;
  404: 	{H1,H2,H3} ->
  405: 	    io:format("Different hash values: ~p, ~p, ~p\n", [H1,H2,H3]),
  406: 	    ?t:fail()
  407:     end.
  408: 
  409: bad_size(doc) -> "Try bad arguments to size/1.";
  410: bad_size(suite) -> [];
  411: bad_size(Config) when is_list(Config) ->
  412:     ?line {'EXIT',{badarg,_}} = (catch size(fun(X) -> X + 33 end)),
  413:     ok.
  414: 
  415: bad_term_to_binary(Config) when is_list(Config) ->
  416:     T = id({a,b,c}),
  417:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, not_a_list)),
  418:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [blurf])),
  419:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,-1}])),
  420:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,10}])),
  421:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,cucumber}])),
  422:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed}])),
  423:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{version,1}|bad_tail])),
  424:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,-1}])),
  425:     ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,x}])),
  426: 
  427:     ok.
  428: 
  429: %% Tests binary_to_term/1 and term_to_binary/1.
  430: 
  431: terms(Config) when is_list(Config) ->
  432:     TestFun = fun(Term) ->
  433: 		      try
  434: 			  S = io_lib:format("~p", [Term]),
  435: 			  io:put_chars(S)
  436: 		      catch
  437: 			  error:badarg ->
  438: 			      io:put_chars("bit sized binary")
  439: 		      end,
  440: 		      Bin = term_to_binary(Term),
  441: 		      case erlang:external_size(Bin) of
  442: 			  Sz when is_integer(Sz), size(Bin) =< Sz ->
  443: 			      ok
  444: 		      end,
  445:               Bin1 = term_to_binary(Term, [{minor_version, 1}]),
  446:               case erlang:external_size(Bin1, [{minor_version, 1}]) of
  447:               Sz1 when is_integer(Sz1), size(Bin1) =< Sz1 ->
  448:                   ok
  449:               end,
  450: 		      Term = binary_to_term(Bin),
  451: 		      Term = binary_to_term(Bin, [safe]),
  452: 		      Unaligned = make_unaligned_sub_binary(Bin),
  453: 		      Term = binary_to_term(Unaligned),
  454: 		      Term = binary_to_term(Unaligned, []),
  455: 		      Term = binary_to_term(Bin, [safe]),
  456: 		      BinC = erlang:term_to_binary(Term, [compressed]),
  457: 		      Term = binary_to_term(BinC),
  458: 		      true = size(BinC) =< size(Bin),
  459: 		      Bin = term_to_binary(Term, [{compressed,0}]),
  460: 		      terms_compression_levels(Term, size(Bin), 1),
  461: 		      UnalignedC = make_unaligned_sub_binary(BinC),
  462: 		      Term = binary_to_term(UnalignedC)
  463: 	      end,
  464:     ?line test_terms(TestFun),
  465:     ok.
  466: 
  467: terms_compression_levels(Term, UncompressedSz, Level) when Level < 10 ->
  468:     BinC = erlang:term_to_binary(Term, [{compressed,Level}]),
  469:     Term = binary_to_term(BinC),
  470:     Sz = byte_size(BinC),
  471:     true = Sz =< UncompressedSz,
  472:     terms_compression_levels(Term, UncompressedSz, Level+1);
  473: terms_compression_levels(_, _, _) -> ok.
  474: 
  475: terms_float(Config) when is_list(Config) ->
  476:     ?line test_floats(fun(Term) ->
  477: 			      Bin0 = term_to_binary(Term),
  478: 			      Bin0 = term_to_binary(Term, [{minor_version,0}]),
  479: 			      Term = binary_to_term(Bin0),
  480: 			      Bin1 = term_to_binary(Term, [{minor_version,1}]),
  481: 			      Term = binary_to_term(Bin1),
  482: 			      true = size(Bin1) < size(Bin0),
  483:                   Size0 = erlang:external_size(Term),
  484:                   Size00 = erlang:external_size(Term, [{minor_version, 0}]),
  485:                   Size1 = erlang:external_size(Term, [{minor_version, 1}]),
  486:                   true = (Size0 =:= Size00),
  487:                   true = Size1 < Size0
  488: 		      end).
  489: 
  490: float_middle_endian(Config) when is_list(Config) ->
  491:     %% Testing for roundtrip is not enough.
  492:     ?line <<131,70,63,240,0,0,0,0,0,0>> = term_to_binary(1.0, [{minor_version,1}]),
  493:     ?line 1.0 = binary_to_term(<<131,70,63,240,0,0,0,0,0,0>>).
  494: 
  495: external_size(Config) when is_list(Config) ->
  496:     %% Build a term whose external size only fits in a big num (on 32-bit CPU).
  497:     ?line external_size_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF),
  498: 
  499:     %% Test that the same binary aligned and unaligned has the same external size.
  500:     ?line Bin = iolist_to_binary([1,2,3,96]),
  501:     ?line Unaligned = make_unaligned_sub_binary(Bin),
  502:     case {erlang:external_size(Bin),erlang:external_size(Unaligned)} of
  503: 	{X,X} -> ok;
  504: 	{Sz1,Sz2} ->
  505: 	    io:format("  Aligned size: ~p\n", [Sz1]),
  506: 	    io:format("Unaligned size: ~p\n", [Sz2]),
  507: 	    ?line ?t:fail()
  508:     end,
  509:     ?line erlang:external_size(Bin) =:= erlang:external_size(Bin, [{minor_version, 1}]),
  510:     ?line erlang:external_size(Unaligned) =:= erlang:external_size(Unaligned, [{minor_version, 1}]).
  511: 
  512: external_size_1(Term, Size0, Limit) when Size0 < Limit ->
  513:     case erlang:external_size(Term) of
  514: 	Size when is_integer(Size), Size0 < Size ->
  515: 	    io:format("~p", [Size]),
  516: 	    external_size_1([Term|Term], Size, Limit)
  517:     end;
  518: external_size_1(_, _, _) -> ok.
  519: 
  520: t_iolist_size(Config) when is_list(Config) ->
  521:     ?line Seed = now(),
  522:     ?line io:format("Seed: ~p", [Seed]),
  523:     ?line random:seed(Seed),
  524:     ?line Base = <<0:(1 bsl 20)/unit:8>>,
  525:     ?line Powers = [1 bsl N || N <- lists:seq(2, 37)],
  526:     ?line Sizes0 = [[N - random:uniform(N div 2),
  527: 		     lists:seq(N-2, N+2),
  528: 		     N+N div 2,
  529: 		     N + random:uniform(N div 2)] ||
  530: 		       N <- Powers],
  531:     %% Test sizes around 1^32 more thoroughly.
  532:     FourGigs = 1 bsl 32,
  533:     ?line Sizes1 = [FourGigs+N || N <- lists:seq(-8, 40)] ++ Sizes0,
  534:     ?line Sizes2 = lists:flatten(Sizes1),
  535:     ?line Sizes = lists:usort(Sizes2),
  536:     io:format("~p sizes:", [length(Sizes)]),
  537:     io:format("~p\n", [Sizes]),
  538:     ?line [Sz = iolist_size(build_iolist(Sz, Base)) || Sz <- Sizes],
  539:     ok.
  540: 
  541: build_iolist(N, Base) when N < 16 ->
  542:     case random:uniform(3) of
  543: 	1 ->
  544: 	    <<Bin:N/binary,_/binary>> = Base,
  545: 	    Bin;
  546: 	_ ->
  547: 	    lists:seq(1, N)
  548:     end;
  549: build_iolist(N, Base) when N =< byte_size(Base) ->
  550:     case random:uniform(3) of
  551: 	1 ->
  552: 	    <<Bin:N/binary,_/binary>> = Base,
  553: 	    Bin;
  554: 	2 ->
  555: 	    <<Bin:N/binary,_/binary>> = Base,
  556: 	    [Bin];
  557: 	3 ->
  558: 	    case N rem 2 of
  559: 		0 ->
  560: 		    L = build_iolist(N div 2, Base),
  561: 		    [L,L];
  562: 		1 ->
  563: 		    L = build_iolist(N div 2, Base),
  564: 		    [L,L,45]
  565: 	    end
  566:     end;
  567: build_iolist(N0, Base) ->
  568:     Small = random:uniform(15),
  569:     Seq = lists:seq(1, Small),
  570:     N = N0 - Small,
  571:     case N rem 2 of
  572: 	0 ->
  573: 	    L = build_iolist(N div 2, Base),
  574: 	    [L,L|Seq];
  575: 	1 ->
  576: 	    L = build_iolist(N div 2, Base),
  577: 	    [47,L,L|Seq]
  578:     end.
  579: 
  580: 
  581: bad_binary_to_term_2(doc) -> "OTP-4053.";
  582: bad_binary_to_term_2(suite) -> [];
  583: bad_binary_to_term_2(Config) when is_list(Config) ->
  584:     ?line {ok, N} = test_server:start_node(plopp, slave, []),
  585:     ?line R = rpc:call(N, erlang, binary_to_term, [<<131,111,255,255,255,0>>]),
  586:     ?line case R of
  587: 	      {badrpc, {'EXIT', _}} ->
  588: 		  ok;
  589: 	      _Other ->
  590: 		  test_server:fail({rpcresult, R})
  591: 	  end,
  592:     ?line test_server:stop_node(N),
  593:     ok.
  594: 
  595: bad_binary_to_term(doc) -> "Try bad input to binary_to_term/1.";
  596: bad_binary_to_term(Config) when is_list(Config) ->
  597:     ?line bad_bin_to_term(an_atom),
  598:     ?line bad_bin_to_term({an,tuple}),
  599:     ?line bad_bin_to_term({a,list}),
  600:     ?line bad_bin_to_term(fun() -> self() end),
  601:     ?line bad_bin_to_term(fun(X) -> 42*X end),
  602:     ?line bad_bin_to_term(fun(X, Y) -> {X,Y} end),
  603:     ?line bad_bin_to_term(fun(X, Y, Z) -> {X,Y,Z} end),
  604:     ?line bad_bin_to_term(bit_sized_binary(term_to_binary({you,should,'not',see,this,term}))),
  605: 
  606:     %% Bad float.
  607:     ?line bad_bin_to_term(<<131,70,-1:64>>),
  608:     ok.
  609: 
  610: bad_bin_to_term(BadBin) ->
  611:     {'EXIT',{badarg,_}} = (catch binary_to_term(BadBin)).
  612: 
  613: bad_bin_to_term(BadBin,Opts) ->
  614:     {'EXIT',{badarg,_}} = (catch binary_to_term(BadBin,Opts)).
  615: 
  616: safe_binary_to_term2(doc) -> "Test safety options for binary_to_term/2";
  617: safe_binary_to_term2(Config) when is_list(Config) ->
  618:     ?line bad_bin_to_term(<<131,100,0,14,"undefined_atom">>, [safe]),
  619:     ?line bad_bin_to_term(<<131,100,0,14,"other_bad_atom">>, [safe]),
  620:     BadHostAtom = <<100,0,14,"badguy@badhost">>,
  621:     Empty = <<0,0,0,0>>,
  622:     BadRef = <<131,114,0,3,BadHostAtom/binary,0,<<0,0,0,255>>/binary,
  623: 	      Empty/binary,Empty/binary>>,
  624:     ?line bad_bin_to_term(BadRef, [safe]), % good ref, with a bad atom
  625:     ?line fullsweep_after = binary_to_term(<<131,100,0,15,"fullsweep_after">>, [safe]), % should be a good atom
  626:     BadExtFun = <<131,113,100,0,4,98,108,117,101,100,0,4,109,111,111,110,97,3>>,
  627:     ?line bad_bin_to_term(BadExtFun, [safe]),
  628:     ok.
  629: 
  630: %% Tests bad input to binary_to_term/1.
  631: 
  632: bad_terms(suite) -> [];
  633: bad_terms(Config) when is_list(Config) ->
  634:     ?line test_terms(fun corrupter/1),
  635:     {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,0,11,22,33>>)),
  636:     {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,9,11,22,33>>)),
  637:     {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,0:32,1,11,22,33>>)),
  638:     {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,-1:32,1,11,22,33>>)),
  639:     ok.
  640: 
  641: 
  642: corrupter(Term) when is_function(Term);
  643: 		     is_function(hd(Term));
  644: 		     is_function(element(2,element(2,element(2,Term)))) ->
  645:     %% Check if lists is native compiled. If it is, we do not try to
  646:     %% corrupt funs as this can create some very strange behaviour.
  647:     %% To show the error print `Byte` in the foreach fun in corrupter/2.
  648:     case erlang:system_info(hipe_architecture) of
  649: 	undefined ->
  650: 	    corrupter0(Term);
  651: 	Architecture ->
  652: 	    {lists, ListsBinary, _ListsFilename} = code:get_object_code(lists),
  653: 	    ChunkName = hipe_unified_loader:chunk_name(Architecture),
  654: 	    NativeChunk = beam_lib:chunks(ListsBinary, [ChunkName]),
  655: 	    case NativeChunk of
  656: 		{ok,{_,[{_,Bin}]}} when is_binary(Bin) ->
  657: 		    S = io_lib:format("Skipping corruption of: ~P", [Term,12]),
  658: 		    io:put_chars(S);
  659: 		{error, beam_lib, _} ->
  660: 		    corrupter0(Term)
  661: 	    end
  662:     end;
  663: corrupter(Term) ->
  664:     corrupter0(Term).
  665: 
  666: corrupter0(Term) ->
  667:     ?line try
  668: 	      S = io_lib:format("About to corrupt: ~P", [Term,12]),
  669: 	      io:put_chars(S)
  670: 	  catch
  671: 	      error:badarg ->
  672: 		  io:format("About to corrupt: <<bit-level-binary:~p",
  673: 			    [bit_size(Term)])
  674: 	  end,
  675:     ?line Bin = term_to_binary(Term),
  676:     ?line corrupter(Bin, size(Bin)-1),
  677:     ?line CompressedBin = term_to_binary(Term, [compressed]),
  678:     ?line corrupter(CompressedBin, size(CompressedBin)-1).
  679: 
  680: corrupter(Bin, Pos) when Pos >= 0 ->
  681:     ?line {ShorterBin, Rest} = split_binary(Bin, Pos),
  682:     ?line catch binary_to_term(ShorterBin), %% emulator shouldn't crash
  683:     ?line MovedBin = list_to_binary([ShorterBin]),
  684:     ?line catch binary_to_term(MovedBin), %% emulator shouldn't crash
  685: 
  686:     %% Bit faults, shouldn't crash
  687:     <<Byte,Tail/binary>> = Rest,
  688:     Fun = fun(M) -> FaultyByte = Byte bxor M,                    
  689: 		    catch binary_to_term(<<ShorterBin/binary,
  690: 					  FaultyByte, Tail/binary>>) end,
  691:     ?line lists:foreach(Fun,[1,2,4,8,16,32,64,128,255]),    
  692:     ?line corrupter(Bin, Pos-1);
  693: corrupter(_Bin, _) ->
  694:     ok.
  695: 
  696: more_bad_terms(suite) -> [];
  697: more_bad_terms(Config) when is_list(Config) ->
  698:     ?line Data = ?config(data_dir, Config),
  699:     ?line BadFile = filename:join(Data, "bad_binary"),
  700:     ?line ok = io:format("File: ~s\n", [BadFile]),
  701:     ?line case file:read_file(BadFile) of
  702: 	      {ok,Bin} ->
  703: 		  ?line {'EXIT',{badarg,_}} = (catch binary_to_term(Bin)),
  704: 		  ok;
  705: 	      Other ->
  706: 		  ?line ?t:fail(Other)
  707: 	  end.
  708: 
  709: otp_5484(Config) when is_list(Config) ->
  710:     ?line {'EXIT',_} =
  711: 	(catch
  712: 	     binary_to_term(
  713: 	       <<131,
  714: 		104,2,				%Tuple, 2 elements
  715: 		103,				%Pid
  716: 		100,0,20,"wslin1427198@wslin14",
  717: 		%% Obviously bad values follow.
  718: 		255,255,255,255,
  719: 		255,255,255,255,
  720: 		255,
  721: 		106>>)),
  722: 
  723:     ?line {'EXIT',_} =
  724: 	(catch
  725: 	     binary_to_term(
  726: 	       <<131,
  727: 		104,2,				%Tuple, 2 elements
  728: 		103,				%Pid
  729: 		106,				%[] instead of atom.
  730: 		0,0,0,17,
  731: 		0,0,0,135,
  732: 		2,
  733: 		106>>)),
  734: 
  735:     ?line {'EXIT',_} =
  736: 	(catch
  737: 	     binary_to_term(
  738: 	       %% A old-type fun in a list containing a bad creator pid.
  739: 	       <<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>>)),
  740: 
  741:     ?line {'EXIT',_} =
  742: 	(catch
  743: 	     binary_to_term(
  744: 	       %% A new-type fun in a list containing a bad creator pid.
  745: 	       %% 
  746: 	       <<131,
  747: 		108,0,0,0,1,			%List, 1 element
  748: 		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,
  749: 		103,				%Pid.
  750: 		106,				%[] instead of an atom.
  751: 		0,0,0,27,0,0,0,0,0,106>>)),
  752: 
  753:     ?line {'EXIT',_} =
  754: 	(catch
  755: 	     binary_to_term(
  756: 	       %% A new-type fun in a list containing a bad module.
  757: 	       <<131,
  758: 		108,0,0,0,1,			%List, 1 element
  759: 		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,
  760: 		%%100,0,1,116,
  761: 		107,0,1,64,			%String instead of atom (same length).
  762: 		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>>)),
  763: 
  764:     ?line {'EXIT',_} =
  765: 	(catch
  766: 	     binary_to_term(
  767: 	       %% A new-type fun in a list containing a bad index.
  768: 	       <<131,
  769: 		108,0,0,0,1,			%List, 1 element
  770: 		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,
  771: 		100,0,1,116,
  772: 		%%97,0,				%Integer: 0.
  773: 		104,0,				%Tuple {} instead of integer.
  774: 		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>>)),
  775: 
  776:     ?line {'EXIT',_} =
  777: 	(catch
  778: 	     binary_to_term(
  779: 	       %% A new-type fun in a list containing a bad unique value.
  780: 	       <<131,
  781: 		108,0,0,0,1,			%List, 1 element
  782: 		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,
  783: 		100,0,1,116,
  784: 		97,0,				%Integer: 0.
  785: 		%%98,6,64,82,230,		%Integer.
  786: 		100,0,2,64,65,			%Atom instead of integer.
  787: 		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>>)),
  788: 
  789:     %% An absurdly large atom.
  790:     ?line {'EXIT',_} = 
  791: 	(catch binary_to_term(iolist_to_binary([<<131,100,65000:16>>|
  792: 						lists:duplicate(65000, 42)]))),
  793: 
  794:     %% Longer than 255 characters.
  795:     ?line {'EXIT',_} = 
  796: 	(catch binary_to_term(iolist_to_binary([<<131,100,256:16>>|
  797: 						lists:duplicate(256, 42)]))),
  798: 
  799:     %% OTP-7218. Thanks to Matthew Dempsky. Also make sure that we
  800:     %% cover the other error cases for external funs (EXPORT_EXT).
  801:     ?line {'EXIT',_} = 
  802: 	(catch binary_to_term(
  803: 		 <<131,
  804: 		  113,				%EXPORT_EXP
  805: 		  97,13,			%Integer: 13
  806: 		  97,13,			%Integer: 13
  807: 		  97,13>>)),			%Integer: 13
  808:     ?line {'EXIT',_} = 
  809: 	(catch binary_to_term(
  810: 		 <<131,
  811: 		  113,				%EXPORT_EXP
  812: 		  100,0,1,64,			%Atom: '@'
  813: 		  97,13,			%Integer: 13
  814: 		  97,13>>)),			%Integer: 13
  815:     ?line {'EXIT',_} = 
  816: 	(catch binary_to_term(
  817: 		 <<131,
  818: 		  113,				%EXPORT_EXP
  819: 		  100,0,1,64,			%Atom: '@'
  820: 		  100,0,1,64,			%Atom: '@'
  821: 		  106>>)),			%NIL
  822:     ?line {'EXIT',_} = 
  823: 	(catch binary_to_term(
  824: 		 <<131,
  825: 		  113,				%EXPORT_EXP
  826: 		  100,0,1,64,			%Atom: '@'
  827: 		  100,0,1,64,			%Atom: '@'
  828: 		  98,255,255,255,255>>)),	%Integer: -1
  829:     ?line {'EXIT',_} = 
  830: 	(catch binary_to_term(
  831: 		 <<131,
  832: 		  113,				%EXPORT_EXP
  833: 		  100,0,1,64,			%Atom: '@'
  834: 		  100,0,1,64,			%Atom: '@'
  835: 		  113,97,13,97,13,97,13>>)),	%fun 13:13/13
  836: 
  837:     %% Bad funs.
  838:     ?line {'EXIT',_} = (catch binary_to_term(fake_fun(0, lists:seq(0, 256)))),
  839:     ok.
  840: 
  841: fake_fun(Arity, Env0) ->
  842:     Uniq = erlang:md5([]),
  843:     Index = 0,
  844:     NumFree = length(Env0),
  845:     Mod = list_to_binary(?MODULE_STRING),
  846:     OldIndex = 0,
  847:     OldUniq = 16#123456,
  848:     <<131,Pid/binary>> = term_to_binary(self()),
  849:     Env1 = [term_to_binary(Term) || Term <- Env0],
  850:     Env = << <<Bin/binary>> || <<131,Bin/binary>> <- Env1 >>,
  851:     B = <<Arity,Uniq/binary,Index:32,NumFree:32,
  852: 	 $d,(byte_size(Mod)):16,Mod/binary,	%Module.
  853: 	 $a,OldIndex:8,
  854: 	 $b,OldUniq:32,
  855: 	 Pid/binary,Env/binary>>,
  856:     <<131,$p,(byte_size(B)+4):32,B/binary>>.
  857: 
  858: 
  859: %% More bad terms submitted by Matthias Lang.
  860: otp_5933(Config) when is_list(Config) ->
  861:     ?line try_bad_lengths(<<131,$m>>),		%binary
  862:     ?line try_bad_lengths(<<131,$n>>),		%bignum
  863:     ?line try_bad_lengths(<<131,$o>>),		%huge bignum
  864:     ok.
  865: 
  866: try_bad_lengths(B) ->
  867:     try_bad_lengths(B, 16#FFFFFFFF).
  868: 
  869: try_bad_lengths(B, L) when L > 16#FFFFFFF0 ->
  870:     Bin = <<B/binary,L:32>>,
  871:     io:format("~p\n", [Bin]),
  872:     {'EXIT',_} = (catch binary_to_term(Bin)),
  873:     try_bad_lengths(B, L-1);
  874: try_bad_lengths(_, _) -> ok.
  875: 
  876: 
  877: otp_6817(Config) when is_list(Config) ->
  878:     process_flag(min_heap_size, 20000),		%Use the heap, not heap fragments.
  879: 
  880:     %% Floats are only validated when the heap fragment has been allocated.
  881:     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>>,
  882:     ?line otp_6817_try_bin(BadFloat),
  883: 
  884:     %% {Binary,BadFloat}: When the error in float is discovered, a refc-binary
  885:     %% has been allocated and the list of refc-binaries goes through the
  886:     %% limbo area between the heap top and stack.
  887:     BinAndFloat = 
  888: 	<<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,
  889: 	 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,
  890: 	 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,
  891: 	 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,
  892: 	 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,
  893: 	 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
  894: 	 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
  895: 	 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,
  896: 	 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
  897: 	 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
  898: 	 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
  899: 	 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,
  900: 	 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48,
  901: 	 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>,
  902:     ?line otp_6817_try_bin(BinAndFloat),
  903: 
  904:     %% {Fun,BadFloat}
  905:     FunAndFloat =
  906: 	<<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84,
  907: 	 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,
  908: 	 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,
  909: 	 $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>>,
  910:     ?line otp_6817_try_bin(FunAndFloat),
  911: 
  912:     %% [ExternalPid|BadFloat]
  913:     ExtPidAndFloat =
  914: 	<<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101,
  915: 	 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,
  916: 	 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>,
  917:     ?line otp_6817_try_bin(ExtPidAndFloat),
  918:     ok.
  919: 
  920: otp_6817_try_bin(Bin) ->
  921:     erlang:garbage_collect(),
  922: 
  923:     %% If the bug is present, the heap pointer will moved when the invalid term
  924:     %% is found and we will have a linked list passing through the limbo area
  925:     %% between the heap top and the stack pointer.
  926:     catch binary_to_term(Bin),
  927: 
  928:     %% If the bug is present, we will overwrite the pointers in the limbo area.
  929:     Filler = erlang:make_tuple(1024, 16#3FA),
  930:     id(Filler),
  931: 
  932:     %% Will crash if the bug is present.
  933:     erlang:garbage_collect().
  934: 
  935: otp_8117(doc) -> "Some bugs in binary_to_term when 32-bit integers are negative.";
  936: otp_8117(suite) -> [];
  937: otp_8117(Config) when is_list(Config) ->
  938:     [otp_8117_do(Op,-(1 bsl N)) || Op <- ['fun',list,tuple],
  939: 				   N <- lists:seq(0,31)],
  940:     ok.
  941: 
  942: otp_8117_do('fun',Neg) ->
  943:     % Fun with negative num_free
  944:     FunBin = term_to_binary(fun() -> ok end),
  945:     ?line <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,   
  946:     ?line bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
  947: otp_8117_do(list,Neg) ->
  948:     %% List with negative length
  949:     ?line bad_bin_to_term(<<131,104,2,108,Neg:32,97,11,104,1,97,12,97,13,106,97,14>>);
  950: otp_8117_do(tuple,Neg) ->    
  951:     %% Tuple with negative arity
  952:     ?line bad_bin_to_term(<<131,104,2,105,Neg:32,97,11,97,12,97,13,97,14>>).
  953:     
  954: 
  955: ordering(doc) -> "Tests ordering of binaries.";
  956: ordering(suite) -> [];
  957: ordering(Config) when is_list(Config) ->
  958:     B1 = list_to_binary([7,8,9]),
  959:     B2 = make_sub_binary([1,2,3,4]),
  960:     B3 = list_to_binary([1,2,3,5]),
  961:     Unaligned = make_unaligned_sub_binary(B2),
  962: 
  963:     %% From R8 binaries are compared as strings.
  964: 
  965:     ?line false = B1 == B2,
  966:     ?line false = B1 =:= B2,
  967:     ?line true = B1 /= B2,
  968:     ?line true = B1 =/= B2,
  969: 
  970:     ?line true = B1 > B2,
  971:     ?line true = B2 < B3,
  972:     ?line true = B2 =< B1,
  973:     ?line true = B2 =< B3,
  974: 
  975:     ?line true = B2 =:= Unaligned,
  976:     ?line true = B2 == Unaligned,
  977:     ?line true = Unaligned < B3,
  978:     ?line true = Unaligned =< B3,
  979: 
  980:     %% Binaries are greater than all other terms.
  981: 
  982:     ?line true = B1 > 0,
  983:     ?line true = B1 > 39827491247298471289473333333333333333333333333333,
  984:     ?line true = B1 > -3489274937438742190467869234328742398347,
  985:     ?line true = B1 > 3.14,
  986:     ?line true = B1 > [],
  987:     ?line true = B1 > [a],
  988:     ?line true = B1 > {a},
  989:     ?line true = B1 > self(),
  990:     ?line true = B1 > make_ref(),
  991:     ?line true = B1 > xxx,
  992:     ?line true = B1 > fun() -> 1 end,
  993:     ?line true = B1 > fun erlang:send/2,
  994: 
  995:     ?line Path = ?config(priv_dir, Config),
  996:     ?line AFile = filename:join(Path, "vanilla_file"),
  997:     ?line Port = open_port(AFile, [out]),
  998:     ?line true = B1 > Port,
  999: 
 1000:     ?line true = B1 >= 0,
 1001:     ?line true = B1 >= 39827491247298471289473333333333333333333333333333,
 1002:     ?line true = B1 >= -3489274937438742190467869234328742398347,
 1003:     ?line true = B1 >= 3.14,
 1004:     ?line true = B1 >= [],
 1005:     ?line true = B1 >= [a],
 1006:     ?line true = B1 >= {a},
 1007:     ?line true = B1 >= self(),
 1008:     ?line true = B1 >= make_ref(),
 1009:     ?line true = B1 >= xxx,
 1010:     ?line true = B1 >= fun() -> 1 end,
 1011:     ?line true = B1 >= fun erlang:send/2,
 1012:     ?line true = B1 >= Port,
 1013: 
 1014:     ok.
 1015: 
 1016: %% Test that comparisions between binaries with different alignment work.
 1017: unaligned_order(Config) when is_list(Config) ->
 1018:     L = lists:seq(0, 7),
 1019:     [test_unaligned_order(I, J) || I <- L, J <- L], 
 1020:     ok.
 1021: 
 1022: test_unaligned_order(I, J) ->
 1023:     Align = {I,J},
 1024:     io:format("~p ~p", [I,J]),
 1025:     ?line true = test_unaligned_order_1('=:=', <<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
 1026: 					<<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
 1027: 					Align),
 1028:     ?line false = test_unaligned_order_1('=/=', <<1,2,3>>, <<1,2,3>>, Align),
 1029:     ?line true = test_unaligned_order_1('==', <<4,5,6>>, <<4,5,6>>, Align),
 1030:     ?line false = test_unaligned_order_1('/=', <<1,2,3>>, <<1,2,3>>, Align),
 1031: 
 1032:     ?line true = test_unaligned_order_1('<', <<1,2>>, <<1,2,3>>, Align),
 1033:     ?line true = test_unaligned_order_1('=<', <<1,2>>, <<1,2,3>>, Align),
 1034:     ?line true = test_unaligned_order_1('=<', <<1,2,7,8>>, <<1,2,7,8>>, Align),
 1035:     ok.
 1036: 
 1037: test_unaligned_order_1(Op, A, B, {Aa,Ba}) ->
 1038:     erlang:Op(unaligned_sub_bin(A, Aa), unaligned_sub_bin(B, Ba)).
 1039:     
 1040: test_terms(Test_Func) ->
 1041:     ?line Test_Func(atom),
 1042:     ?line Test_Func(''),
 1043:     ?line Test_Func('a'),
 1044:     ?line Test_Func('ab'),
 1045:     ?line Test_Func('abc'),
 1046:     ?line Test_Func('abcd'),
 1047:     ?line Test_Func('abcde'),
 1048:     ?line Test_Func('abcdef'),
 1049:     ?line Test_Func('abcdefg'),
 1050:     ?line Test_Func('abcdefgh'),
 1051: 
 1052:     ?line Test_Func(fun() -> ok end),
 1053:     X = id([a,{b,c},c]),
 1054:     Y = id({x,y,z}),
 1055:     Z = id(1 bsl 8*257),
 1056:     ?line Test_Func(fun() -> X end),
 1057:     ?line Test_Func(fun() -> {X,Y} end),
 1058:     ?line Test_Func([fun() -> {X,Y,Z} end,
 1059: 		     fun() -> {Z,X,Y} end,
 1060: 		     fun() -> {Y,Z,X} end]),
 1061: 
 1062:     ?line Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}),
 1063:     ?line Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}},
 1064: 		     {1,2,3}}),
 1065: 
 1066:     ?line Test_Func(1),
 1067:     ?line Test_Func(42),
 1068:     ?line Test_Func(-23),
 1069:     ?line Test_Func(256),
 1070:     ?line Test_Func(25555),
 1071:     ?line Test_Func(-3333),
 1072: 
 1073:     ?line Test_Func(1.0),
 1074: 
 1075:     ?line Test_Func(183749783987483978498378478393874),
 1076:     ?line Test_Func(-37894183749783987483978498378478393874),
 1077:     Very_Big = very_big_num(),
 1078:     ?line Test_Func(Very_Big),
 1079:     ?line Test_Func(-Very_Big+1),
 1080: 
 1081:     ?line Test_Func([]),
 1082:     ?line Test_Func("abcdef"),
 1083:     ?line Test_Func([a, b, 1, 2]),
 1084:     ?line Test_Func([a|b]),
 1085: 
 1086:     ?line Test_Func({}),
 1087:     ?line Test_Func({1}),
 1088:     ?line Test_Func({a, b}),
 1089:     ?line Test_Func({a, b, c}),
 1090:     ?line Test_Func(list_to_tuple(lists:seq(0, 255))),
 1091:     ?line Test_Func(list_to_tuple(lists:seq(0, 256))),
 1092: 
 1093:     ?line Test_Func(make_ref()),
 1094:     ?line Test_Func([make_ref(), make_ref()]),
 1095: 
 1096:     ?line Test_Func(make_port()),
 1097: 
 1098:     ?line Test_Func(make_pid()),
 1099: 
 1100:     ?line Test_Func(Bin0 = list_to_binary(lists:seq(0, 14))),
 1101:     ?line Test_Func(Bin1 = list_to_binary(lists:seq(0, ?heap_binary_size))),
 1102:     ?line Test_Func(Bin2 = list_to_binary(lists:seq(0, ?heap_binary_size+1))),
 1103:     ?line Test_Func(Bin3 = list_to_binary(lists:seq(0, 255))),
 1104: 
 1105:     ?line Test_Func(make_unaligned_sub_binary(Bin0)),
 1106:     ?line Test_Func(make_unaligned_sub_binary(Bin1)),
 1107:     ?line Test_Func(make_unaligned_sub_binary(Bin2)),
 1108:     ?line Test_Func(make_unaligned_sub_binary(Bin3)),
 1109: 
 1110:     ?line Test_Func(make_sub_binary(lists:seq(42, 43))),
 1111:     ?line Test_Func(make_sub_binary([42,43,44])),
 1112:     ?line Test_Func(make_sub_binary([42,43,44,45])),
 1113:     ?line Test_Func(make_sub_binary([42,43,44,45,46])),
 1114:     ?line Test_Func(make_sub_binary([42,43,44,45,46,47])),
 1115:     ?line Test_Func(make_sub_binary([42,43,44,45,46,47,48])),
 1116:     ?line Test_Func(make_sub_binary(lists:seq(42, 49))),
 1117:     ?line Test_Func(make_sub_binary(lists:seq(0, 14))),
 1118:     ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))),
 1119:     ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))),
 1120:     ?line Test_Func(make_sub_binary(lists:seq(0, 255))),
 1121: 
 1122:     ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))),
 1123:     ?line Test_Func(make_unaligned_sub_binary([42,43,44])),
 1124:     ?line Test_Func(make_unaligned_sub_binary([42,43,44,45])),
 1125:     ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46])),
 1126:     ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])),
 1127:     ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])),
 1128:     ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))),
 1129:     ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))),
 1130:     ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))),
 1131:     ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))),
 1132:     ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))),
 1133: 
 1134:     %% Bit level binaries.
 1135:     ?line Test_Func(<<1:1>>),
 1136:     ?line Test_Func(<<2:2>>),
 1137:     ?line Test_Func(<<42:10>>),
 1138:     ?line Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
 1139: 
 1140:     ?line Test_Func(F = fun(A) -> 42*A end),
 1141:     ?line Test_Func(lists:duplicate(32, F)),
 1142: 
 1143:     ?line Test_Func(FF = fun binary_SUITE:all/0),
 1144:     ?line Test_Func(lists:duplicate(32, FF)),
 1145: 
 1146:     ok.
 1147: 
 1148: test_floats(Test_Func) ->
 1149:     ?line Test_Func(5.5),
 1150:     ?line Test_Func(-15.32),
 1151:     ?line Test_Func(1.2435e25),
 1152:     ?line Test_Func(1.2333e-20),
 1153:     ?line Test_Func(199.0e+15),
 1154:     ok.
 1155: 
 1156: very_big_num() ->
 1157:     very_big_num(33, 1).
 1158: 
 1159: very_big_num(Left, Result) when Left > 0 ->
 1160:     ?line very_big_num(Left-1, Result*256);
 1161: very_big_num(0, Result) ->
 1162:     ?line Result.
 1163: 
 1164: make_port() ->
 1165:     ?line open_port({spawn, efile}, [eof]).
 1166: 
 1167: make_pid() ->
 1168:     ?line spawn_link(?MODULE, sleeper, []).
 1169: 
 1170: sleeper() ->
 1171:     ?line receive after infinity -> ok end.
 1172: 
 1173: 
 1174: %% Test that binaries are garbage collected properly.
 1175: gc_test(Config) when is_list(Config) ->
 1176:     %% Note: This test is only relevant for REFC binaries.
 1177:     %% Therefore, we take care that all binaries are REFC binaries.
 1178:     B = list_to_binary(lists:seq(0, ?heap_binary_size)),
 1179:     Self = self(),
 1180:     F1 = fun() ->
 1181: 		 gc(),
 1182: 		 {binary,[]} = process_info(self(), binary),
 1183: 		 Self ! {self(),done}
 1184: 	 end,
 1185:     F = fun() ->
 1186: 		receive go -> ok end,
 1187: 		{binary,[{_,65,1}]} = process_info(self(), binary),
 1188: 		gc(),
 1189: 		{B1,B2} = my_split_binary(B, 4),
 1190: 		gc(),
 1191: 		gc(),
 1192: 		{binary,L1} = process_info(self(), binary),
 1193: 		[Binfo1,Binfo2,Binfo3] = L1,
 1194: 		{_,65,3} = Binfo1 = Binfo2 = Binfo3,
 1195: 		65 = size(B),
 1196: 		4 = size(B1),
 1197: 		61 = size(B2),
 1198: 		F1()
 1199: 	end,
 1200:     gc(),
 1201:     gc(),
 1202:     65 = size(B),
 1203:     gc_test1(spawn_opt(erlang, apply, [F,[]], [link,{fullsweep_after,0}])).
 1204: 
 1205: gc_test1(Pid) ->
 1206:     gc(),
 1207:     Pid ! go,
 1208:     receive
 1209: 	{Pid,done} -> ok
 1210:     after 10000 ->
 1211: 	    ?line ?t:fail()
 1212:     end.
 1213: 
 1214: %% Like split binary, but returns REFC binaries. Only useful for gc_test/1.
 1215: 
 1216: my_split_binary(B, Pos) ->
 1217:     Self = self(),
 1218:     Ref = make_ref(),
 1219:     spawn(fun() -> Self ! {Ref,split_binary(B, Pos)} end),
 1220:     receive
 1221: 	{Ref,Result} -> Result
 1222:     end.
 1223: 
 1224: gc() ->
 1225:     erlang:garbage_collect(),
 1226:     gc1().
 1227: gc1() -> ok.
 1228: 
 1229: bit_sized_binary_sizes(Config) when is_list(Config) ->
 1230:     ?line [bsbs_1(A) || A <- lists:seq(1, 8)],
 1231:     ok.
 1232: 
 1233: bsbs_1(A) ->
 1234:     BinSize = 32+A,
 1235:     io:format("A: ~p BinSize: ~p", [A,BinSize]),
 1236:     Bin = binary_to_term(<<131,$M,5:32,A,0,0,0,0,0>>),
 1237:     BinSize = bit_size(Bin).
 1238: 
 1239: deep(Config) when is_list(Config) ->
 1240:     ?line deep_roundtrip(lists:foldl(fun(E, A) ->
 1241: 					     [E,A]
 1242: 				     end, [], lists:seq(1, 1000000))),
 1243:     ?line deep_roundtrip(lists:foldl(fun(E, A) ->
 1244: 					     {E,A}
 1245: 				     end, [], lists:seq(1, 1000000))),
 1246:     ?line deep_roundtrip(lists:foldl(fun(E, A) ->
 1247: 					     fun() -> {E,A} end
 1248: 				     end, [], lists:seq(1, 1000000))),
 1249:     ok.
 1250: 
 1251: deep_roundtrip(T) ->
 1252:     B = term_to_binary(T),
 1253:     T = binary_to_term(B).
 1254: 
 1255: obsolete_funs(Config) when is_list(Config) ->
 1256:     erts_debug:set_internal_state(available_internal_state, true),
 1257: 
 1258:     X = id({1,2,3}),
 1259:     Y = id([a,b,c,d]),
 1260:     Z = id({x,y,z}),
 1261:     ?line obsolete_fun(fun() -> ok end),
 1262:     ?line obsolete_fun(fun() -> X end),
 1263:     ?line obsolete_fun(fun(A) -> {A,X} end),
 1264:     ?line obsolete_fun(fun() -> {X,Y} end),
 1265:     ?line obsolete_fun(fun() -> {X,Y,Z} end),
 1266: 
 1267:     ?line obsolete_fun(fun ?MODULE:all/1),
 1268: 
 1269:     erts_debug:set_internal_state(available_internal_state, false),
 1270:     ok.
 1271: 
 1272: obsolete_fun(Fun) ->
 1273:     Tuple = case erlang:fun_info(Fun, type) of
 1274: 		{type,external} ->
 1275: 		    {module,M} = erlang:fun_info(Fun, module),
 1276: 		    {name,F} = erlang:fun_info(Fun, name),
 1277: 		    {M,F};
 1278: 		{type,local} ->
 1279: 		    {module,M} = erlang:fun_info(Fun, module),
 1280: 		    {index,I} = erlang:fun_info(Fun, index),
 1281: 		    {uniq,U} = erlang:fun_info(Fun, uniq),
 1282: 		    {env,E} = erlang:fun_info(Fun, env),
 1283: 		    {'fun',M,I,U,list_to_tuple(E)}
 1284: 	    end,
 1285:     Tuple = no_fun_roundtrip(Fun).
 1286: 
 1287: no_fun_roundtrip(Term) ->
 1288:     binary_to_term(erts_debug:get_internal_state({term_to_binary_no_funs,Term})).
 1289: 
 1290: %% Test non-standard encodings never generated by term_to_binary/1
 1291: %% but recognized by binary_to_term/1.
 1292: 
 1293: robustness(Config) when is_list(Config) ->
 1294:     ?line [] = binary_to_term(<<131,107,0,0>>),	%Empty string.
 1295:     ?line [] = binary_to_term(<<131,108,0,0,0,0,106>>),	%Zero-length list.
 1296: 
 1297:     %% {[],a} where [] is a zero-length list.
 1298:     ?line {[],a} = binary_to_term(<<131,104,2,108,0,0,0,0,106,100,0,1,97>>),
 1299: 
 1300:     %% {42,a} where 42 is a zero-length list with 42 in the tail.
 1301:     ?line {42,a} = binary_to_term(<<131,104,2,108,0,0,0,0,97,42,100,0,1,97>>),
 1302: 
 1303:     %% {{x,y},a} where {x,y} is a zero-length list with {x,y} in the tail.
 1304:     ?line {{x,y},a} = binary_to_term(<<131,104,2,108,0,0,0,0,
 1305: 				      104,2,100,0,1,120,100,0,1,
 1306: 				      121,100,0,1,97>>),
 1307: 
 1308:     %% Bignums fitting in 32 bits.
 1309:     ?line 16#7FFFFFFF = binary_to_term(<<131,98,127,255,255,255>>),
 1310:     ?line -1 = binary_to_term(<<131,98,255,255,255,255>>),
 1311:     
 1312:     ok.
 1313: 
 1314: %% OTP-8180: Test several terms that have been known to crash the emulator.
 1315: %% (Thanks to Scott Lystig Fritchie.)
 1316: otp_8180(Config) when is_list(Config) ->
 1317:     ?line Data = ?config(data_dir, Config),
 1318:     ?line Wc = filename:join(Data, "zzz.*"),
 1319:     Files = filelib:wildcard(Wc),
 1320:     [run_otp_8180(F) || F <- Files],
 1321:     ok.
 1322: 
 1323: run_otp_8180(Name) ->
 1324:     io:format("~s", [Name]),
 1325:     ?line {ok,Bins} = file:consult(Name),
 1326:     [begin
 1327: 	 io:format("~p\n", [Bin]),
 1328: 	 ?line {'EXIT',{badarg,_}} = (catch binary_to_term(Bin))
 1329:      end || Bin <- Bins],
 1330:     ok.
 1331: 
 1332: %% Test that exit and GC during term_to_binary trap does not crash.
 1333: ttb_trap(Config) when is_list(Config)->
 1334:     case erlang:system_info(wordsize) of
 1335: 	N when N < 8 ->
 1336: 	    {skipped, "Only on 64bit machines"};
 1337: 	_ ->
 1338: 	    do_ttb_trap(5)
 1339:     end.
 1340: 
 1341: do_ttb_trap(0) ->
 1342:     ok;
 1343: do_ttb_trap(N) ->
 1344:     Pid = spawn(?MODULE,ttb_loop,[1000,self()]),
 1345:     receive ok -> ok end,
 1346:     receive after 100 -> ok end,
 1347:     erlang:garbage_collect(Pid),
 1348:     receive after 100 -> ok end,
 1349:     exit(Pid,kill),
 1350:     receive after 1 -> ok end,
 1351:     do_ttb_trap(N-1).
 1352: 
 1353: ttb_loop(N,Pid) ->
 1354:     Term = lists:duplicate(2000000,2000000),
 1355:     Pid ! ok,
 1356:     ttb_loop2(N,Term).
 1357: ttb_loop2(0,_T) ->
 1358:     ok;
 1359: ttb_loop2(N,T) ->
 1360:     apply(erlang,term_to_binary,[T]),
 1361:     ttb_loop2(N-1,T).
 1362: 
 1363: 
 1364: %% Utilities.
 1365: 
 1366: make_sub_binary(Bin) when is_binary(Bin) ->
 1367:     {_,B} = split_binary(list_to_binary([0,1,3,Bin]), 3),
 1368:     B;
 1369: make_sub_binary(List) ->
 1370:     make_sub_binary(list_to_binary(List)).
 1371: 
 1372: make_unaligned_sub_binary(Bin0) when is_binary(Bin0) ->
 1373:     Bin1 = <<0:3,Bin0/binary,31:5>>,
 1374:     Sz = size(Bin0),
 1375:     <<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
 1376:     Bin;
 1377: make_unaligned_sub_binary(List) ->
 1378:     make_unaligned_sub_binary(list_to_binary(List)).
 1379: 
 1380: %% Add 1 bit to the size of the binary.
 1381: bit_sized_binary(Bin0) ->
 1382:     Bin = <<Bin0/binary,1:1>>,
 1383:     BitSize = bit_size(Bin),
 1384:     BitSize = 8*size(Bin) + 1,
 1385:     Bin.
 1386: 
 1387: unaligned_sub_bin(Bin, 0) -> Bin;
 1388: unaligned_sub_bin(Bin0, Offs) ->
 1389:     F = random:uniform(256),
 1390:     Roffs = 8-Offs,
 1391:     Bin1 = <<F:Offs,Bin0/binary,F:Roffs>>,
 1392:     Sz = size(Bin0),
 1393:     <<_:Offs,Bin:Sz/binary,_:Roffs>> = id(Bin1),
 1394:     Bin.
 1395: 
 1396: id(I) -> I.