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.