diff options
author | Björn Gustavsson <[email protected]> | 2014-01-20 15:31:21 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2014-01-24 16:24:55 +0100 |
commit | 4bda9201055daf3abbdb5ef48bbdd0efacfd1fbc (patch) | |
tree | 1696fdc27de1f5d13ec15826919edaef372f3819 /lib/asn1 | |
parent | bd9e8cf011ee6c1391c134287f0fe877e51c54b8 (diff) | |
download | otp-4bda9201055daf3abbdb5ef48bbdd0efacfd1fbc.tar.gz otp-4bda9201055daf3abbdb5ef48bbdd0efacfd1fbc.tar.bz2 otp-4bda9201055daf3abbdb5ef48bbdd0efacfd1fbc.zip |
Fix BIT STRING
Diffstat (limited to 'lib/asn1')
-rw-r--r-- | lib/asn1/src/asn1ct_constructed_per.erl | 46 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_gen_ber_bin_v2.erl | 28 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_gen_per.erl | 9 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_imm.erl | 35 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_ber.erl | 51 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_per_common.erl | 24 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE.erl | 17 | ||||
-rw-r--r-- | lib/asn1/test/testPrimStrings.erl | 196 |
8 files changed, 303 insertions, 103 deletions
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index c224f4c9fa..f2509d1324 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -906,26 +906,36 @@ def_values(#type{def=#'Externaltypereference'{module=Mod,type=Type}}, Def) -> #typedef{typespec=T} = asn1_db:dbget(Mod, Type), def_values(T, Def); def_values(#type{def={'BIT STRING',[]}}, Bs) when is_bitstring(Bs) -> - ListBs = [B || <<B:1>> <= Bs], - IntBs = lists:foldl(fun(B, A) -> - (A bsl 1) bor B - end, 0, lists:reverse(ListBs)), - Sz = bit_size(Bs), - Compact = case 8 - Sz rem 8 of - 8 -> - {0,Bs}; - Unused -> - {Unused,<<Bs:Sz/bits,0:Unused>>} - end, - [asn1_DEFAULT,Bs,Compact,ListBs,IntBs]; + case asn1ct:use_legacy_types() of + false -> + [asn1_DEFAULT,Bs]; + true -> + ListBs = [B || <<B:1>> <= Bs], + IntBs = lists:foldl(fun(B, A) -> + (A bsl 1) bor B + end, 0, lists:reverse(ListBs)), + Sz = bit_size(Bs), + Compact = case 8 - Sz rem 8 of + 8 -> + {0,Bs}; + Unused -> + {Unused,<<Bs:Sz/bits,0:Unused>>} + end, + [asn1_DEFAULT,Bs,Compact,ListBs,IntBs] + end; def_values(#type{def={'BIT STRING',[_|_]=Ns}}, List) when is_list(List) -> Bs = asn1ct_gen:named_bitstring_value(List, Ns), - ListBs = [B || <<B:1>> <= Bs], - IntBs = lists:foldl(fun(B, A) -> - (A bsl 1) bor B - end, 0, lists:reverse(ListBs)), - Args = [List,Bs,ListBs,IntBs], - {call,per_common,is_default_bitstring,Args}; + As = case asn1ct:use_legacy_types() of + false -> + [List,Bs]; + true -> + ListBs = [B || <<B:1>> <= Bs], + IntBs = lists:foldl(fun(B, A) -> + (A bsl 1) bor B + end, 0, lists:reverse(ListBs)), + [List,Bs,ListBs,IntBs] + end, + {call,per_common,is_default_bitstring,As}; def_values(#type{def={'INTEGER',Ns}}, Def) -> [asn1_DEFAULT,Def|case lists:keyfind(Def, 2, Ns) of false -> []; diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index de81259fcb..84cda4491b 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -206,10 +206,32 @@ gen_encode_prim(_Erules, #type{}=D, DoTag, Value) -> {call,ber,encode_tags, [DoTag,{curr,realval},{curr,realsize}]},nl, "end"]); + {'BIT STRING',[]} -> + case asn1ct:use_legacy_types() of + false when BitStringConstraint =:= [] -> + call(encode_unnamed_bit_string, [Value,DoTag]); + false -> + call(encode_unnamed_bit_string, + [{asis,BitStringConstraint},Value,DoTag]); + true -> + call(encode_bit_string, + [{asis,BitStringConstraint},Value, + {asis,[]},DoTag]) + end; {'BIT STRING',NamedNumberList} -> - call(encode_bit_string, - [{asis,BitStringConstraint},Value, - {asis,NamedNumberList},DoTag]); + case asn1ct:use_legacy_types() of + false when BitStringConstraint =:= [] -> + call(encode_named_bit_string, + [Value,{asis,NamedNumberList},DoTag]); + false -> + call(encode_named_bit_string, + [{asis,BitStringConstraint},Value, + {asis,NamedNumberList},DoTag]); + true -> + call(encode_bit_string, + [{asis,BitStringConstraint},Value, + {asis,NamedNumberList},DoTag]) + end; 'NULL' -> call(encode_null, [Value,DoTag]); 'OBJECT IDENTIFIER' -> diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 7ba649c874..1885f782bd 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -132,7 +132,14 @@ gen_encode_prim_imm(Val, #type{def=Type0,constraint=Constraint}, Aligned) -> ToBinary = {real_common,encode_real}, asn1ct_imm:per_enc_restricted_string(Val, ToBinary, Aligned); {'BIT STRING',NNL} -> - asn1ct_imm:per_enc_bit_string(Val, NNL, Constraint, Aligned); + case asn1ct:use_legacy_types() of + false -> + asn1ct_imm:per_enc_bit_string(Val, NNL, + Constraint, Aligned); + true -> + asn1ct_imm:per_enc_legacy_bit_string(Val, NNL, + Constraint, Aligned) + end; 'NULL' -> asn1ct_imm:per_enc_null(Val, Aligned); 'OBJECT IDENTIFIER' -> diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl index c14f0b889f..9da8658f19 100644 --- a/lib/asn1/src/asn1ct_imm.erl +++ b/lib/asn1/src/asn1ct_imm.erl @@ -26,7 +26,8 @@ per_dec_octet_string/2,per_dec_open_type/1,per_dec_real/1, per_dec_restricted_string/1]). -export([per_dec_constrained/3,per_dec_normally_small_number/1]). --export([per_enc_bit_string/4,per_enc_boolean/2, +-export([per_enc_bit_string/4,per_enc_legacy_bit_string/4, + per_enc_boolean/2, per_enc_choice/3,per_enc_enumerated/3, per_enc_integer/3,per_enc_integer/4, per_enc_null/2, @@ -157,7 +158,35 @@ per_dec_restricted_string(Aligned) -> %%% Encoding. %%% -per_enc_bit_string(Val0, [], Constraint0, Aligned) -> +per_enc_bit_string(Val, [], Constraint0, Aligned) -> + {B,[[],Bits]} = mk_vars([], [bits]), + Constraint = effective_constraint(bitstring, Constraint0), + B ++ [{call,erlang,bit_size,[Val],Bits}| + per_enc_length(Val, 1, Bits, Constraint, Aligned, 'BIT STRING')]; +per_enc_bit_string(Val0, NNL0, Constraint0, Aligned) -> + {B,[Val,Bs,Bits,Positions]} = mk_vars(Val0, [bs,bits,positions]), + NNL = lists:keysort(2, NNL0), + Constraint = effective_constraint(bitstring, Constraint0), + ExtraArgs = case constr_min_size(Constraint) of + no -> []; + Lb -> [Lb] + end, + ToBs = case ExtraArgs of + [] -> + {call,per_common,bs_drop_trailing_zeroes,[Val]}; + [Lower] -> + {call,per_common,adjust_trailing_zeroes,[Val,Lower]} + end, + B ++ [{'try', + [bit_string_name2pos_fun(NNL, Val)], + {Positions, + [{call,per_common,bitstring_from_positions, + [Positions|ExtraArgs]}]}, + [ToBs],Bs}, + {call,erlang,bit_size,[Bs],Bits}| + per_enc_length(Bs, 1, Bits, Constraint, Aligned, 'BIT STRING')]. + +per_enc_legacy_bit_string(Val0, [], Constraint0, Aligned) -> {B,[Val,Bs,Bits]} = mk_vars(Val0, [bs,bits]), Constraint = effective_constraint(bitstring, Constraint0), ExtraArgs = case constr_min_size(Constraint) of @@ -167,7 +196,7 @@ per_enc_bit_string(Val0, [], Constraint0, Aligned) -> B ++ [{call,per_common,to_bitstring,[Val|ExtraArgs],Bs}, {call,erlang,bit_size,[Bs],Bits}| per_enc_length(Bs, 1, Bits, Constraint, Aligned, 'BIT STRING')]; -per_enc_bit_string(Val0, NNL0, Constraint0, Aligned) -> +per_enc_legacy_bit_string(Val0, NNL0, Constraint0, Aligned) -> {B,[Val,Bs,Bits,Positions]} = mk_vars(Val0, [bs,bits,positions]), NNL = lists:keysort(2, NNL0), Constraint = effective_constraint(bitstring, Constraint0), diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl index 583ff790b7..a4aa347aea 100644 --- a/lib/asn1/src/asn1rtt_ber.erl +++ b/lib/asn1/src/asn1rtt_ber.erl @@ -29,6 +29,8 @@ decode_integer/2,decode_integer/3, decode_named_integer/3,decode_named_integer/4, encode_enumerated/2,decode_enumerated/3, + encode_unnamed_bit_string/2,encode_unnamed_bit_string/3, + encode_named_bit_string/3,encode_named_bit_string/4, encode_bit_string/4, decode_named_bit_string/3, decode_compact_bit_string/3, @@ -780,6 +782,55 @@ decode_enumerated1(Val, NamedNumberList) -> {asn1_enum,Val} end. +%%============================================================================ +%% Bitstring value, ITU_T X.690 Chapter 8.6 +%% +%% encode bitstring value +%%============================================================================ + +encode_unnamed_bit_string(Bits, TagIn) -> + Unused = (8 - (bit_size(Bits) band 7)) band 7, + Bin = <<Unused,Bits/bitstring,0:Unused>>, + encode_tags(TagIn, Bin, byte_size(Bin)). + +encode_unnamed_bit_string(C, Bits, TagIn) -> + NumBits = bit_size(Bits), + Unused = (8 - (NumBits band 7)) band 7, + Bin = <<Unused,Bits/bitstring,0:Unused>>, + case C of + {_Min,Max} -> + if + NumBits > Max -> + exit({error,{asn1, + {bitstring_length, + {{was,NumBits},{maximum,Max}}}}}); + true -> + ok + end; + Size -> + if NumBits =< Size -> + ok; + true -> + exit({error,{asn1, + {bitstring_length, + {{was,NumBits},{should_be,Size}}}}}) + end + end, + encode_tags(TagIn, Bin, byte_size(Bin)). + +encode_named_bit_string([H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> + encode_bit_string_named([], Bits, NamedBitList, TagIn); +encode_named_bit_string([{bit,_}|_]=Bits, NamedBitList, TagIn) -> + encode_bit_string_named([], Bits, NamedBitList, TagIn); +encode_named_bit_string(Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> + encode_unnamed_bit_string(Bits, TagIn). + +encode_named_bit_string(C, [H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> + encode_bit_string_named(C, Bits, NamedBitList, TagIn); +encode_named_bit_string(C, [{bit,_}|_]=Bits, NamedBitList, TagIn) -> + encode_bit_string_named(C, Bits, NamedBitList, TagIn); +encode_named_bit_string(C, Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> + encode_unnamed_bit_string(C, Bits, TagIn). %%============================================================================ %% Bitstring value, ITU_T X.690 Chapter 8.6 diff --git a/lib/asn1/src/asn1rtt_per_common.erl b/lib/asn1/src/asn1rtt_per_common.erl index 3309e6a4ca..e84fa581df 100644 --- a/lib/asn1/src/asn1rtt_per_common.erl +++ b/lib/asn1/src/asn1rtt_per_common.erl @@ -37,7 +37,8 @@ bitstring_from_positions/1,bitstring_from_positions/2, to_bitstring/1,to_bitstring/2, to_named_bitstring/1,to_named_bitstring/2, - is_default_bitstring/5, + bs_drop_trailing_zeroes/1,adjust_trailing_zeroes/2, + is_default_bitstring/3,is_default_bitstring/5, extension_bitmap/3]). -define('16K',16384). @@ -272,6 +273,25 @@ to_named_bitstring(Val, Lb) -> %% for correctness, not speed. adjust_trailing_zeroes(to_bitstring(Val), Lb). +is_default_bitstring(asn1_DEFAULT, _, _) -> + true; +is_default_bitstring(Named, Named, _) -> + true; +is_default_bitstring(Bs, _, Bs) -> + true; +is_default_bitstring(Val, _, Def) when is_bitstring(Val) -> + Sz = bit_size(Def), + case Val of + <<Def:Sz/bitstring,T/bitstring>> -> + NumZeroes = bit_size(T), + case T of + <<0:NumZeroes>> -> true; + _ -> false + end; + _ -> + false + end. + is_default_bitstring(asn1_DEFAULT, _, _, _, _) -> true; is_default_bitstring({Unused,Bin}, V0, V1, V2, V3) when is_integer(Unused) -> @@ -438,6 +458,8 @@ adjust_trailing_zeroes(Bs0, Lb) -> bs_drop_trailing_zeroes(Bs) -> bs_drop_trailing_zeroes(Bs, bit_size(Bs)). +bs_drop_trailing_zeroes(Bs, 0) -> + Bs; bs_drop_trailing_zeroes(Bs0, Sz0) when Sz0 < 8 -> <<Byte:Sz0>> = Bs0, Sz = Sz0 - ntz(Byte), diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index 2809c8020b..ac61187ed4 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -328,6 +328,10 @@ testCompactBitString(Config, Rule, Opts) -> testPrimStrings(Config) -> test(Config, fun testPrimStrings/3, [ber,{ber,[der]},per,uper]). testPrimStrings(Config, Rule, Opts) -> + LegacyOpts = [legacy_erlang_types|Opts], + asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, + [Rule|LegacyOpts]), + testPrimStrings_cases(Rule, LegacyOpts), asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, [Rule|Opts]), testPrimStrings_cases(Rule, Opts), asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, @@ -432,7 +436,8 @@ testDef(Config, Rule, Opts) -> testDEFAULT(Config) -> test(Config, fun testDEFAULT/3, [ber,{ber,[der]},per,uper]). testDEFAULT(Config, Rule, Opts) -> - asn1_test_lib:compile_all(["Def","Default"], Config, [Rule|Opts]), + asn1_test_lib:compile_all(["Def","Default"], Config, + [legacy_erlang_types,Rule|Opts]), testDef:main(Rule), testSeqSetDefaultVal:main(Rule, Opts). @@ -784,7 +789,8 @@ testMergeCompile(Config, Rule, Opts) -> testobj(Config) -> test(Config, fun testobj/3). testobj(Config, Rule, Opts) -> - asn1_test_lib:compile("RANAP", Config, [Rule|Opts]), + asn1_test_lib:compile("RANAP", Config, [legacy_erlang_types, + Rule|Opts]), asn1_test_lib:compile_erlang("testobj", Config, []), ok = testobj:run(), ok = testParameterizedInfObj:ranap(Rule). @@ -1022,7 +1028,8 @@ test_x691(Config, Rule, Opts) -> test_x691:cases(Rule), %% OTP-7708. - asn1_test_lib:compile("EUTRA-extract-55", Config, [Rule|Opts]), + asn1_test_lib:compile("EUTRA-extract-55", Config, + [legacy_erlang_types,Rule|Opts]), %% OTP-7763. Val = {'Seq',15,lists:duplicate(8, 0),[0],lists:duplicate(28, 0),15,true}, @@ -1200,8 +1207,8 @@ ticket_7407_code(FinalPadding) -> eutra1(msg) -> {'BCCH-BCH-Message', - {'MasterInformationBlock',[0,1,0,1],[1,0,1,0], - {'PHICH-Configuration',short,ffs},[1,0,1,0,0,0,0,0]}}. + {'MasterInformationBlock',<<2#0101:4>>,<<2#1010:4>>, + {'PHICH-Configuration',short,ffs},<<2#10100000>>}}. eutra1(result, true) -> <<90,80,0>>; diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index f8e48be4ae..2e133e184a 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -68,33 +68,37 @@ bit_string(Rules, Opts) -> %% Bs1 ::= BIT STRING %%========================================================== - bs_roundtrip('Bs1', 0, <<>>), - bs_roundtrip('Bs1', 4, <<1:3>>), - bs_roundtrip('Bs1', 15, <<15:4>>), - bs_roundtrip('Bs1', 255, <<255:8>>), - - bs_roundtrip('Bs1', 256, [0,0,0,0,0,0,0,0,1]), - bs_roundtrip('Bs1', 257, [1,0,0,0,0,0,0,0,1]), - bs_roundtrip('Bs1', 444, [0,0,1,1,1,1,0,1,1]), - - {ok,Enc1} = 'PrimStrings':encode('Bs1', 12345678901234567890), - {ok,_} = 'PrimStrings':decode('Bs1', Enc1), - - bs_roundtrip('Bs1', [1,1,1,1,1,1,1,1]), - bs_roundtrip('Bs1', [0,1,0,0,1,0]), - bs_roundtrip('Bs1', [1,0,0,0,0,0,0,0,0]), - bs_roundtrip('Bs1', [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]), + bs_roundtrip('Bs1', <<>>), + bs_roundtrip('Bs1', <<1:3>>), + bs_roundtrip('Bs1', <<15:4>>), + bs_roundtrip('Bs1', <<2#010010:6>>), + bs_roundtrip('Bs1', <<2#11111111:8>>), + bs_roundtrip('Bs1', <<2#100000000:9>>), + bs_roundtrip('Bs1', <<2#100000001:9>>), + bs_roundtrip('Bs1', <<2#001111011:9>>), + bs_roundtrip('Bs1', <<2#0100101111100010011:19>>), + + case 'PrimStrings':legacy_erlang_types() of + false -> + ok; + true -> + {ok,Enc1} = 'PrimStrings':encode('Bs1', 12345678901234567890), + {ok,_} = 'PrimStrings':decode('Bs1', Enc1) + end, case {Rules,Opts} of - {ber,[]} -> + {ber,[legacy_erlang_types]} -> bs_decode('Bs1', <<35,8,3,2,0,73,3,2,4,32>>, [0,1,0,0,1,0,0,1,0,0,1,0]), bs_decode('Bs1', <<35,9,3,2,0,234,3,3,7,156,0>>, [1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]), bs_decode('Bs1', <<35,128,3,2,0,234,3,3,7,156,0,0,0>>, [1,1,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0]); - _ -> + {ber,[]} -> + %% XXX + ok; + {_,_} -> %% DER, PER, UPER consistent_def_enc('BsDef1', [2#111101, @@ -114,30 +118,39 @@ bit_string(Rules, Opts) -> %%========================================================== roundtrip('Bs2', [mo,tu,fr]), - roundtrip('Bs2', [0,1,1,0,0,1,0], [mo,tu,fr]), + bs_roundtrip('Bs2', <<2#0110010:7>>, [mo,tu,fr]), + bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]), %%========================================================== %% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7)) %%========================================================== roundtrip('Bs3', [mo,tu,fr]), - bs_roundtrip('Bs3', [0,1,1,0,0,1,0], [mo,tu,fr]), + bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), + bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), + bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]), + bs_roundtrip('Bs3', <<2#011001:6>>, [mo,tu,fr]), + bs_roundtrip('Bs3', <<2#11:2>>, [su,mo]), %%========================================================== %% Bs7 ::= BIT STRING (SIZE (24)) %%========================================================== - bs_roundtrip('Bs7', 53245, - [1,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0]), - bs_roundtrip('Bs7', [1,0,1,0], - [1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + bs_roundtrip('Bs7', <<23563:24>>), + case 'PrimStrings':legacy_erlang_types() of + false -> +%% {error,_} = 'PrimStrings':encode('Bs7', <<2#1010:4>>); + ok; + true -> + ok + end, %%========================================================== %% BsPri ::= [PRIVATE 61] BIT STRING %%========================================================== - bs_roundtrip('BsPri', 45, [1,0,1,1,0,1]), - bs_roundtrip('BsPri', 211, [1,1,0,0,1,0,1,1]), + bs_roundtrip('BsPri', <<2#101101:6>>), + bs_roundtrip('BsPri', <<2#11001011:8>>), case Rules of ber -> @@ -158,8 +171,8 @@ bit_string(Rules, Opts) -> %% BsExpPri ::= [PRIVATE 61] EXPLICIT BIT STRING %%========================================================== - bs_roundtrip('BsExpPri', 45, [1,0,1,1,0,1]), - bs_roundtrip('BsExpPri', 211, [1,1,0,0,1,0,1,1]), + bs_roundtrip('BsExpPri', <<2#101101:6>>), + bs_roundtrip('BsExpPri', <<2#11001011:8>>), case Rules of ber -> @@ -180,14 +193,14 @@ bit_string(Rules, Opts) -> %% veteran(2), collegeGraduate(3)}, test case for OTP-5710 %%========================================================== - {ok,Bytes54} = 'BitStr':encode('PersonalStatus', []), + {ok,Bytes54} = 'BitStr':encode('PersonalStatus', <<>>), {ok,[]} = 'BitStr':decode('PersonalStatus', Bytes54), %%========================================================== %% BS5932 ::= BIT STRING (SIZE (5..MAX)) %% test case for OTP-5932 %%========================================================== - bs_roundtrip('BSMAX', [1,0,1,0,1]), + bs_roundtrip('BSMAX', <<2#10101:5>>), case Rules of ber -> {error,_} = 'PrimStrings':encode('BSMAX', [1,0,1]); @@ -201,28 +214,35 @@ bit_string(Rules, Opts) -> %% BS1024 ::= BIT STRING (SIZE (1024)) %% test case for OTP-7602 %%========================================================== - BSmaker = - fun(_F,S,S,_,Acc) -> - Acc; - (F,Ix,S,{A,B},Acc) -> - F(F,Ix+1,S,{B,A},[A|Acc]) - end, - - BSList255 = BSmaker(BSmaker,0,255,{1,0},[]), - bs_roundtrip('BS255', BSList255), - BSList256 = BSmaker(BSmaker,0,256,{1,0},[]), - bs_roundtrip('BS256', BSList256), - BSList1024 = BSmaker(BSmaker,0,1024,{1,0},[]), - bs_roundtrip('BS1024', BSList1024), - bs_roundtrip('TransportLayerAddress', [0,1,1,0]), + bs_roundtrip('BS255', random_bits(255)), + bs_roundtrip('BS256', random_bits(256)), + bs_roundtrip('BS1024', random_bits(1024)), + + bs_roundtrip('TransportLayerAddress', <<2#0110:4>>), case Rules of ber -> ok; _ -> per_bs_strings() end. -consistent_def_enc(Type, Vs) -> +random_bits(N) -> + Seed = integer_to_list(erlang:phash2(erlang:now())), + random_bits(<<>>, N, Seed). + +random_bits(Bin, N, Seed) -> + RandomBits = erlang:md5(Seed), + Bits = bit_size(RandomBits), + if + Bits < N -> + random_bits(<<Bin/bitstring,RandomBits/bitstring>>, + N-Bits, RandomBits); + true -> + <<LastBits:N/bitstring,_/bitstring>> = RandomBits, + <<Bin/bitstring,LastBits/bitstring>> + end. + +consistent_def_enc(Type, Vs0) -> M = 'PrimStrings', {ok,Enc} = M:encode(Type, {Type,asn1_DEFAULT}), {ok,Val} = M:decode(Type, Enc), @@ -235,6 +255,13 @@ consistent_def_enc(Type, Vs) -> {legacy,{_,Bs}} when is_list(Bs) -> ok end, + %% If this is not the legacy format, only bitstrings are + %% allowed. + Vs = case M:legacy_erlang_types() of + false -> [V || V <- Vs0, is_bitstring(V)]; + true -> Vs0 + end, + %% All values should be recognized and encoded as the %% the default value (i.e. not encoded at all). _ = [{ok,Enc} = M:encode(Type, {Type,V}) || V <- Vs], @@ -246,18 +273,9 @@ consistent_def_enc(Type, Vs) -> %% a SIZE constraint). per_bs_strings() -> - bs_roundtrip('Bs3', [0,0,1,0,0,0,0], [tu]), bs_roundtrip('Bs3', <<2#0010000:7>>, [tu]), - bs_roundtrip('Bs3', {1,<<2#00100000:8>>}, [tu]), - - bs_roundtrip('Bs4', [0,1,1,0,0,1,0], [mo,tu,fr]), bs_roundtrip('Bs4', <<2#0110010:7>>, [mo,tu,fr]), - bs_roundtrip('Bs4', {1,<<2#01100100:8>>}, [mo,tu,fr]), - - bs_roundtrip('Bs4', [0,1,1,0,0,0,0], [mo,tu]), bs_roundtrip('Bs4', <<2#011:3,0:32>>, [mo,tu]), - bs_roundtrip('Bs4', {5,<<2#011:3,0:32,0:5>>}, [mo,tu]), - [per_trailing_zeroes(B) || B <- lists:seq(0, 255)], ok. @@ -273,10 +291,6 @@ per_trailing_zeroes(Byte) -> {bit,LastBitPos} -> LastBitPos+1 end, - %% List of zeroes and ones. - named_roundtrip(L, Pos, ExpectedSz), - named_roundtrip(L++[0,0,0,0,0], Pos, ExpectedSz), - %% Bitstrings. Bs = << <<B:1>> || B <- L >>, Sz = bit_size(Bs), @@ -284,14 +298,22 @@ per_trailing_zeroes(Byte) -> Bin = <<Bs:Sz/bits,0:16,0:7>>, named_roundtrip(Bin, Pos, ExpectedSz), - %% Compact bitstring. - named_roundtrip({7,Bin}, Pos, ExpectedSz), + case 'PrimStrings':legacy_erlang_types() of + false -> + ok; + true -> + %% List of zeroes and ones. + named_roundtrip(L, Pos, ExpectedSz), + named_roundtrip(L++[0,0,0,0,0], Pos, ExpectedSz), - %% Integer bitstring (obsolete). - IntBs = intlist_to_integer(L, 0, 0), - named_roundtrip(IntBs, Pos, ExpectedSz), + %% Compact bitstring. + named_roundtrip({7,Bin}, Pos, ExpectedSz), - ok. + %% Integer bitstring (obsolete). + IntBs = intlist_to_integer(L, 0, 0), + named_roundtrip(IntBs, Pos, ExpectedSz), + ok + end. make_bit_list(0) -> []; make_bit_list(B) -> [B band 1|make_bit_list(B bsr 1)]. @@ -753,15 +775,45 @@ roundtrip(Type, Value, Expected) -> bs_roundtrip(Type, Value) -> bs_roundtrip(Type, Value, Value). -bs_roundtrip(Type, Value, Expected) -> +bs_roundtrip(Type, Value, Expected) when is_bitstring(Value) -> M = 'PrimStrings', - {ok,Encoded} = M:encode(Type, Value), - {ok,Encoded} = M:encode(Type, Expected), - case M:decode(Type, Encoded) of - {ok,Expected} -> - ok; - {ok,Other} -> - Expected = convert(Other, Expected) + case M:legacy_erlang_types() of + false -> + asn1_test_lib:roundtrip(M, Type, Value, Expected); + true -> + {ok,Encoded} = M:encode(Type, Value), + BitList = [B || <<B:1>> <= Value], + {ok,Encoded} = M:encode(Type, BitList), + case BitList of + [] -> + {ok,Encoded} = M:encode(Type, 0); + [_|_] -> + case lists:last(BitList) of + 1 -> + Int = lists:foldr(fun(B, A) -> + (A bsl 1) bor B + end, 0, BitList), + {ok,Encoded} = M:encode(Type, Int); + 0 -> + %% This BIT STRING cannot be represented + %% as an integer. + ok + end + end, + Compact = case bit_size(Value) of + Bits when Bits rem 8 =:= 0 -> + {0,Value}; + Bits -> + Unused = 8 - Bits rem 8, + {Unused,<<Value:Bits/bitstring,0:Unused>>} + end, + {ok,Encoded} = M:encode(Type, Compact), + case M:decode(Type, Encoded) of + {ok,Expected} -> + ok; + {ok,Other} -> + Expected = convert(Other, Expected) + end end. bs_decode(Type, Encoded, Expected) -> |