diff options
author | Björn Gustavsson <[email protected]> | 2013-03-02 12:59:36 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2013-05-31 14:52:17 +0200 |
commit | c11b5a2ebb602c76d0957b67a0ca7741c45fea85 (patch) | |
tree | b9dd1abb048ea3359facc5eb20e8511bd5fe430c /lib/asn1/src | |
parent | 95af544936f9b6d7b8d03f3f49effaf5c314513d (diff) | |
download | otp-c11b5a2ebb602c76d0957b67a0ca7741c45fea85.tar.gz otp-c11b5a2ebb602c76d0957b67a0ca7741c45fea85.tar.bz2 otp-c11b5a2ebb602c76d0957b67a0ca7741c45fea85.zip |
PER: Fix aligments bugs for short strings
The encoder wrongly assumed that a known multiplier string (such as
IA5String) encoded as exactly 16 bits did not need to be aligned to an
octet boundary. X.691 (07/2002) 27.5.7 says that it does. Since an
OCTET STRING encoded to 16 bits (two octets) should not be aligned to
an octet boundary, that means that asnct_imm:dec_string() needs an
additional parameter to determine whether a string of a given length
needs to be aligned.
Furthermore, there is another subtle rule difference: An OCTET STRING
which does not have fixed length is always aligned (in PER), but
a known multiplier string is aligned if its upper bound is greater
than or equal to 16.
In encoding, make sure that short known multiplier strings and
OCTET STRINGs with extensible sizes are not aligned when they are
below the appropriate limit.
Diffstat (limited to 'lib/asn1/src')
-rw-r--r-- | lib/asn1/src/asn1ct_imm.erl | 43 | ||||
-rw-r--r-- | lib/asn1/src/asn1rtt_per.erl | 31 |
2 files changed, 55 insertions, 19 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. |