diff options
Diffstat (limited to 'lib/asn1')
-rw-r--r-- | lib/asn1/src/asn1ct_check.erl | 2 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_gen_ber_bin_v2.erl | 2 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_gen_per.erl | 16 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_gen_per_rt2ct.erl | 15 | ||||
-rw-r--r-- | lib/asn1/src/asn1rt_per_bin.erl | 46 | ||||
-rw-r--r-- | lib/asn1/src/asn1rt_per_bin_rt2ct.erl | 39 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE.erl | 1 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE_data/Constraints.py | 5 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE_data/LargeConstraints.py | 9 | ||||
-rw-r--r-- | lib/asn1/test/testConstraints.erl | 74 |
10 files changed, 135 insertions, 74 deletions
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 494a2eddd9..59e82b7a57 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -4177,7 +4177,7 @@ check_constraint(S,{'SizeConstraint',Lb}) -> check_constraint(S,{'SingleValue', L}) when is_list(L) -> F = fun(A) -> resolv_value(S,A) end, - {'SingleValue',lists:map(F,L)}; + {'SingleValue',lists:sort(lists:map(F,L))}; check_constraint(S,{'SingleValue', V}) when is_integer(V) -> Val = resolv_value(S,V), diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index 597fb0030b..3ccfca3784 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -419,7 +419,7 @@ gen_decode_selected(Erules,Type,FuncName) -> " {Tlv,_} = ?RT_BER:decode(Bin2",asn1ct_gen:nif_parameter(),"),",nl]), emit("{ok,"), gen_decode_selected_type(Erules,Type), - emit(["};",nl," Err -> exit({error,{selctive_decode,Err}})",nl, + emit(["};",nl," Err -> exit({error,{selective_decode,Err}})",nl, " end.",nl]). gen_decode_selected_type(_Erules,TypeDef) -> diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 5f42eacbdc..bd5b81991d 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -321,19 +321,13 @@ effective_constr(_,[]) -> []; effective_constr('SingleValue',List) -> SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)), - % sort and remove duplicates - SortedSVList = lists:sort(SVList), - RemoveDup = fun([],_) ->[]; - ([H],_) -> [H]; - ([H,H|T],F) -> F([H|T],F); - ([H|T],F) -> [H|F(T,F)] - end, - - case RemoveDup(SortedSVList,RemoveDup) of + %% Sort and remove duplicates before generating SingleValue or ValueRange + %% In case of ValueRange, also check for 'MIN and 'MAX' + case lists:usort(SVList) of [N] -> [{'SingleValue',N}]; - L when is_list(L) -> - [{'ValueRange',{hd(L),lists:last(L)}}] + L when is_list(L) -> + [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}] end; effective_constr('ValueRange',List) -> LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List), diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl index eda0faad3c..16eec92847 100644 --- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl +++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl @@ -670,18 +670,13 @@ effective_constr(_,[]) -> []; effective_constr('SingleValue',List) -> SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)), - % sort and remove duplicates - RemoveDup = fun([],_) ->[]; - ([H],_) -> [H]; - ([H,H|T],F) -> F([H|T],F); - ([H|T],F) -> [H|F(T,F)] - end, - - case RemoveDup(SVList,RemoveDup) of + %% Sort and remove duplicates before generating SingleValue or ValueRange + %% In case of ValueRange, also check for 'MIN and 'MAX' + case lists:usort(SVList) of [N] -> [{'SingleValue',N}]; - L when is_list(L) -> - [{'ValueRange',{hd(L),lists:last(L)}}] + L when is_list(L) -> + [{'ValueRange',{least_Lb(L),greatest_Ub(L)}}] end; effective_constr('ValueRange',List) -> LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List), diff --git a/lib/asn1/src/asn1rt_per_bin.erl b/lib/asn1/src/asn1rt_per_bin.erl index a124c7553d..85988aa21d 100644 --- a/lib/asn1/src/asn1rt_per_bin.erl +++ b/lib/asn1/src/asn1rt_per_bin.erl @@ -18,7 +18,6 @@ %% %% -module(asn1rt_per_bin). - %% encoding / decoding of PER aligned -include("asn1_records.hrl"). @@ -57,7 +56,7 @@ encode_NumericString/2, decode_NumericString/2, encode_ObjectDescriptor/2, decode_ObjectDescriptor/1 ]). --export([complete_bytes/1, getbits/2, getoctets/2]). +-export([complete_bytes/1, getbits/2, getoctets/2, minimum_bits/1]). -define('16K',16384). -define('32K',32768). @@ -695,21 +694,28 @@ encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val -> {octets,[Val2]}; Range =< 65536 -> {octets,<<Val2:16>>}; - Range =< 16#1000000 -> - Octs = eint_positive(Val2), - [{bits,2,length(Octs)-1},{octets,Octs}]; - Range =< 16#100000000 -> - Octs = eint_positive(Val2), - [{bits,2,length(Octs)-1},{octets,Octs}]; - Range =< 16#10000000000 -> - Octs = eint_positive(Val2), - [{bits,3,length(Octs)-1},{octets,Octs}]; + Range =< (1 bsl (255*8)) -> + Octs = binary:encode_unsigned(Val2), + RangeOcts = binary:encode_unsigned(Range - 1), + OctsLen = erlang:byte_size(Octs), + RangeOctsLen = erlang:byte_size(RangeOcts), + LengthBitsNeeded = minimum_bits(RangeOctsLen - 1), + [{bits, LengthBitsNeeded, OctsLen - 1}, {octets, Octs}]; true -> exit({not_supported,{integer_range,Range}}) end; encode_constrained_number(Range,Val) -> exit({error,{asn1,{integer_range,Range,value,Val}}}). +%% For some reason the minimum bits needed in the length field in encoding of +%% constrained whole numbers must always be atleast 2? +minimum_bits(N) when N < 4 -> 2; +minimum_bits(N) when N < 8 -> 3; +minimum_bits(N) when N < 16 -> 4; +minimum_bits(N) when N < 32 -> 5; +minimum_bits(N) when N < 64 -> 6; +minimum_bits(N) when N < 128 -> 7; +minimum_bits(_N) -> 8. decode_constrained_number(Buffer,{Lb,Ub}) -> Range = Ub - Lb + 1, @@ -738,18 +744,12 @@ decode_constrained_number(Buffer,{Lb,Ub}) -> getoctets(Buffer,1); Range =< 65536 -> getoctets(Buffer,2); - Range =< 16#1000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,3}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#100000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,4}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#10000000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,5}), - {Octs,Bytes3} = getoctets_as_list(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; + Range =< (1 bsl (255*8)) -> + OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)), + RangeOctLen = length(OList), + {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}), + {Octs, RestBytes} = getoctets_as_list(Bytes, Len), + {binary:decode_unsigned(binary:list_to_bin(Octs)), RestBytes}; true -> exit({not_supported,{integer_range,Range}}) end, diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl index 750b59aba6..46d4bcb065 100644 --- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl +++ b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl @@ -18,7 +18,6 @@ %% %% -module(asn1rt_per_bin_rt2ct). - %% encoding / decoding of PER aligned -include("asn1_records.hrl"). @@ -605,19 +604,13 @@ encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val -> Range =< 65536 -> % Size = {octets,<<Val2:16>>}; [20,2,<<Val2:16>>]; - Range =< 16#1000000 -> - Octs = eint_positive(Val2), -% [{bits,2,length(Octs)-1},{octets,Octs}]; - Len = length(Octs), - [10,2,Len-1,20,Len,Octs]; - Range =< 16#100000000 -> - Octs = eint_positive(Val2), - Len = length(Octs), - [10,2,Len-1,20,Len,Octs]; - Range =< 16#10000000000 -> - Octs = eint_positive(Val2), - Len = length(Octs), - [10,3,Len-1,20,Len,Octs]; + Range =< (1 bsl (255*8)) -> + Octs = binary:encode_unsigned(Val2), + RangeOcts = binary:encode_unsigned(Range - 1), + OctsLen = erlang:byte_size(Octs), + RangeOctsLen = erlang:byte_size(RangeOcts), + LengthBitsNeeded = asn1rt_per_bin:minimum_bits(RangeOctsLen - 1), + [10,LengthBitsNeeded,OctsLen-1,20,OctsLen,Octs]; true -> exit({not_supported,{integer_range,Range}}) end; @@ -661,18 +654,12 @@ decode_constrained_number(Buffer,{Lb,_Ub},Range) -> getoctets(Buffer,1); Range =< 65536 -> getoctets(Buffer,2); - Range =< 16#1000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,3}), - {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#100000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,4}), - {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; - Range =< 16#10000000000 -> - {Len,Bytes2} = decode_length(Buffer,{1,5}), - {Octs,Bytes3} = getoctets_as_bin(Bytes2,Len), - {dec_pos_integer(Octs),Bytes3}; + Range =< (1 bsl (255*8)) -> + OList = binary:bin_to_list(binary:encode_unsigned(Range - 1)), + RangeOctLen = length(OList), + {Len, Bytes} = decode_length(Buffer, {1, RangeOctLen}), + {Octs, RestBytes} = getoctets_as_bin(Bytes, Len), + {binary:decode_unsigned(Octs), RestBytes}; true -> exit({not_supported,{integer_range,Range}}) end, diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index e9b680d1be..56f31de638 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -773,6 +773,7 @@ per_open_type(Config, Rule, Opts) -> testConstraints(Config) -> test(Config, fun testConstraints/3). testConstraints(Config, Rule, Opts) -> asn1_test_lib:compile("Constraints", Config, [Rule|Opts]), + asn1_test_lib:compile("LargeConstraints", Config, [Rule|Opts]), testConstraints:int_constraints(Rule). diff --git a/lib/asn1/test/asn1_SUITE_data/Constraints.py b/lib/asn1/test/asn1_SUITE_data/Constraints.py index de48c4c2ca..87243121f7 100644 --- a/lib/asn1/test/asn1_SUITE_data/Constraints.py +++ b/lib/asn1/test/asn1_SUITE_data/Constraints.py @@ -4,9 +4,14 @@ BEGIN -- Single Value SingleValue ::= INTEGER (1) SingleValue2 ::= INTEGER (1..20) +predefined INTEGER ::= 1 +SingleValue3 ::= INTEGER (predefined | 5 | 10) Range2to19 ::= INTEGER (1<..<20) Range10to20 ::= INTEGER (10..20) ContainedSubtype ::= INTEGER (INCLUDES Range10to20) +-- Some ranges for additional constrained number testing. +LongLong ::= INTEGER (0..18446744073709551615) +Range256to65536 ::= INTEGER (256..65536) FixedSize ::= OCTET STRING (SIZE(10)) FixedSize2 ::= OCTET STRING (SIZE(10|20)) VariableSize ::= OCTET STRING (SIZE(1..10)) diff --git a/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py b/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py new file mode 100644 index 0000000000..68c7616b62 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/LargeConstraints.py @@ -0,0 +1,9 @@ +LargeConstraints DEFINITIONS ::= +BEGIN + +-- Maximum number that can be encoded as a constrained whole number: 1 bsl (255*8) +-- The number of octets needed to represent a number cannot be more than 255 +-- As the length field is encoded as a 8-bit bitfield. +RangeMax ::= INTEGER (1..126238304966058622268417487065116999845484776053576109500509161826268184136202698801551568013761380717534054534851164138648904527931605160527688095259563605939964364716019515983399209962459578542172100149937763938581219604072733422507180056009672540900709554109516816573779593326332288314873251559077853068444977864803391962580800682760017849589281937637993445539366428356761821065267423102149447628375691862210717202025241630303118559188678304314076943801692528246980959705901641444238894928620825482303431806955690226308773426829503900930529395181208739591967195841536053143145775307050594328881077553168201547776) + +END diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl index 1ce68ec522..543c106e8a 100644 --- a/lib/asn1/test/testConstraints.erl +++ b/lib/asn1/test/testConstraints.erl @@ -52,8 +52,6 @@ int_constraints(Rules) -> ?line {error,_Reason2} = asn1_wrapper:encode('Constraints','SingleValue',1000) end, - - %%========================================================== %% SingleValue2 ::= INTEGER (1..20) @@ -86,7 +84,21 @@ int_constraints(Rules) -> asn1_wrapper:encode('Constraints','SingleValue',1000) end, + %%========================================================== + %% SingleValue3 ::= INTEGER (Predefined | 5 | 10) + %% Testcase for OTP-10139. A single value subtyping of an integer type + %% where one value is predefined. + %%========================================================== + ?line {ok,BytesSV3} = asn1_wrapper:encode('Constraints','SingleValue3',1), + ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue3', + lists:flatten(BytesSV3)), + ?line {ok,BytesSV3_2} = asn1_wrapper:encode('Constraints','SingleValue3',5), + ?line {ok,5} = asn1_wrapper:decode('Constraints','SingleValue3', + lists:flatten(BytesSV3_2)), + ?line {ok,BytesSV3_3} = asn1_wrapper:encode('Constraints','SingleValue3',10), + ?line {ok,10} = asn1_wrapper:decode('Constraints','SingleValue3', + lists:flatten(BytesSV3_3)), %%========================================================== %% Range2to19 ::= INTEGER (1<..<20) @@ -116,7 +128,65 @@ int_constraints(Rules) -> ?line {error,_Reason6} = asn1_wrapper:encode('Constraints','Range2to19',20) end, + + %%========================================================== + %% Tests for Range above 16^4 up to maximum supported by asn1 assuming the + %% octet length field is encoded on max 8 bits + %%========================================================== + LastNumWithoutLengthEncoding = 65536, + ?line {ok,BytesFoo} = asn1_wrapper:encode('Constraints','Range256to65536', + LastNumWithoutLengthEncoding), + ?line {ok,LastNumWithoutLengthEncoding} = + asn1_wrapper:decode('Constraints','Range256to65536',lists:flatten(BytesFoo)), + + FirstNumWithLengthEncoding = 65537, + ?line {ok,BytesBar} = asn1_wrapper:encode('LargeConstraints','RangeMax', + FirstNumWithLengthEncoding), + ?line {ok,FirstNumWithLengthEncoding} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBar)), + + FirstNumOver16_6 = 16777217, + ?line {ok, BytesBaz} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_6), + ?line {ok, FirstNumOver16_6} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBaz)), + + FirstNumOver16_8 = 4294967297, + ?line {ok, BytesQux} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_8), + ?line {ok, FirstNumOver16_8} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesQux)), + + FirstNumOver16_10 = 1099511627776, + ?line {ok, BytesBur} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10), + ?line {ok, FirstNumOver16_10} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)), + + FirstNumOver16_10 = 1099511627776, + ?line {ok, BytesBur} = + asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10), + ?line {ok, FirstNumOver16_10} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)), + + HalfMax = 1 bsl (128*8), + ?line {ok, BytesHalfMax} = + asn1_wrapper:encode('LargeConstraints','RangeMax', HalfMax), + ?line {ok, HalfMax} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesHalfMax)), + + Max = 1 bsl (255*8), + ?line {ok, BytesMax} = + asn1_wrapper:encode('LargeConstraints','RangeMax', Max), + ?line {ok, Max} = + asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesMax)), + %% Random number within longlong range + LongLong = 12672809400538808320, + ?line {ok, BytesLongLong} = + asn1_wrapper:encode('Constraints','LongLong', LongLong), + ?line {ok, LongLong} = + asn1_wrapper:decode('Constraints','LongLong',lists:flatten(BytesLongLong)), %%========================================================== %% Constraint Combinations (Duboisson p. 285) |