diff options
author | Björn Gustavsson <[email protected]> | 2013-08-06 12:05:21 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2013-08-08 15:30:06 +0200 |
commit | 302ad9890fbd71ad54cb6a0ae4f5e6cfe198b485 (patch) | |
tree | de88653f5c0acfc4c748bb86c995320add1befb3 /lib/asn1/src/asn1rt_per_bin_rt2ct.erl | |
parent | 90f6229822c720d7616f9a11d1ca51e522586564 (diff) | |
download | otp-302ad9890fbd71ad54cb6a0ae4f5e6cfe198b485.tar.gz otp-302ad9890fbd71ad54cb6a0ae4f5e6cfe198b485.tar.bz2 otp-302ad9890fbd71ad54cb6a0ae4f5e6cfe198b485.zip |
PER, UPER: Fix encoding/decoding of open types greater than 16K
Diffstat (limited to 'lib/asn1/src/asn1rt_per_bin_rt2ct.erl')
-rw-r--r-- | lib/asn1/src/asn1rt_per_bin_rt2ct.erl | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl index 1df757a47f..9ce5b086cd 100644 --- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl +++ b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl @@ -378,21 +378,32 @@ decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) -> %% Contraint = not used in this version %% encode_open_type(_Constraint, Val) when is_list(Val) -> - Bin = list_to_binary(Val), - case size(Bin) of - Size when Size>255 -> - [encode_length(undefined,Size),[21,<<Size:16>>,Bin]]; - Size -> - [encode_length(undefined,Size),[20,Size,Bin]] - end; + encode_open_type_1(list_to_binary(Val)); encode_open_type(_Constraint, Val) when is_binary(Val) -> - case size(Val) of - Size when Size>255 -> - [encode_length(undefined,size(Val)),[21,<<Size:16>>,Val]]; % octets implies align + encode_open_type_1(Val). + +encode_open_type_1(Val) -> + case byte_size(Val) of + Size when Size < 256 -> + [encode_length(undefined, Size),20,Size,Val]; + Size when Size < 16384 -> + [encode_length(undefined, Size),21,<<Size:16>>,Val]; Size -> - [encode_length(undefined,Size),[20,Size,Val]] + encode_fragmented(Val, Size) + end. + +encode_fragmented(Val0, Size) -> + case Size bsr 14 of + F when F >= 4 -> + <<Val1:16#8000/binary,Val2:16#8000/binary,T/binary>> = Val0, + [20,1,16#C4,<<21,16#8000:16>>,Val1, + <<21,16#8000:16>>,Val2|encode_open_type_1(T)]; + F -> + SegSz = F * ?'16K', + <<Val:SegSz/binary,T/binary>> = Val0, + [<<20,1,3:2,F:6,21,SegSz:16>>,Val|encode_open_type_1(T)] end. -%% the binary_to_list is not optimal but compatible with the current solution + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% decode_open_type(Buffer,Constraint) -> Value @@ -401,8 +412,19 @@ encode_open_type(_Constraint, Val) when is_binary(Val) -> %% Value = [byte] with decoded data (which must be decoded again as some type) %% decode_open_type(Bytes, _Constraint) -> - {Len,Bytes2} = decode_length(Bytes,undefined), - getoctets_as_bin(Bytes2,Len). + decode_open_type_1(Bytes, []). + +decode_open_type_1(Bytes0, Acc) -> + case decode_length_unlimited(Bytes0) of + {Len,Bytes} when Len < ?'16K', Acc =:= [] -> + getoctets_as_bin(Bytes, Len); + {Len,Bytes1} when Len < ?'16K' -> + {Bin,Bytes} = getoctets_as_bin(Bytes1, Len), + {iolist_to_binary([Acc,Bin]),Bytes}; + {Len,Bytes1} -> + <<Bin:Len/binary,Bytes/binary>> = Bytes1, + decode_open_type_1(Bytes, [Acc,Bin]) + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList @@ -788,6 +810,17 @@ decode_small_length(Buffer) -> decode_length(Remain,undefined) end. +decode_length_unlimited(Buffer) -> + case align(Buffer) of + <<0:1,Oct:7,Rest/binary>> -> + {Oct,Rest}; + <<1:1,0:1,Val:14,Rest/binary>> -> + {Val,Rest}; + <<1:1,1:1,F:6,Rest/binary>> -> + SegSz = F * ?'16K', + {SegSz,Rest} + end. + decode_length(Buffer) -> decode_length(Buffer,undefined). |