1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2000-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(bs_match_misc_SUITE). 21 22-export([all/0, suite/0, 23 bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1, 24 kenneth/1,encode_binary/1,native/1,happi/1, 25 size_var/1,wiger/1,x0_context/1,huge_float_field/1, 26 writable_binary_matched/1,otp_7198/1,unordered_bindings/1, 27 float_middle_endian/1,unsafe_get_binary_reuse/1]). 28 29-include_lib("common_test/include/ct.hrl"). 30 31suite() -> 32 [{ct_hooks,[ts_install_cth]}, 33 {timetrap, {seconds, 10}}]. 34 35all() -> 36 [bound_var, bound_tail, t_float, little_float, sean, 37 kenneth, encode_binary, native, happi, size_var, wiger, 38 x0_context, huge_float_field, writable_binary_matched, 39 otp_7198, unordered_bindings, float_middle_endian, 40 unsafe_get_binary_reuse]. 41 42 43%% Test matching of bound variables. 44bound_var(Config) when is_list(Config) -> 45 ok = bound_var(42, 13, <<42,13>>), 46 nope = bound_var(42, 13, <<42,255>>), 47 nope = bound_var(42, 13, <<154,255>>), 48 ok. 49 50bound_var(A, B, <<A:8,B:8>>) -> ok; 51bound_var(_, _, _) -> nope. 52 53%% Test matching of a bound tail. 54bound_tail(Config) when is_list(Config) -> 55 ok = bound_tail(<<>>, <<13,14>>), 56 ok = bound_tail(<<2,3>>, <<1,1,2,3>>), 57 nope = bound_tail(<<2,3>>, <<1,1,2,7>>), 58 nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>), 59 nope = bound_tail(<<2,3>>, <<>>), 60 ok. 61 62bound_tail(T, <<_:16,T/binary>>) -> ok; 63bound_tail(_, _) -> nope. 64 65t_float(Config) when is_list(Config) -> 66 F = f1(), 67 G = f_one(), 68 69 G = match_float(<<63,128,0,0>>, 32, 0), 70 G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0), 71 72 fcmp(F, match_float(<<F:32/float>>, 32, 0)), 73 fcmp(F, match_float(<<F:64/float>>, 64, 0)), 74 fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)), 75 fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 76 fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)), 77 fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 78 79 {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)), 80 {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)), 81 82 ok. 83 84float_middle_endian(Config) when is_list(Config) -> 85 F = 9007199254740990.0, % turns to -NaN when word-swapped 86 fcmp(F, match_float(<<F:64/float>>, 64, 0)), 87 fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 88 fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 89 ok. 90 91 92fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok. 93 94match_float(Bin0, Fsz, I) -> 95 Bin = make_sub_bin(Bin0), 96 Bsz = size(Bin) * 8, 97 Tsz = Bsz - Fsz - I, 98 <<_:I,F:Fsz/float,_:Tsz>> = Bin, 99 F. 100 101little_float(Config) when is_list(Config) -> 102 F = f2(), 103 G = f_one(), 104 105 G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0), 106 G = match_float_little(<<0,0,128,63>>, 32, 0), 107 108 fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)), 109 fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)), 110 fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)), 111 fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)), 112 fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)), 113 fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)), 114 115 ok. 116 117match_float_little(Bin0, Fsz, I) -> 118 Bin = make_sub_bin(Bin0), 119 Bsz = size(Bin) * 8, 120 Tsz = Bsz - Fsz - I, 121 <<_:I,F:Fsz/float-little,_:Tsz>> = Bin, 122 F. 123 124 125make_sub_bin(Bin0) -> 126 Sz = size(Bin0), 127 Bin1 = <<37,Bin0/binary,38,39>>, 128 <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1, 129 Bin. 130 131f1() -> 132 3.1415. 133 134f2() -> 135 2.7133. 136 137f_one() -> 138 1.0. 139 140sean(Config) when is_list(Config) -> 141 small = sean1(<<>>), 142 small = sean1(<<1>>), 143 small = sean1(<<1,2>>), 144 small = sean1(<<1,2,3>>), 145 large = sean1(<<1,2,3,4>>), 146 147 small = sean1(<<4>>), 148 small = sean1(<<4,5>>), 149 small = sean1(<<4,5,6>>), 150 {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)), 151 ok. 152 153sean1(<<B/binary>>) when byte_size(B) < 4 -> small; 154sean1(<<1, _B/binary>>) -> large. 155 156kenneth(Config) when is_list(Config) -> 157 {ok,[145,148,113,129,0,0,0,0]} = 158 msisdn_internal_storage(<<145,148,113,129,0,0,0,0>>, []). 159 160msisdn_internal_storage(<<>>,MSISDN) -> 161 {ok,lists:reverse(MSISDN)}; 162msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) -> 163 {ok,lists:reverse(MSISDN)}; 164msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when 165 DigitN < 10 -> 166 {ok,lists:reverse([(DigitN bor 2#11110000)|MSISDN])}; 167msisdn_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,MSISDN) when 168 DigitNplus1 < 10, 169 DigitN < 10 -> 170 NewMSISDN=[((DigitNplus1 bsl 4) bor DigitN)|MSISDN], 171 msisdn_internal_storage(Rest,NewMSISDN); 172msisdn_internal_storage(_Rest,_MSISDN) -> 173 {fault}. %% Mandatory IE incorrect 174 175encode_binary(Config) when is_list(Config) -> 176 "C2J2QiSc" = encodeBinary(<<11,98,118,66,36,156>>, []), 177 ok. 178 179encodeBinary(<<>>, Output) -> 180 lists:reverse(Output); 181encodeBinary(<<Data:1/binary>>, Output) -> 182 <<DChar1:6, DChar2:2>> = Data, 183 Char1 = getBase64Char(DChar1), 184 Char2 = getBase64Char(DChar2), 185 Char3 = "=", 186 Char4 = "=", 187 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 188 encodeBinary(<<>>, NewOutput); 189encodeBinary(<<Data:2/binary>>, Output) -> 190 <<DChar1:6, DChar2:6, DChar3:4>> = Data, 191 Char1 = getBase64Char(DChar1), 192 Char2 = getBase64Char(DChar2), 193 Char3 = getBase64Char(DChar3), 194 Char4 = "=", 195 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 196 encodeBinary(<<>>, NewOutput); 197encodeBinary(<<Data:3/binary, Rest/binary>>, Output) -> 198 <<DChar1:6, DChar2:6, DChar3:6, DChar4:6>> = Data, 199 Char1 = getBase64Char(DChar1), 200 Char2 = getBase64Char(DChar2), 201 Char3 = getBase64Char(DChar3), 202 Char4 = getBase64Char(DChar4), 203 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 204 encodeBinary(Rest, NewOutput); 205encodeBinary(_Data, _) -> 206 error. 207 208getBase64Char(0) -> "A"; 209getBase64Char(1) -> "B"; 210getBase64Char(2) -> "C"; 211getBase64Char(3) -> "D"; 212getBase64Char(4) -> "E"; 213getBase64Char(5) -> "F"; 214getBase64Char(6) -> "G"; 215getBase64Char(7) -> "H"; 216getBase64Char(8) -> "I"; 217getBase64Char(9) -> "J"; 218getBase64Char(10) -> "K"; 219getBase64Char(11) -> "L"; 220getBase64Char(12) -> "M"; 221getBase64Char(13) -> "N"; 222getBase64Char(14) -> "O"; 223getBase64Char(15) -> "P"; 224getBase64Char(16) -> "Q"; 225getBase64Char(17) -> "R"; 226getBase64Char(18) -> "S"; 227getBase64Char(19) -> "T"; 228getBase64Char(20) -> "U"; 229getBase64Char(21) -> "V"; 230getBase64Char(22) -> "W"; 231getBase64Char(23) -> "X"; 232getBase64Char(24) -> "Y"; 233getBase64Char(25) -> "Z"; 234getBase64Char(26) -> "a"; 235getBase64Char(27) -> "b"; 236getBase64Char(28) -> "c"; 237getBase64Char(29) -> "d"; 238getBase64Char(30) -> "e"; 239getBase64Char(31) -> "f"; 240getBase64Char(32) -> "g"; 241getBase64Char(33) -> "h"; 242getBase64Char(34) -> "i"; 243getBase64Char(35) -> "j"; 244getBase64Char(36) -> "k"; 245getBase64Char(37) -> "l"; 246getBase64Char(38) -> "m"; 247getBase64Char(39) -> "n"; 248getBase64Char(40) -> "o"; 249getBase64Char(41) -> "p"; 250getBase64Char(42) -> "q"; 251getBase64Char(43) -> "r"; 252getBase64Char(44) -> "s"; 253getBase64Char(45) -> "t"; 254getBase64Char(46) -> "u"; 255getBase64Char(47) -> "v"; 256getBase64Char(48) -> "w"; 257getBase64Char(49) -> "x"; 258getBase64Char(50) -> "y"; 259getBase64Char(51) -> "z"; 260getBase64Char(52) -> "0"; 261getBase64Char(53) -> "1"; 262getBase64Char(54) -> "2"; 263getBase64Char(55) -> "3"; 264getBase64Char(56) -> "4"; 265getBase64Char(57) -> "5"; 266getBase64Char(58) -> "6"; 267getBase64Char(59) -> "7"; 268getBase64Char(60) -> "8"; 269getBase64Char(61) -> "9"; 270getBase64Char(62) -> "+"; 271getBase64Char(63) -> "/"; 272getBase64Char(_Else) -> 273 %% This is an illegal input. 274% cgLogEM:log(error, ?MODULE, getBase64Char, [Else], 275% "illegal input", 276% ?LINE, version()), 277 "**". 278 279-define(M(F), <<F>> = <<F>>). 280 281native(Config) when is_list(Config) -> 282 ?M(3.14:64/native-float), 283 ?M(333:16/native), 284 ?M(38658345:32/native), 285 case <<1:16/native>> of 286 <<0,1>> -> native_big(); 287 <<1,0>> -> native_little() 288 end. 289 290native_big() -> 291 <<37.33:64/native-float>> = <<37.33:64/big-float>>, 292 <<3974:16/native-integer>> = <<3974:16/big-integer>>, 293 {comment,"Big endian"}. 294 295native_little() -> 296 <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>, 297 <<7974:16/native-integer>> = <<7974:16/little-integer>>, 298 {comment,"Little endian"}. 299 300happi(Config) when is_list(Config) -> 301 Bin = <<".123">>, 302 <<"123">> = lex_digits1(Bin, 1, []), 303 <<"123">> = lex_digits2(Bin, 1, []), 304 ok. 305 306lex_digits1(<<$., Rest/binary>>,_Val,_Acc) -> 307 Rest; 308lex_digits1(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 309 lex_digits1(Rest,Val*10+dec(N),Acc); 310lex_digits1(_Other,_Val,_Acc) -> 311 not_ok. 312 313lex_digits2(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 314 lex_digits2(Rest,Val*10+dec(N),Acc); 315lex_digits2(<<$., Rest/binary>>,_Val,_Acc) -> 316 Rest; 317lex_digits2(_Other,_Val,_Acc) -> 318 not_ok. 319 320dec(A) -> 321 A-$0. 322 323size_var(Config) when is_list(Config) -> 324 {<<45>>,<<>>} = split(<<1:16,45>>), 325 {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>), 326 {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>), 327 328 {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>), 329 330 {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>), 331 {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)), 332 333 <<"cdef">> = skip(<<2:8,"abcdef">>), 334 335 ok. 336 337split(<<N:16,B:N/binary,T/binary>>) -> 338 {B,T}. 339 340split(N, <<N:16,B:N/binary,T/binary>>) -> 341 {B,T}. 342 343split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) -> 344 {B,T}. 345 346skip(<<N:8,_:N/binary,T/binary>>) -> T. 347 348wiger(Config) when is_list(Config) -> 349 ok1 = wcheck(<<3>>), 350 ok2 = wcheck(<<1,2,3>>), 351 ok3 = wcheck(<<4>>), 352 {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), 353 {error,<<>>} = wcheck(<<>>), 354 ok. 355 356wcheck(<<A>>) when A==3-> 357 ok1; 358wcheck(<<_,_:2/binary>>) -> 359 ok2; 360wcheck(<<_>>) -> 361 ok3; 362wcheck(Other) -> 363 {error,Other}. 364 365%% Test that having the match context in x(0) works. 366 367x0_context(Config) when is_list(Config) -> 368 x0_0([], <<3.0:64/float,42:16,123456:32>>). 369 370x0_0(_, Bin) -> 371 <<3.0:64/float,42:16,_/binary>> = Bin, 372 x0_1([], Bin, 64, 16, 2). 373 374x0_1(_, Bin, FloatSz, IntSz, BinSz) -> 375 <<_:FloatSz/float,42:IntSz,B:BinSz/binary,C:1/binary,D/binary>> = Bin, 376 id({B,C,D}), 377 <<_:FloatSz/float,42:IntSz,B:BinSz/binary,_/binary>> = Bin, 378 x0_2([], Bin). 379 380x0_2(_, Bin) -> 381 <<_:64,0:7,42:9,_/binary>> = Bin, 382 x0_3([], Bin). 383 384x0_3(_, Bin) -> 385 case Bin of 386 <<_:72,7:8,_/binary>> -> 387 ct:fail(bs_matched_1); 388 <<_:64,0:16,_/binary>> -> 389 ct:fail(bs_matched_2); 390 <<_:64,42:16,123456:32,_/binary>> -> 391 ok 392 end. 393 394 395huge_float_field(Config) when is_list(Config) -> 396 Sz = 1 bsl 27, 397 Bin = <<0:Sz>>, 398 399 nomatch = overflow_huge_float_skip_32(Bin), 400 nomatch = overflow_huge_float_32(Bin), 401 402 ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 403 ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 404 ok. 405 406overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32 407overflow_huge_float_skip_32(<<_:33554432/float-unit:128,0,_/binary>>) -> 2; % 1 bsl 25 408overflow_huge_float_skip_32(<<_:67108864/float-unit:64,0,_/binary>>) -> 3; % 1 bsl 26 409overflow_huge_float_skip_32(<<_:134217728/float-unit:32,0,_/binary>>) -> 4; % 1 bsl 27 410overflow_huge_float_skip_32(<<_:268435456/float-unit:16,0,_/binary>>) -> 5; % 1 bsl 28 411overflow_huge_float_skip_32(<<_:536870912/float-unit:8,0,_/binary>>) -> 6; % 1 bsl 29 412overflow_huge_float_skip_32(<<_:1073741824/float-unit:8,0,_/binary>>) -> 7; % 1 bsl 30 413overflow_huge_float_skip_32(<<_:2147483648/float-unit:8,0,_/binary>>) -> 8; % 1 bsl 31 414overflow_huge_float_skip_32(_) -> nomatch. 415 416overflow_huge_float_32(<<F:4294967296/float,_/binary>>) -> {1,F}; % 1 bsl 32 417overflow_huge_float_32(<<F:33554432/float-unit:128,0,_/binary>>) -> {2,F}; % 1 bsl 25 418overflow_huge_float_32(<<F:67108864/float-unit:128,0,_/binary>>) -> {3,F}; % 1 bsl 26 419overflow_huge_float_32(<<F:134217728/float-unit:128,0,_/binary>>) -> {4,F}; % 1 bsl 27 420overflow_huge_float_32(<<F:268435456/float-unit:128,0,_/binary>>) -> {5,F}; % 1 bsl 28 421overflow_huge_float_32(<<F:536870912/float-unit:128,0,_/binary>>) -> {6,F}; % 1 bsl 29 422overflow_huge_float_32(<<F:1073741824/float-unit:128,0,_/binary>>) -> {7,F}; % 1 bsl 30 423overflow_huge_float_32(<<F:2147483648/float-unit:128,0,_/binary>>) -> {8,F}; % 1 bsl 31 424overflow_huge_float_32(_) -> nomatch. 425 426 427overflow_huge_float(Bin, [Sz0|Sizes]) -> 428 Sz = id(1 bsl Sz0), 429 case Bin of 430 <<_:Sz/float-unit:8,0,_/binary>> -> 431 {error,Sz}; 432 _ -> 433 case Bin of 434 <<Var:Sz/float-unit:8,0,_/binary>> -> 435 {error,Sz,Var}; 436 _ -> 437 overflow_huge_float(Bin, Sizes) 438 end 439 end; 440overflow_huge_float(_, []) -> ok. 441 442overflow_huge_float_unit128(Bin, [Sz0|Sizes]) -> 443 Sz = id(1 bsl Sz0), 444 case Bin of 445 <<_:Sz/float-unit:128,0,_/binary>> -> 446 {error,Sz}; 447 _ -> 448 case Bin of 449 <<Var:Sz/float-unit:128,0,_/binary>> -> 450 {error,Sz,Var}; 451 _ -> 452 overflow_huge_float_unit128(Bin, Sizes) 453 end 454 end; 455overflow_huge_float_unit128(_, []) -> ok. 456 457 458%% 459%% Test that a writable binary can be safely matched. 460%% 461 462writable_binary_matched(Config) when is_list(Config) -> 463 WritableBin = create_writeable_binary(), 464 writable_binary_matched(WritableBin, WritableBin, 500). 465 466writable_binary_matched(<<0>>, _, N) -> 467 if N =:= 0 -> ok; 468 true -> 469 put(grow_heap, [N|get(grow_heap)]), 470 WritableBin = create_writeable_binary(), 471 writable_binary_matched(WritableBin, WritableBin, N-1) 472 end; 473writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) -> 474 WritableBin = writable_binary(WritableBin0, B), 475 writable_binary_matched(T, WritableBin, N). 476 477writable_binary(WritableBin0, B) when is_binary(WritableBin0) -> 478 %% Heavy append to force the binary to move. 479 WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>, 480 id(<<(id(0)):128/unit:8>>), 481 WritableBin. 482 483create_writeable_binary() -> 484 <<(id(<<>>))/binary,1,2,3,4,5,6,0>>. 485 486otp_7198(Config) when is_list(Config) -> 487 %% When a match context was reused, and grown at the same time to 488 %% increase the number of saved positions, the thing word was not updated 489 %% to account for the new size. Therefore, if there was a garbage collection, 490 %% the new slots would be included in the garbage collection. 491 [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)], 492 ok. 493 494do_otp_7198(FillerSize) -> 495 Filler = erlang:make_tuple(FillerSize, 42), 496 {Pid,Ref} = spawn_monitor(fun() -> do_otp_7198_test(Filler) end), 497 receive 498 {'DOWN',Ref,process,Pid,normal} -> 499 ok; 500 {'DOWN',Ref,process,Pid,Reason} -> 501 ct:fail("unexpected: ~p", [Reason]) 502 end. 503 504do_otp_7198_test(_) -> 505 [{'KEYWORD',114}, 506 {'KEYWORD',101}, 507 {'KEYWORD',103}, 508 {'KEYWORD',105}, 509 {'KEYWORD',111}, 510 {'FIELD',110}, 511 {'KEYWORD',119}, 512 {'KEYWORD',104}, 513 {'KEYWORD',97}, 514 {'KEYWORD',116}, 515 {'KEYWORD',101}, 516 {'KEYWORD',118}, 517 {'KEYWORD',101}, 518 {'KEYWORD',114}, 519 '$thats_all_folks$'] = otp_7198_scan(<<"region:whatever">>, []). 520 521 522otp_7198_scan(<<>>, TokAcc) -> 523 lists:reverse(['$thats_all_folks$' | TokAcc]); 524 525otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when 526 (D =:= $D orelse D =:= $d) and 527 ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> 528 otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]); 529 530otp_7198_scan(<<D>>, TokAcc) when 531 (D =:= $D) or (D =:= $d) -> 532 otp_7198_scan(<<>>, ['AND' | TokAcc]); 533 534otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when 535 (N =:= $N orelse N =:= $n) and 536 ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> 537 otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]); 538 539otp_7198_scan(<<C, Rest/binary>>, TokAcc) when 540 (C >= $A) and (C =< $Z); 541 (C >= $a) and (C =< $z); 542 (C >= $0) and (C =< $9) -> 543 case Rest of 544 <<$:, R/binary>> -> 545 otp_7198_scan(R, [{'FIELD', C} | TokAcc]); 546 _ -> 547 otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc]) 548 end. 549 550unordered_bindings(Config) when is_list(Config) -> 551 {<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} = 552 unordered_bindings(4, 2, 3, <<1,2,3,4, 42,42, 3,3,3, 3>>), 553 ok. 554 555unordered_bindings(CompressedLength, HashSize, PadLength, T) -> 556 <<Content:CompressedLength/binary,Mac:HashSize/binary, 557 Padding:PadLength/binary,PadLength>> = T, 558 {Content,Mac,Padding}. 559 560%% ERL-901: A load-time optimization assumed that match contexts had no further 561%% uses when a bs_get_binary2 overwrote the match context's register, and 562%% figured it would be safe to reuse the match context's memory for the 563%% resulting binary. 564%% 565%% This is no longer safe as of OTP 22, as a match context may be reused after 566%% being passed to another function. 567unsafe_get_binary_reuse(Config) when is_list(Config) -> 568 <<_First, Rest/binary>> = <<"hello">>, 569 ubgr_1(Rest), 570 <<Second,_/bits>> = Rest, 571 $e = Second, 572 ok. 573 574ubgr_1(<<_CP/utf8, Rest/binary>>) -> id(Rest); 575ubgr_1(_) -> false. 576 577id(I) -> I. 578