1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2000-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(bs_construct_SUITE). 22 23%% Copied from bs_construct_SUITE in the emulator test suite. 24%% The following test cases have been omitted since they don't 25%% make much sense for the debugger: 26%% bs_add 27%% kostis 28 29-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 30 init_per_testcase/2,end_per_testcase/2, 31 init_per_suite/1,end_per_suite/1, 32 test1/1, test2/1, test3/1, test4/1, test5/1, testf/1, 33 not_used/1, in_guard/1, 34 mem_leak/1, coerce_to_float/1, bjorn/1, 35 huge_float_field/1, huge_binary/1, system_limit/1, badarg/1, 36 copy_writable_binary/1, dynamic/1, 37 otp_7422/1, zero_width/1]). 38 39-include_lib("common_test/include/ct.hrl"). 40 41suite() -> 42 [{ct_hooks,[ts_install_cth]}, 43 {timetrap,{minutes,15}}]. 44 45all() -> 46 [test1, test2, test3, test4, test5, testf, not_used, 47 in_guard, mem_leak, coerce_to_float, bjorn, 48 huge_float_field, huge_binary, system_limit, badarg, 49 copy_writable_binary, dynamic, otp_7422, zero_width]. 50 51groups() -> 52 []. 53 54init_per_group(_GroupName, Config) -> 55 Config. 56 57end_per_group(_GroupName, Config) -> 58 Config. 59 60init_per_testcase(_Case, Config) -> 61 test_lib:interpret(?MODULE), 62 Config. 63 64end_per_testcase(_Case, _Config) -> 65 ok. 66 67init_per_suite(Config) when is_list(Config) -> 68 test_lib:interpret(?MODULE), 69 true = lists:member(?MODULE, int:interpreted()), 70 Config. 71 72end_per_suite(Config) when is_list(Config) -> 73 ok. 74 75big(1) -> 76 57285702734876389752897683. 77 78i(X) -> X. 79 80r(L) -> 81 lists:reverse(L). 82 83-define(T(B, L), {B, ??B, L}). 84-define(N(B), {B, ??B, unknown}). 85 86-define(FAIL(Expr), fail_check(catch Expr, ??Expr, [])). 87 88-define(FAIL_VARS(Expr, Vars), fail_check(catch Expr, ??Expr, Vars)). 89 90l(I_13, I_big1) -> 91 [ 92 ?T(<<-43>>, 93 [256-43]), 94 ?T(<<56>>, 95 [56]), 96 ?T(<<1,2>>, 97 [1, 2]), 98 ?T(<<4:4, 7:4>>, 99 [4*16+7]), 100 ?T(<<777:16/big>>, 101 [3, 9]), 102 ?T(<<777:16/little>>, 103 [9, 3]), 104 ?T(<<0.0:32/float>>, 105 [0,0,0,0]), 106 ?T(<<0.125:32/float>>, 107 [62,0,0,0]), 108 ?T(<<0.125:32/little-float>>, 109 [0,0,0,62]), 110 ?T(<<I_big1:32>>, 111 [138, 99, 0, 147]), 112 ?T(<<57285702734876389752897684:32>>, 113 [138, 99, 0, 148]), 114 ?T(<<I_big1:32/little>>, 115 r([138, 99, 0, 147])), 116 ?T(<<-1:17/unit:8>>, 117 lists:duplicate(17, 255)), 118 119 ?T(<<I_13>>, 120 [13]), 121 122 ?T(<<4:8/unit:2,5:2/unit:8>>, 123 [0, 4, 0, 5]), 124 125 ?T(<<1:1, 0:6, 1:1>>, 126 [129]), 127 ?T(<<1:1/little, 0:6/little, 1:1/little>>, 128 [129]), 129 130 ?T(<<<<1,2>>/binary>>, 131 [1, 2]), 132 ?T(<<<<1,2>>:1/binary>>, 133 [1]), 134 ?T(<<4,3,<<1,2>>:1/binary>>, 135 [4,3,1]), 136 137 ?T(<<(256*45+47)>>, 138 [47]), 139 140 ?T(<<57:0>>, 141 []), 142 143 ?T(<<"apa">>, 144 "apa"), 145 146 ?T(<<1:3,"string",9:5>>, 147 [46,110,142,77,45,204,233]), 148 149 ?T(<<>>, 150 []), 151 152 ?T(<<37.98:64/native-float>>, 153 native_3798()), 154 155 ?T(<<32978297842987249827298387697777669766334937:128/native-integer>>, 156 native_bignum()), 157 158 %% Unit tests. 159 ?T(<<<<5:3>>/bitstring>>, <<5:3>>), 160 ?T(<<42,<<7:4>>/binary-unit:4>>, <<42,7:4>>), 161 ?T(<<<<344:17>>/binary-unit:17>>, <<344:17>>), 162 ?T(<<<<42,3,7656:16>>/binary-unit:16>>, <<42,3,7656:16>>) 163 164 ]. 165 166native_3798() -> 167 case <<1:16/native>> of 168 <<0,1>> -> [64,66,253,112,163,215,10,61]; 169 <<1,0>> -> [61,10,215,163,112,253,66,64] 170 end. 171 172native_bignum() -> 173 case <<1:16/native>> of 174 <<0,1>> -> [129,205,18,177,1,213,170,101,39,231,109,128,176,11,73,217]; 175 <<1,0>> -> [217,73,11,176,128,109,231,39,101,170,213,1,177,18,205,129] 176 end. 177 178evaluate(Str, Vars) -> 179 {ok,Tokens,_} = 180 erl_scan:string(Str ++ " . "), 181 {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 182 case erl_eval:expr(Expr, Vars) of 183 {value, Result, _} -> 184 Result 185 end. 186 187eval_list([], _Vars) -> 188 []; 189eval_list([{C_bin, Str, Bytes} | Rest], Vars) -> 190 case catch evaluate(Str, Vars) of 191 {'EXIT', Error} -> 192 io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]), 193 exit(Error); 194 E_bin -> 195 [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)] 196 end. 197 198one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) -> 199 io:format(" ~s, ~p~n", [Str, Bytes]), 200 Bin = list_to_binary(Bytes), 201 if 202 C_bin == Bin -> 203 ok; 204 true -> 205 io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n", 206 [Str, Bytes, binary_to_list(C_bin)]), 207 ct:fail(comp) 208 end, 209 if 210 E_bin == Bin -> 211 ok; 212 true -> 213 io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n", 214 [Str, Bytes, binary_to_list(E_bin)]), 215 ct:fail(comp) 216 end; 217one_test({C_bin, E_bin, Str, Result}) -> 218 io:format(" ~s ~p~n", [Str, C_bin]), 219 if 220 C_bin == E_bin -> 221 ok; 222 true -> 223 Arbitrary = case Result of 224 unknown -> 225 size(C_bin); 226 _ -> 227 Result 228 end, 229 case equal_lists(binary_to_list(C_bin), 230 binary_to_list(E_bin), 231 Arbitrary) of 232 false -> 233 io:format("ERROR: Compiled not equal to interpreted:" 234 "~n ~p, ~p.~n", 235 [binary_to_list(C_bin), binary_to_list(E_bin)]), 236 ct:fail(comp); 237 0 -> 238 ok; 239 %% For situations where the final bits may not matter, like 240 %% for floats: 241 N when is_integer(N) -> 242 io:format("Info: compiled and interpreted differ in the" 243 " last bytes:~n ~p, ~p.~n", 244 [binary_to_list(C_bin), binary_to_list(E_bin)]), 245 ok 246 end 247 end. 248 249equal_lists([], [], _) -> 250 0; 251equal_lists([], _, _) -> 252 false; 253equal_lists(_, [], _) -> 254 false; 255equal_lists([A|AR], [A|BR], R) -> 256 equal_lists(AR, BR, R); 257equal_lists(A, B, R) -> 258 if 259 length(A) /= length(B) -> 260 false; 261 length(A) =< R -> 262 R; 263 true -> 264 false 265 end. 266 267fail_check({'EXIT',{badarg,_}}, Str, Vars) -> 268 try evaluate(Str, Vars) of 269 Res -> 270 io:format("Interpreted result: ~p", [Res]), 271 ct:fail(did_not_fail_in_intepreted_code) 272 catch 273 error:badarg -> 274 ok 275 end; 276fail_check(Res, _, _) -> 277 io:format("Compiled result: ~p", [Res]), 278 ct:fail(did_not_fail_in_compiled_code). 279 280%%% Simple working cases 281test1(Config) when is_list(Config) -> 282 I_13 = i(13), 283 I_big1 = big(1), 284 Vars = [{'I_13', I_13}, 285 {'I_big1', I_big1}], 286 lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1), Vars)). 287 288%%% Misc 289 290%%% <<A:S, A:(N-S)>> 291comp(N, A, S) -> 292 M1 = (1 bsl S) - 1, 293 M2 = (1 bsl (N-S)) - 1, 294 [((A band M1) bsl (N-S)) bor (A band M2)]. 295 296gen(N, S, A) -> 297 [?T(<<A:S, A:(N-S)>>, comp(N, A, S))]. 298 299gen_l(N, S, A) -> 300 [?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))]. 301 302test2(Config) when is_list(Config) -> 303 test2(0, 8, 2#10101010101010101), 304 test2(0, 8, 2#1111111111). 305 306test2(End, End, _) -> 307 ok; 308test2(I, End, A) -> 309 test2(I, A), 310 test2(I+1, End, A). 311 312test2(S, A) -> 313 N = 8, 314 Vars = [{'A',A}, {'N',N}, {'S',S}], 315 io:format("Vars: ~p\n", [Vars]), 316 lists:foreach(fun one_test/1, eval_list(gen(N, S, A), Vars)), 317 lists:foreach(fun one_test/1, eval_list(gen_l(N, S, A), Vars)). 318 319%%% Tests without facit 320 321t3() -> 322 [?N(<<4711:13, 9876:13, 3:6>>), 323 ?N(<<4.57:64/float>>), 324 ?N(<<4.57:32/float>>), 325 326 ?N(<<>>) 327 ]. 328 329test3(Config) when is_list(Config) -> 330 Vars = [], 331 lists:foreach(fun one_test/1, eval_list(t3(), Vars)). 332 333gen_u(N, S, A) -> 334 [?N(<<A:S, A:(N-S)>>)]. 335 336gen_u_l(N, S, A) -> 337 [?N(<<A:S/little, A:(N-S)/little>>)]. 338 339test4(Config) when is_list(Config) -> 340 test4(0, 16, 2#10101010101010101), 341 test4(0, 16, 2#1111111111). 342 343test4(End, End, _) -> 344 ok; 345test4(I, End, A) -> 346 test4(I, A), 347 test4(I+1, End, A). 348 349test4(S, A) -> 350 N = 16, 351 Vars = [{'A', A}, {'N', 16}, {'S', S}], 352 lists:foreach(fun one_test/1, eval_list(gen_u(N, S, A), Vars)), 353 lists:foreach(fun one_test/1, eval_list(gen_u_l(N, S, A), Vars)). 354 355gen_b(N, S, A) -> 356 [?T(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>, 357 binary_to_list(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>))]. 358 359%% OTP-3995. 360test5(Config) when is_list(Config) -> 361 test5(0, 8, <<73>>), 362 test5(0, 8, <<68>>). 363 364test5(End, End, _) -> 365 ok; 366test5(I, End, A) -> 367 test5(I, A), 368 test5(I+1, End, A). 369 370test5(S, A) -> 371 N = 8, 372 Vars = [{'A', A}, {'N', 8}, {'S', S}], 373 lists:foreach(fun one_test/1, eval_list(gen_b(N, S, A), Vars)). 374 375%%% Failure cases 376testf(Config) when is_list(Config) -> 377 ?FAIL(<<3.14>>), 378 ?FAIL(<<<<1,2>>>>), 379 380 ?FAIL(<<2.71/binary>>), 381 ?FAIL(<<24334/binary>>), 382 ?FAIL(<<24334344294788947129487129487219847/binary>>), 383 BigInt = id(24334344294788947129487129487219847), 384 ?FAIL_VARS(<<BigInt/binary>>, [{'BigInt',BigInt}]), 385 ?FAIL_VARS(<<42,BigInt/binary>>, [{'BigInt',BigInt}]), 386 ?FAIL_VARS(<<BigInt:2/binary>>, [{'BigInt',BigInt}]), 387 388 %% One negative field size, but the sum of field sizes will be 1 byte. 389 %% Make sure that we reject that properly. 390 I_minus_777 = id(-777), 391 I_minus_2047 = id(-2047), 392 ?FAIL_VARS(<<I_minus_777:2048/unit:8,57:I_minus_2047/unit:8>>, 393 ordsets:from_list([{'I_minus_777',I_minus_777}, 394 {'I_minus_2047',I_minus_2047}])), 395 ?FAIL(<<<<1,2,3>>/float>>), 396 397 %% Negative field widths. 398 testf_1(-8, <<1,2,3,4,5>>), 399 ?FAIL(<<0:(-(1 bsl 100))>>), 400 401 ?FAIL(<<42:(-16)>>), 402 ?FAIL(<<3.14:(-8)/float>>), 403 ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>), 404 ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>), 405 ?FAIL(<<<<23,56,0,2>>:(anka)>>), 406 ?FAIL(<<<<23,56,0,2>>:(anka)>>), 407 408 %% Unit failures. 409 ?FAIL(<<<<1:1>>/binary>>), 410 Sz = id(1), 411 ?FAIL_VARS(<<<<1:Sz>>/binary>>, [{'Sz',Sz}]), 412 {'EXIT',{badarg,_}} = (catch <<<<1:(id(1))>>/binary>>), 413 ?FAIL(<<<<7,8,9>>/binary-unit:16>>), 414 ?FAIL(<<<<7,8,9,3:7>>/binary-unit:16>>), 415 ?FAIL(<<<<7,8,9,3:7>>/binary-unit:17>>), 416 417 ok. 418 419testf_1(W, B) -> 420 Vars = [{'W',W}], 421 ?FAIL_VARS(<<42:W>>, Vars), 422 ?FAIL_VARS(<<3.14:W/float>>, Vars), 423 ?FAIL_VARS(<<B:W/binary>>, [{'B',B}|Vars]). 424 425%% Test that constructed binaries that are not used will still give an exception. 426not_used(Config) when is_list(Config) -> 427 ok = not_used1(3, <<"dum">>), 428 {'EXIT',{badarg,_}} = (catch not_used1(3, "dum")), 429 {'EXIT',{badarg,_}} = (catch not_used2(444, -2)), 430 {'EXIT',{badarg,_}} = (catch not_used2(444, anka)), 431 {'EXIT',{badarg,_}} = (catch not_used3(444)), 432 ok. 433 434not_used1(I, BinString) -> 435 <<I:32,BinString/binary>>, 436 ok. 437 438not_used2(I, Sz) -> 439 <<I:Sz>>, 440 ok. 441 442not_used3(I) -> 443 <<I:(-8)>>, 444 ok. 445 446in_guard(Config) when is_list(Config) -> 447 1 = in_guard(<<16#74ad:16>>, 16#e95, 5), 448 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), 449 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), 450 3 = in_guard(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3), 451 3 = in_guard(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226), 452 nope = in_guard(<<1>>, 42, b), 453 nope = in_guard(<<1>>, a, b), 454 nope = in_guard(<<1,2>>, 1, 1), 455 nope = in_guard(<<4,5>>, 1, 2.71), 456 nope = in_guard(<<4,5>>, 1, <<12,13>>), 457 ok. 458 459in_guard(Bin, A, B) when <<A:13,B:3>> == Bin -> 1; 460in_guard(Bin, A, B) when <<A:16,B/binary>> == Bin -> 2; 461in_guard(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3; 462in_guard(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen; 463in_guard(_, _, _) -> nope. 464 465%% Make sure that construction has no memory leak. 466mem_leak(Config) when is_list(Config) -> 467 B = make_bin(16, <<0>>), 468 mem_leak(1024, B), 469 ok. 470 471mem_leak(0, _) -> ok; 472mem_leak(N, B) -> 473 big_bin(B, <<23>>), 474 {'EXIT',{badarg,_}} = (catch big_bin(B, bad)), 475 mem_leak(N-1, B). 476 477big_bin(B1, B2) -> 478 <<B1/binary,B1/binary,B1/binary,B1/binary, 479 B1/binary,B1/binary,B1/binary,B1/binary, 480 B1/binary,B1/binary,B1/binary,B1/binary, 481 B1/binary,B1/binary,B1/binary,B1/binary, 482 B2/binary>>. 483 484make_bin(0, Acc) -> Acc; 485make_bin(N, Acc) -> make_bin(N-1, <<Acc/binary,Acc/binary>>). 486 487-define(COF(Int0), 488 (fun(Int) -> 489 true = <<Int:32/float>> =:= <<(float(Int)):32/float>>, 490 true = <<Int:64/float>> =:= <<(float(Int)):64/float>> 491 end)(nonliteral(Int0)), 492 true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>, 493 true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). 494 495-define(COF64(Int0), 496 (fun(Int) -> 497 true = <<Int:64/float>> =:= <<(float(Int)):64/float>> 498 end)(nonliteral(Int0)), 499 true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). 500 501nonliteral(X) -> X. 502 503coerce_to_float(Config) when is_list(Config) -> 504 ?COF(0), 505 ?COF(-1), 506 ?COF(1), 507 ?COF(42), 508 ?COF(255), 509 ?COF(-255), 510 ?COF(38474), 511 ?COF(387498738948729893849444444443), 512 ?COF(-37489378937773899999999999999993), 513 ?COF64(298748888888888888888888888883478264866528467367364766666666666666663), 514 ?COF64(-367546729879999999999947826486652846736736476555566666663), 515 ok. 516 517bjorn(Config) when is_list(Config) -> 518 error = bjorn_1(), 519 ok. 520 521bjorn_1() -> 522 Bitstr = <<7:13>>, 523 try 524 do_something() 525 catch 526 throw:blurf -> 527 ignore 528 end, 529 do_more(Bitstr, 13). 530 531do_more(Bin, Sz) -> 532 %% Previous bug in the bs_bits_to_bytes instruction: The exeption code 533 %% was not set - the previous exception (throw:blurf) would be used, 534 %% causing the catch to slip. 535 try <<Bin:Sz/binary>> of 536 _V -> ok 537 catch 538 error:_ -> 539 error 540 end. 541 542do_something() -> 543 throw(blurf). 544 545huge_float_field(Config) when is_list(Config) -> 546 {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>), 547 huge_float_check(catch <<0.0:67108865/float-unit:64>>), 548 huge_float_check(catch <<0.0:((1 bsl 26)+1)/float-unit:64>>), 549 huge_float_check(catch <<0.0:(id(67108865))/float-unit:64>>), 550 %% huge_float_check(catch <<0.0:((1 bsl 60)+1)/float-unit:64>>), 551 huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 26)+1)/float-unit:64>>), 552 %% huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 60)+1)/float-unit:64>>), 553 ok. 554 555huge_float_check({'EXIT',{system_limit,_}}) -> ok; 556huge_float_check({'EXIT',{badarg,_}}) -> ok. 557 558huge_binary(Config) when is_list(Config) -> 559 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>), 560 ok. 561 562system_limit(Config) when is_list(Config) -> 563 WordSize = erlang:system_info(wordsize), 564 BitsPerWord = WordSize * 8, 565 {'EXIT',{system_limit,_}} = 566 (catch <<0:(id(0)),42:(id(1 bsl BitsPerWord))>>), 567 {'EXIT',{system_limit,_}} = 568 (catch <<42:(id(1 bsl BitsPerWord)),0:(id(0))>>), 569 {'EXIT',{system_limit,_}} = 570 (catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>), 571 572 case WordSize of 573 4 -> 574 system_limit_32(); 575 8 -> 576 ok 577 end. 578 579system_limit_32() -> 580 {'EXIT',{badarg,_}} = (catch <<42:(-1)>>), 581 {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>), 582 {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>), 583 {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>), 584 {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>), 585 {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>), 586 {'EXIT',{system_limit,_}} = 587 (catch <<0:(id(8)),42:(id(536870912))/unit:8>>), 588 ok. 589 590badarg(Config) when is_list(Config) -> 591 %% BEAM will generate a badarg exception for: 592 %% <<0:(id(1 bsl 100)),0:(id(-1))>> 593 %% but the debugger will generate a system_limit exception. 594 %% It does not seems worthwhile to fix the debugger. 595 596 {'EXIT',{badarg,_}} = 597 (catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>), 598 599 ok. 600 601copy_writable_binary(Config) when is_list(Config) -> 602 [copy_writable_binary_1(I) || I <- lists:seq(0, 256)], 603 ok. 604 605copy_writable_binary_1(_) -> 606 Bin0 = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>, 607 SubBin = make_sub_bin(Bin0), 608 id(<<42,34,55,Bin0/binary>>), %Make reallocation likelier. 609 Pid = spawn(fun() -> 610 copy_writable_binary_holder(Bin0, SubBin) 611 end), 612 Tab = ets:new(holder, []), 613 ets:insert(Tab, {17,Bin0}), 614 ets:insert(Tab, {42,SubBin}), 615 id(<<Bin0/binary,0:(64*1024*8)>>), 616 Pid ! self(), 617 [{17,Bin0}] = ets:lookup(Tab, 17), 618 [{42,Bin0}] = ets:lookup(Tab, 42), 619 receive 620 {Pid,Bin0,Bin0} -> ok; 621 Other -> 622 io:format("Unexpected message: ~p", [Other]), 623 ct:fail(failed) 624 end, 625 ok. 626 627copy_writable_binary_holder(Bin, SubBin) -> 628 receive 629 Pid -> 630 Pid ! {self(),Bin,SubBin} 631 end. 632 633make_sub_bin(Bin0) -> 634 N = bit_size(Bin0), 635 <<_:17,Bin:N/bitstring,_:5>> = <<(-1):17,Bin0/bitstring,(-1):5>>, 636 Bin = Bin0, %Assertion. 637 Bin. 638 639%% Test that different ways of using bit syntax instructions 640%% give the same result. 641 642dynamic(Config) when is_list(Config) -> 643 Ps = [spawn_monitor(fun() -> 644 dynamic_1(Fun) 645 end) || Fun <- [fun dynamic_big/5, 646 fun dynamic_little/5]], 647 [receive 648 {'DOWN',Ref,process,Pid,normal} -> 649 ok; 650 {'DOWN',Ref,process,Pid,Exit} -> 651 ct:fail({Pid,Exit}) 652 end || {Pid,Ref} <- Ps], 653 ok. 654 655dynamic_1(Dynamic) -> 656 <<Lpad:64,_/binary>> = erlang:md5([0]), 657 <<Rpad:64,_/binary>> = erlang:md5([1]), 658 <<Int:64,_/binary>> = erlang:md5([2]), 659 2145 = dynamic_2(0, {Int,Lpad,Rpad,Dynamic}, 0). 660 661dynamic_2(64+1, _, Count) -> Count; 662dynamic_2(Bef, Data, Count0) -> 663 Count = dynamic_3(Bef, 64-Bef, Data, Count0), 664 dynamic_2(Bef+1, Data, Count). 665 666dynamic_3(_, -1, _, Count) -> Count; 667dynamic_3(Bef, N, {Int0,Lpad,Rpad,Dynamic}=Data, Count) -> 668 Int1 = Int0 band ((1 bsl (N+3))-1), 669 Dynamic(Bef, N, Int1, Lpad, Rpad), 670 Dynamic(Bef, N, -Int1, Lpad, Rpad), 671 672 %% OTP-7085: Test a small number in a wide field. 673 Int2 = Int0 band 16#FFFFFF, 674 Dynamic(Bef, N, Int2, Lpad, Rpad), 675 Dynamic(Bef, N, -Int2, Lpad, Rpad), 676 dynamic_3(Bef, N-1, Data, Count+1). 677 678dynamic_big(Bef, N, Int, Lpad, Rpad) -> 679 NumBin = id(<<Int:N>>), 680 MaskedInt = Int band ((1 bsl N) - 1), 681 <<MaskedInt:N>> = NumBin, 682 683 %% Construct the binary in two different ways. 684 Bin = id(<<Lpad:Bef,NumBin/bitstring,Rpad:(64-Bef-N)>>), 685 Bin = <<Lpad:Bef,Int:N,Rpad:(64-Bef-N)>>, 686 687 %% Further verify the result by matching. 688 LpadMasked = Lpad band ((1 bsl Bef) - 1), 689 RpadMasked = Rpad band ((1 bsl (64-Bef-N)) - 1), 690 Rbits = (64-Bef-N), 691 <<LpadMasked:Bef,MaskedInt:N,RpadMasked:Rbits>> = id(Bin), 692 ok. 693 694dynamic_little(Bef, N, Int, Lpad, Rpad) -> 695 NumBin = id(<<Int:N/little>>), 696 MaskedInt = Int band ((1 bsl N) - 1), 697 <<MaskedInt:N/little>> = NumBin, 698 699 %% Construct the binary in two different ways. 700 Bin = id(<<Lpad:Bef/little,NumBin/bitstring,Rpad:(64-Bef-N)/little>>), 701 Bin = <<Lpad:Bef/little,Int:N/little,Rpad:(64-Bef-N)/little>>, 702 703 %% Further verify the result by matching. 704 LpadMasked = Lpad band ((1 bsl Bef) - 1), 705 RpadMasked = Rpad band ((1 bsl (64-Bef-N)) - 1), 706 Rbits = (64-Bef-N), 707 <<LpadMasked:Bef/little,MaskedInt:N/little,RpadMasked:Rbits/little>> = id(Bin), 708 ok. 709 710otp_7422(Config) when is_list(Config) -> 711 otp_7422_int(0), 712 otp_7422_bin(0). 713 714otp_7422_int(N) when N < 512 -> 715 T = erlang:make_tuple(N, []), 716 spawn_link(fun() -> 717 id(T), 718 %% A size of field 0 would write one byte beyond 719 %% the current position in the binary. It could 720 %% overwrite the continuation pointer stored on 721 %% the stack if HTOP was equal to E (the stack pointer). 722 id(<<0:(id(0))>>) 723 end), 724 otp_7422_int(N+1); 725otp_7422_int(_) -> ok. 726 727otp_7422_bin(N) when N < 512 -> 728 T = erlang:make_tuple(N, []), 729 Z = id(<<>>), 730 spawn_link(fun() -> 731 id(T), 732 id(<<Z:(id(0))/bits>>) 733 end), 734 otp_7422_bin(N+1); 735otp_7422_bin(_) -> ok. 736 737zero_width(Config) when is_list(Config) -> 738 Z = id(0), 739 Small = id(42), 740 Big = id(1 bsl 128), 741 <<>> = <<Small:Z>>, 742 <<>> = <<Small:0>>, 743 <<>> = <<Big:Z>>, 744 <<>> = <<Big:0>>, 745 746 {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>), 747 {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):Z>>), 748 {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>), 749 750 ok. 751 752id(I) -> I. 753