diff options
-rw-r--r-- | lib/asn1/src/asn1ct_imm.erl | 43 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_per.erl | 31 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 | 72 | ||||
-rw-r--r-- | lib/asn1/test/testPrimStrings.erl | 33 |
4 files changed, 156 insertions, 23 deletions
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl index 2c5620d5c8..e0e4a5a451 100644 --- a/lib/asn1/src/asn1ct_imm.erl +++ b/lib/asn1/src/asn1ct_imm.erl @@ -117,15 +117,25 @@ per_dec_named_integer(Constraint, NamedList0, Aligned) -> per_dec_k_m_string(StringType, Constraint, Aligned) -> SzConstr = get_constraint(Constraint, 'SizeConstraint'), N = string_num_bits(StringType, Constraint, Aligned), - Imm = dec_string(SzConstr, N, Aligned), + %% X.691 (07/2002) 27.5.7 says if the upper bound times the number + %% of bits is greater than or equal to 16, then the bit field should + %% be aligned. + Imm = dec_string(SzConstr, N, Aligned, fun(_, Ub) -> Ub >= 16 end), Chars = char_tab(Constraint, StringType, N), convert_string(N, Chars, Imm). per_dec_octet_string(Constraint, Aligned) -> - dec_string(Constraint, 8, Aligned). + dec_string(Constraint, 8, Aligned, + %% Aligned unless the size is fixed and =< 16. + fun(Sv, Sv) -> Sv > 16; + (_, _) -> true + end). per_dec_raw_bitstring(Constraint, Aligned) -> - dec_string(Constraint, 1, Aligned). + dec_string(Constraint, 1, Aligned, + fun(Sv, Sv) -> Sv > 16; + (_, _) -> true + end). per_dec_open_type(Aligned) -> {get_bits,decode_unconstrained_length(true, Aligned), @@ -149,21 +159,22 @@ per_dec_restricted_string(Aligned) -> %%% Local functions. %%% -dec_string(Sv, U, _Aligned) when is_integer(Sv), U*Sv =< 16 -> - {get_bits,Sv,[U,binary]}; -dec_string(Sv, U, Aligned) when is_integer(Sv), Sv < 16#10000 -> +dec_string(Sv, U, Aligned0, AF) when is_integer(Sv), Sv < 16#10000 -> + Bits = U*Sv, + Aligned = Aligned0 andalso AF(Bits, Bits), {get_bits,Sv,[U,binary,{align,Aligned}]}; -dec_string([_|_]=C, U, Aligned) when is_list(C) -> - dec_string({hd(C),lists:max(C)}, U, Aligned); -dec_string({Sv,Sv}, U, Aligned) -> - dec_string(Sv, U, Aligned); -dec_string({{_,_}=C,_}, U, Aligned) -> - bit_case(dec_string(C, U, Aligned), - dec_string(no, U, Aligned)); -dec_string({Lb,Ub}, U, Aligned) when Ub < 16#10000 -> - Len = per_dec_constrained(Lb, Ub, Aligned), +dec_string([_|_]=C, U, Aligned, AF) when is_list(C) -> + dec_string({hd(C),lists:max(C)}, U, Aligned, AF); +dec_string({Sv,Sv}, U, Aligned, AF) -> + dec_string(Sv, U, Aligned, AF); +dec_string({{_,_}=C,_}, U, Aligned, AF) -> + bit_case(dec_string(C, U, Aligned, AF), + dec_string(no, U, Aligned, AF)); +dec_string({Lb,Ub}, U, Aligned0, AF) when Ub < 16#10000 -> + Len = per_dec_constrained(Lb, Ub, Aligned0), + Aligned = Aligned0 andalso AF(Lb*U, Ub*U), {get_bits,Len,[U,binary,{align,Aligned}]}; -dec_string(_, U, Aligned) -> +dec_string(_, U, Aligned, _AF) -> Al = [{align,Aligned}], DecRest = fun(V, Buf) -> asn1ct_func:call(per_common, diff --git a/lib/asn1/src/asn1rtt_per.erl b/lib/asn1/src/asn1rtt_per.erl index d5952755f8..8d2025d603 100644 --- a/lib/asn1/src/asn1rtt_per.erl +++ b/lib/asn1/src/asn1rtt_per.erl @@ -663,6 +663,19 @@ make_and_set_list([], _) -> %% encode_octet_string(Constraint, Val) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +encode_octet_string({{Sv,Sv},Ext}=SZ, Val) when is_list(Ext), Sv =< 2 -> + Len = length(Val), + try + case encode_length(SZ, Len) of + [0|_]=EncLen -> + [EncLen,45,Sv*8,Sv,Val]; + [_|_]=EncLen -> + [EncLen|octets_to_complete(Len, Val)] + end + catch + exit:{error,{asn1,{encode_length,_}}} -> + encode_fragmented_octet_string(Val) + end; encode_octet_string({_,_}=SZ, Val) -> Len = length(Val), try @@ -725,12 +738,24 @@ encode_restricted_string(Val) when is_list(Val)-> encode_known_multiplier_string(SizeC, NumBits, CharOutTab, Val) -> Result = chars_encode2(Val, NumBits, CharOutTab), case SizeC of - Ub when is_integer(Ub), Ub*NumBits =< 16 -> + Ub when is_integer(Ub), Ub*NumBits < 16 -> Result; Ub when is_integer(Ub), Ub =<65535 -> % fixed length [2,Result]; - {Ub,Lb} -> - [encode_length({Ub,Lb},length(Val)),2,Result]; + {{_,Ub},Ext}=SZ when is_list(Ext) -> + Len = length(Val), + case encode_length(SZ, Len) of + [0|_]=EncLen when Ub*NumBits < 16 -> + [EncLen,45,Len*NumBits,Len,Val]; + [_|_]=EncLen -> + [EncLen,2|Result] + end; + {_,Ub}=Range -> + [encode_length(Range, length(Val))| + if + Ub*NumBits < 16 -> Result; + true -> [2|Result] + end]; no -> [encode_length(length(Val)),2,Result] end. diff --git a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 index cfaf4cf034..99fe38c07c 100644 --- a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 @@ -72,6 +72,32 @@ BS1024 ::= BIT STRING (SIZE (1024)) i INTEGER (0..1024) } + OsFixedStringsExt ::= SEQUENCE { + b1 BOOLEAN, -- Unalign + s0 OCTET STRING (SIZE (0, ...)), + s1 OCTET STRING (SIZE (1, ...)), + s2 OCTET STRING (SIZE (2, ...)), + s3 OCTET STRING (SIZE (3, ...)), + b2 BOOLEAN, -- Unalign + s255 OCTET STRING (SIZE (255, ...)), + s256 OCTET STRING (SIZE (256, ...)), + s257 OCTET STRING (SIZE (257, ...)), + i INTEGER (0..1024) + } + + OsVarStringsExt ::= SEQUENCE { + b1 BOOLEAN, -- Unalign + s0 OCTET STRING (SIZE (0, ...)), + s1 OCTET STRING (SIZE (0..1, ...)), + s2 OCTET STRING (SIZE (1..2, ...)), + s3 OCTET STRING (SIZE (2..3, ...)), + b2 BOOLEAN, -- Unalign + s255 OCTET STRING (SIZE (254..255, ...)), + s256 OCTET STRING (SIZE (255..256, ...)), + s257 OCTET STRING (SIZE (256..257, ...)), + i INTEGER (0..1024) + } + OsAlignment ::= SEQUENCE { b1 BOOLEAN, s1 Os, @@ -82,6 +108,52 @@ BS1024 ::= BIT STRING (SIZE (1024)) i INTEGER (0..63) } + IA5FixedStrings ::= SEQUENCE { + b1 BOOLEAN, -- Unalign + s0 IA5String (SIZE (0)), + s1 IA5String (SIZE (1)), + s2 IA5String (SIZE (2)), + s3 IA5String (SIZE (3)), + b2 BOOLEAN, -- Unalign + s4 IA5String (SIZE (4)), + b3 BOOLEAN, -- Unalign + s255 IA5String (SIZE (255)), + s256 IA5String (SIZE (256)), + s257 IA5String (SIZE (257)), + i INTEGER (0..1024) + } + + IA5FixedStringsExt ::= SEQUENCE { + b1 BOOLEAN, -- Unalign + s0 IA5String (SIZE (0, ...)), + s1 IA5String (SIZE (1, ...)), + s2 IA5String (SIZE (2, ...)), + s3 IA5String (SIZE (3, ...)), + b2 BOOLEAN, -- Unalign + s4 IA5String (SIZE (4, ...)), + b3 BOOLEAN, -- Unalign + s255 IA5String (SIZE (255, ...)), + s256 IA5String (SIZE (256, ...)), + s257 IA5String (SIZE (257, ...)), + i INTEGER (0..1024) + } + + IA5VarStringsExt ::= SEQUENCE { + b1 BOOLEAN, -- Unalign + s0 IA5String (SIZE (0, ...)), + s1 IA5String (SIZE (0..1, ...)), + s2 IA5String (SIZE (1..2, ...)), + s3 IA5String (SIZE (2..3, ...)), + b2 BOOLEAN, -- Unalign + s4 IA5String (SIZE (3..4, ...)), + b3 BOOLEAN, -- Unalign + s255 IA5String (SIZE (254..255, ...)), + s256 IA5String (SIZE (255..256, ...)), + s257 IA5String (SIZE (256..257, ...)), + i INTEGER (0..1024) + } + + Ns ::= NumericString NsCon ::= [70] NumericString NsExpCon ::= [71] EXPLICIT NumericString diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index f8b0c5b05a..66415afe87 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -255,11 +255,16 @@ octet_string(Rules) -> fragmented_octet_string(Rules), S255 = lists:seq(1, 255), - FixedStrings = {'OsFixedStrings',true,"","1","12","345",true, - S255,[$a|S255],[$a,$b|S255],397}, - roundtrip('OsFixedStrings', FixedStrings), + Strings = {type,true,"","1","12","345",true, + S255,[$a|S255],[$a,$b|S255],397}, + p_roundtrip('OsFixedStrings', Strings), + p_roundtrip('OsFixedStringsExt', Strings), + p_roundtrip('OsVarStringsExt', Strings), + ShortenedStrings = shorten_by_two(Strings), + p_roundtrip('OsFixedStringsExt', ShortenedStrings), + p_roundtrip('OsVarStringsExt', ShortenedStrings), ok. - + fragmented_octet_string(Erules) -> K16 = 1 bsl 14, K32 = K16 + K16, @@ -438,6 +443,15 @@ other_strings(_Rules) -> roundtrip('IA5Visible', lists:seq($\s, $~)), + S255 = lists:seq(0, 127) ++ lists:seq(1, 127), + Strings = {type,true,"","1","12","345",true,"6789",true, + S255,[$a|S255],[$a,$b|S255],397}, + p_roundtrip('IA5FixedStrings', Strings), + p_roundtrip('IA5FixedStringsExt', Strings), + p_roundtrip('IA5VarStringsExt', Strings), + ShortenedStrings = shorten_by_two(Strings), + p_roundtrip('IA5VarStringsExt', ShortenedStrings), + ok. @@ -709,6 +723,17 @@ wrapper_utf8_binary_to_list(L) when is_list(L) -> wrapper_utf8_binary_to_list(B) -> asn1rt:utf8_binary_to_list(B). +shorten_by_two(Tuple) -> + L = [case E of + [_,_|T] -> T; + _ -> E + end || E <- tuple_to_list(Tuple)], + list_to_tuple(L). + +p_roundtrip(Type, Value0) -> + Value = setelement(1, Value0, Type), + roundtrip(Type, Value). + roundtrip(Type, Value) -> {ok,Encoded} = 'PrimStrings':encode(Type, Value), {ok,Value} = 'PrimStrings':decode(Type, Encoded), |