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 | |
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')
-rw-r--r-- | lib/asn1/src/asn1rt_per_bin.erl | 49 | ||||
-rw-r--r-- | lib/asn1/src/asn1rt_per_bin_rt2ct.erl | 61 | ||||
-rw-r--r-- | lib/asn1/src/asn1rt_uper_bin.erl | 44 |
3 files changed, 124 insertions, 30 deletions
diff --git a/lib/asn1/src/asn1rt_per_bin.erl b/lib/asn1/src/asn1rt_per_bin.erl index 5772f09bf4..1f8c9729e7 100644 --- a/lib/asn1/src/asn1rt_per_bin.erl +++ b/lib/asn1/src/asn1rt_per_bin.erl @@ -505,12 +505,21 @@ decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) -> %% | binary %% Contraint = not used in this version %% -encode_open_type(_C, Val) when is_list(Val) -> - Bin = list_to_binary(Val), - [encode_length(undefined,size(Bin)),{octets,Bin}]; % octets implies align -encode_open_type(_C, Val) when is_binary(Val) -> - [encode_length(undefined,size(Val)),{octets,Val}]. % octets implies align -%% the binary_to_list is not optimal but compatible with the current solution +encode_open_type(_Constraint, Val) when is_list(Val) -> + encode_open_type_1(list_to_binary(Val)); +encode_open_type(_Constraint, Val) when is_binary(Val) -> + encode_open_type_1(Val). + +encode_open_type_1(Val0) -> + case byte_size(Val0) of + Size when Size < 16384 -> + [encode_length(undefined, Size),{octets,Val0}]; + Size -> + F = min(Size bsr 14, 4), + SegSz = F * ?'16K', + <<Val:SegSz/binary,T/binary>> = Val0, + [{octets,<<3:2,F:6>>},{octets,Val}|encode_open_type_1(T)] + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% decode_open_type(Buffer,Constraint) -> Value @@ -518,9 +527,20 @@ encode_open_type(_C, Val) when is_binary(Val) -> %% Buffer = [byte] with PER encoded data %% Value = [byte] with decoded data (which must be decoded again as some type) %% -decode_open_type(Bytes, _C) -> - {Len,Bytes2} = decode_length(Bytes,undefined), - getoctets_as_bin(Bytes2,Len). +decode_open_type(Bytes, _Constraint) -> + 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,Bytes} = getoctets_as_bin(Bytes1, Len), + decode_open_type_1(Bytes, [Acc,Bin]) + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList @@ -884,6 +904,17 @@ decode_small_length(Buffer) -> decode_length(Remain,undefined) end. +decode_length_unlimited(Buffer) -> + case align(Buffer) of + {0,<<0:1,Oct:7,Rest/binary>>} -> + {Oct,{0,Rest}}; + {0,<<1:1,0:1,Val:14,Rest/binary>>} -> + {Val,{0,Rest}}; + {0,<<1:1,1:1,F:6,Rest/binary>>} -> + SegSz = F * ?'16K', + {SegSz,{0,Rest}} + end. + decode_length(Buffer) -> decode_length(Buffer,undefined). 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). diff --git a/lib/asn1/src/asn1rt_uper_bin.erl b/lib/asn1/src/asn1rt_uper_bin.erl index abe178a69e..4e18753a16 100644 --- a/lib/asn1/src/asn1rt_uper_bin.erl +++ b/lib/asn1/src/asn1rt_uper_bin.erl @@ -323,10 +323,21 @@ decode_fragmented_octets(<<0:1,Len:7,BitStr/bitstring>>,C,Acc) -> %% | binary %% Contraint = not used in this version %% -encode_open_type(C, Val) when is_list(Val) -> - encode_open_type(C, list_to_binary(Val)); -encode_open_type(_C, Val) when is_binary(Val) -> - [encode_length(undefined,size(Val)),Val]. +encode_open_type(_Constraint, Val) when is_list(Val) -> + encode_open_type_1(list_to_binary(Val)); +encode_open_type(_Constraint, Val) when is_binary(Val) -> + encode_open_type_1(Val). + +encode_open_type_1(Val0) -> + case byte_size(Val0) of + Size when Size < 16384 -> + [encode_length(undefined, Size),Val0]; + Size -> + F = min(Size bsr 14, 4), + SegSz = F * ?'16K', + <<Val:SegSz/binary,T/binary>> = Val0, + [<<3:2,F:6>>,Val|encode_open_type_1(T)] + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -335,9 +346,20 @@ encode_open_type(_C, Val) when is_binary(Val) -> %% Buffer = [byte] with PER encoded data %% Value = [byte] with decoded data (which must be decoded again as some type) %% -decode_open_type(Bytes, _C) -> - {Len,Bytes2} = decode_length(Bytes,undefined), - getoctets_as_bin(Bytes2,Len). +decode_open_type(Bytes, _Constraint) -> + 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/bitstring>> = Bytes1, + decode_open_type_1(Bytes, [Acc,Bin]) + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList @@ -632,6 +654,14 @@ decode_small_length(Buffer) -> decode_length(Remain,undefined) end. +decode_length_unlimited(<<0:1,Oct:7,Rest/bitstring>>) -> + {Oct,Rest}; +decode_length_unlimited(<<1:1,0:1,Val:14,Rest/bitstring>>) -> + {Val,Rest}; +decode_length_unlimited(<<1:1,1:1,F:6,Rest/bitstring>>) -> + SegSz = F * ?'16K', + {SegSz,Rest}. + decode_length(Buffer) -> decode_length(Buffer,undefined). |