Patch for ASN1 Library

View: New views
1 Messages — Rating Filter:   Alert me  

Patch for ASN1 Library

by Aude Quintana :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello !

Here is a proposition for a patch for Erlang asn1 library.

I hope I didn't reimplement existing functionality, but I didn't manage to do it another way.

If the functionality is already implemented, thanks to reply me with some indication on how to proceed using it.

So this patch should be used to catch decoding error when the message to decode is incomplete and to return the error {error,incomplete} in this case. The existing behaviour is to throw various hard-to-match errors.

This change is necessary when using APER norm. The APER norm makes impossible to foresee the message length and so to foresee if the packet to decode is long enough to contain a full packet. So, when decoding a packet with error, it is impossible to say if it is because the contained message is incomplete or other.

With BER encoding it is cheap to read the size of the message, but with PER you have to decode the whole message first, so an in-library solution is better.

.diff file attached with the details of my modifications to add the return of the error {error,incomplete} in case of an incomplete message.

In the following files :
    asn1rt_ber_bin.erl
    asn1rt_ber_bin_v2.erl
    asn1rt_uper_bin.erl
    asn1rt_per_bin.erl
    asn1rt_per_bin_rt2ct.erl
the size of the buffer put in argument should be check each time a function wants to match a precise number of bytes (related to an expected size of message).

This means
* to add a check_bit_size(Buffer,BitSize) or a check_bin_size(Buffer,BinSize) each time we had something like "<<Bin:5/binary,Rest/binary>> = Buffer",
* and to add pattern functions, for example: for getbit(Bin) we must add getbit(<<>>) -> throw({error,incomplete}) and not let the system crashed.

Note that check_bit_size/2 et check_bin_size/2 are functions added in each file.

Eventually, in the generator file asn1ct_gen.erl, just 2 lines in decode_disp/2 must be added to forward the error {error,incomplete} to the parent module.

This seems to be enough to implement the error matching, I tried to test with my data and it works and with bad data, it replies with an error {error,incomplete}.

What do you think about it ?

Best regards,
Aude.

--
Aude Quintana

[patch_lib_asn1.diff]

diff -u -r old/asn1ct_gen.erl new/asn1ct_gen.erl
--- old/asn1ct_gen.erl 2009-08-12 15:44:57.000000000 +0200
+++ new/asn1ct_gen.erl 2009-08-18 10:00:41.000000000 +0200
@@ -969,6 +969,8 @@
       end,
     
     emit(["case catch decode_disp(Type,",DecWrap,") of",nl,
+  "  {error,incomplete} ->",nl,
+  "    {error,incomplete};",nl,
   "  {'EXIT',{error,Reason}} ->",nl,
   "    {error,Reason};",nl,
   "  {'EXIT',Reason} ->",nl,
diff -u -r old/asn1rt_ber_bin.erl new/asn1rt_ber_bin.erl
--- old/asn1rt_ber_bin.erl 2009-08-12 16:02:39.000000000 +0200
+++ new/asn1rt_ber_bin.erl 2009-08-17 19:32:00.000000000 +0200
@@ -150,6 +150,7 @@
 decode_tlv(Bin) ->
     {Tag,Bin1,_Rb1} = decode_tag(Bin),
     {{Len,Bin2},_Rb2} = decode_length(Bin1),
+    check_bin_size(Bin2,Len),
     <<V:Len/binary,Bin3/binary>> = Bin2,
     {{Tag,Len,V},Bin3}.
 
@@ -163,6 +164,7 @@
 split_list(List,indefinite) ->
     {List, indefinite};
 split_list(Bin, Len) when is_binary(Bin) ->
+    check_bin_size(Bin,Len),
     split_binary(Bin,Len);
 split_list(List,Len) ->
     {lists:sublist(List,Len),lists:nthtail(Len,List)}.
@@ -173,6 +175,8 @@
     {RemBytes,2};
 restbytes2(indefinite,RemBytes,ext) ->
     skipvalue(indefinite,RemBytes);
+restbytes2(indefinite,Bin,_) when Bin=:=<<>> orelse Bin=:=<<0>> ->
+    throw({error,incomplete});
 restbytes2(RemBytes,<<>>,_) ->
     {RemBytes,0};
 restbytes2(_RemBytes,Bytes,noext) ->
@@ -208,6 +212,7 @@
  {{0,0,0},0} ->
     skipvalue(indefinite,Bytes3,Rb+2,IndefLevel - 1);
  _ ->
+    check_bin_size(Bytes3,L),
     <<_:L/binary, RestBytes/binary>> = Bytes3,
     skipvalue(indefinite,RestBytes,Rb+R2+R3+L, IndefLevel)
     %%{RestBytes, R2+R3+L}
@@ -218,6 +223,7 @@
 %% _  -> skipvalue(indefinite,Bytes4,Rb+Rb4)
 %%     end;
 skipvalue(L, Bytes, Rb, _) ->
+    check_bin_size(Bytes,L),
 %    <<Skip:L/binary, RestBytes/binary>> = Bytes,
     <<_:L/binary, RestBytes/binary>> = Bytes,
     {RestBytes,Rb+L}.
@@ -325,7 +331,8 @@
 %% interprets the first byte and possible  second, third and fourth byte as
 %% a tag and returns all the bytes comprising the tag, the constructed/primitive bit (6:th bit of first byte) is normalised to 0
 %%
-
+peek_tag(<<>>) ->
+    throw({error,incomplete});
 peek_tag(<<B7_6:2,_:1,31:5,Buffer/binary>>) ->
     Bin = peek_tag(Buffer, <<>>),
     <<B7_6:2,31:6,Bin/binary>>;
@@ -333,6 +340,8 @@
 peek_tag(<<B7_6:2,_:1,B4_0:5,_Buffer/binary>>) ->
     <<B7_6:2,B4_0:6>>.
 
+peek_tag(<<>>,_) ->
+    throw({error,incomplete});
 peek_tag(<<0:1,PartialTag:7,_Buffer/binary>>, TagAck) ->
     <<TagAck/binary,PartialTag>>;
 peek_tag(<<PartialTag,Buffer/binary>>, TagAck) ->
@@ -366,7 +375,9 @@
 
 %% single tag (< 31 tags)
 decode_tag(<<Class:2,Form:1,TagNo:5, Buffer/binary>>) ->
-    {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer, 1}.
+    {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer, 1};
+decode_tag(<<>>) ->
+    throw({error, incomplete}).
 
 %% last partial tag
 decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
@@ -377,7 +388,9 @@
 decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
     TagAck1 = (TagAck bsl 7) bor PartialTag,
     %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>,
-    decode_tag(Buffer, TagAck1, RemovedBytes+1).
+    decode_tag(Buffer, TagAck1, RemovedBytes+1);
+decode_tag(<<>>,_TagAck,_RemovedBytes) ->
+    throw({error, incomplete}).
 
 %%------------------------------------------------------------------
 %% check_tags_i is the same as check_tags except that it stops and
@@ -560,6 +573,7 @@
     {_Tag, Len, RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
     {_RemainingBuffer2, RemovedBytes2} = skipvalue(Len, RemainingBuffer, RemovedBytes),
     N = RemovedBytes2,
+    check_bin_size(Bytes,N),
     <<Val:N/binary, RemainingBytes/binary>> = Bytes,
 %    {Val, RemainingBytes, Len + RemovedBytes}.
     {Val,RemainingBytes,N}.
@@ -579,12 +593,14 @@
     {_RemainingBuffer2, RemovedBytes2} =
  skipvalue(Len, RemainingBuffer),
     N = RemovedBytes2,
+    check_bin_size(Bytes,RemovedBytes+N),
     <<_:RemovedBytes/unit:8,Val:N/binary,RemainingBytes/binary>> = Bytes,
     {Val, RemainingBytes, N + RemovedBytes};
  _ ->
     {_RemainingBuffer2, RemovedBytes2} =
  skipvalue(Len, RemainingBuffer, RemovedBytes),
     N = RemovedBytes2,
+    check_bin_size(Bytes,N),
     <<Val:N/binary, RemainingBytes/binary>> = Bytes,
     {Val, RemainingBytes, N}
     end.
@@ -648,6 +664,8 @@
     {false, Buffer, RemovedBytes + 1};
 decode_boolean2(<<_:8, Buffer/binary>>, RemovedBytes) ->
     {true, Buffer, RemovedBytes + 1};
+decode_boolean2(<<>>,_RemovedBytes) ->
+    throw({error,incomplete});
 decode_boolean2(Buffer, _) ->
     exit({error,{asn1, {decode_boolean, Buffer}}}).
 
@@ -1088,6 +1106,10 @@
 decode_real2(Buffer, _C, 0, _RemBytes) ->
     {0,Buffer};
 decode_real2(Buffer0, _C, Len, RemBytes1) ->
+    case Buffer0 of
+ <<>> -> throw({error,incomplete});
+ _ -> ok
+    end,
     <<First, Buffer2/binary>> = Buffer0,
     if
  First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
@@ -1095,6 +1117,7 @@
 %% First =:= 2#00000000 -> {0, Buffer2};
  First =:= 1 orelse First =:= 2 orelse First =:= 3 ->
     %% charcter string encoding of base 10
+    check_bin_size(Buffer2,Len-1),
     {NRx,Rest} = split_binary(Buffer2,Len-1),
     {binary_to_list(NRx),Rest,Len};
  true ->
@@ -1112,6 +1135,10 @@
     1 -> {3, decode_integer2(2, Buffer2, RemBytes1), RemBytes1+2};
     2 -> {4, decode_integer2(3, Buffer2, RemBytes1), RemBytes1+3};
     3 ->
+ case Buffer2 of
+    <<>> -> throw({error,incomplete});
+    _ -> ok
+ end,
  <<ExpLen1,RestBuffer/binary>> = Buffer2,
  { ExpLen1 + 2,
   decode_integer2(ExpLen1, RestBuffer, RemBytes1),
@@ -1120,6 +1147,7 @@
     %%    io:format("FirstLen: ~w, Exp: ~w, Buffer3: ~w ~n",
 
     Length = Len - FirstLen,
+    check_bin_size(Buffer3,Length),
     <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
     {{Mantissa, Buffer4}, RemBytes3} =
  if Sign =:= 0 ->
@@ -1478,7 +1506,10 @@
     {decode_bitstring_NNL(BitString,NamedNumberList),
      BufferTail,
      RemovedBytes}
-    end.
+    end;
+
+decode_bit_string2(_Len, <<>>,_NamedNumberList,_RemovedBytes,_BinOrOl) ->
+    throw({error,incomplete}).
 
 %%----------------------------------------
 %% Decode the in buffer to bits
@@ -1488,7 +1519,9 @@
 decode_bitstring2(Len, Unused,
   <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
     [B7, B6, B5, B4, B3, B2, B1, B0 |
-     decode_bitstring2(Len - 1, Unused, Buffer)].
+     decode_bitstring2(Len - 1, Unused, Buffer)];
+decode_bitstring2(_Len, _Unused,<<>>) ->
+    throw({error,incomplete}).
 
 %%decode_bitstring2(1, Unused, Buffer) ->
 %%    make_bits_of_int(hd(Buffer), 128, 8-Unused);
@@ -1706,7 +1739,9 @@
 dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al,Len) ->
     dec_subidentifiers(T,(Av bsl 7) + H,Al,Len-1);
 dec_subidentifiers(<<H,T/binary>>,Av,Al,Len) ->
-    dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al],Len-1).
+    dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al],Len-1);
+dec_subidentifiers(<<>>,_Av,_Al,_Len) ->
+    throw({error,incomplete}).
 
 %%============================================================================
 %% RELATIVE-OID, ITU_T X.690 Chapter 8.20
@@ -1913,14 +1948,17 @@
     decode_bit_string2(InnerLen,Buffer,NamedNumberList,InnerLen,BinOrOld);
 
  ?N_UniversalString ->
+    check_bin_size(Buffer,InnerLen),
     <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
     UniString = mk_universal_string(binary_to_list(PreBuff)),
     {UniString,RestBuff,InnerLen};
  ?N_BMPString ->
+    check_bin_size(Buffer,InnerLen),
     <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
     BMP = mk_BMP_string(binary_to_list(PreBuff)),
     {BMP,RestBuff,InnerLen};
  _ ->
+    check_bin_size(Buffer,InnerLen),
     <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
     {PreBuff, RestBuff, InnerLen}
     end.
@@ -2007,6 +2045,7 @@
     {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
     {Val01, Buffer02, Rb0+Rb01+Rb02};
  {_,Len} ->
+    check_bin_size(Buffer0,Len),
     <<Result:Len/binary,RestBuff/binary>> = Buffer0,
     {Result,RestBuff,Rb0 + Len}
     end.
@@ -2093,6 +2132,7 @@
     {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
     {Val01, Buffer02, Rb0+Rb01+Rb02};
  {_,Len} ->
+    check_bin_size(Buffer0,Len),
     <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
     {binary_to_list(PreBuff), RestBuff, Rb0+Len}
     end.
@@ -2133,6 +2173,7 @@
     {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
     {Val01, Buffer02, Rb0+Rb01+Rb02};
  {_,Len} ->
+    check_bin_size(Buffer0,Len),
     <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
     {binary_to_list(PreBuff), RestBuff, Rb0+Len}
     end.
@@ -2184,8 +2225,11 @@
 decode_length(<<0:1,Length:7,T/binary>>) ->
     {{Length,T},1};
 decode_length(<<1:1,LL:7,T/binary>>) ->
+    check_bin_size(T,LL),
     <<Length:LL/unit:8,Rest/binary>> = T,
-    {{Length,Rest}, LL+1}.
+    {{Length,Rest}, LL+1};
+decode_length(<<>>) ->
+    throw({error,incomplete}).
 
 %decode_length([128 | T]) ->
 %    {{indefinite, T},1};
@@ -2431,12 +2475,16 @@
     {EncLen,LenLen}=encode_length(Len),
     {[UniversalTag,EncLen,Bytes],1+LenLen+Len}.
 
+decode_integer2(_Len, <<>>,_RemovedBytes) ->
+    throw({error,incomplete});
 %% decoding postitive integer values.
 decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>,RemovedBytes) ->
+    check_bin_size(Bin,Len),
     <<Int:Len/unit:8,Buffer2/binary>> = Bin,
     {Int,Buffer2,RemovedBytes};
 %% decoding negative integer values.
 decode_integer2(Len,<<1:1,B2:7,Bs/binary>>,RemovedBytes)  ->
+    check_bin_size(Bs,Len-1),
     <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
     Int = N - (1 bsl (8 * Len - 1)),
     {Int,Buffer2,RemovedBytes}.
@@ -2495,3 +2543,10 @@
  _ ->
     Tags ++ [LastTag]
     end.
+
+check_bin_size(Binary, ExpectedSize) ->
+    case size(Binary) of
+ Size when Size < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.
diff -u -r old/asn1rt_ber_bin_v2.erl new/asn1rt_ber_bin_v2.erl
--- old/asn1rt_ber_bin_v2.erl 2009-08-14 14:16:20.000000000 +0200
+++ new/asn1rt_ber_bin_v2.erl 2009-08-17 19:32:18.000000000 +0200
@@ -505,12 +505,15 @@
 
 %% skip_tag and skip_length_and_value are rutines used both by
 %% decode_partial_incomplete and decode_selective (decode/2).
-
+skip_tag(<<>>) ->
+    throw({error, incomplete});
 skip_tag(<<_:3,31:5,Rest/binary>>)->
     skip_long_tag(Rest);
 skip_tag(<<_:3,_Tag:5,Rest/binary>>) ->
     {ok,Rest}.
 
+skip_long_tag(<<>>) ->
+    throw({error,incomplete});
 skip_long_tag(<<1:1,_:7,Rest/binary>>) ->
     skip_long_tag(Rest);
 skip_long_tag(<<0:1,_:7,Rest/binary>>) ->
@@ -531,6 +534,7 @@
  {indefinite,RestBinary} ->
     skip_indefinite_value(RestBinary);
  {Length,RestBinary} ->
+    check_bin_size(RestBinary,Length),
     <<_:Length/unit:8,Rest/binary>> = RestBinary,
     {ok,Rest}
     end.
@@ -547,6 +551,7 @@
  {indefinite,RestBinary} ->
     get_indefinite_value(RestBinary,[]);
  {Length,RestBinary} ->
+    check_bin_size(RestBinary,Length),
     <<Value:Length/binary,_Rest/binary>> = RestBinary,
     {ok,Value}
     end.
@@ -558,12 +563,16 @@
     {ok,{LenVal,RestBinary2}} = get_length_and_value(RestBinary),
     get_indefinite_value(RestBinary2,[LenVal,Tag|Acc]).
 
+get_tag(<<>>) ->
+    throw({error,incomplete});
 get_tag(<<H:1/binary,Rest/binary>>) ->
     case H of
  <<_:3,31:5>> ->
     get_long_tag(Rest,[H]);
  _ -> {ok,{H,Rest}}
     end.
+get_long_tag(<<>>,_) ->
+    throw({error,incomplete});
 get_long_tag(<<H:1/binary,Rest/binary>>,Acc) ->
     case H of
  <<0:1,_:7>> ->
@@ -572,13 +581,18 @@
     get_long_tag(Rest,[H|Acc])
     end.
 
+get_length_and_value(<<>>) ->
+    throw({error,incomplete});
 get_length_and_value(Bin = <<0:1,Length:7,_T/binary>>) ->
+    check_bin_size(Bin,1+Length),
     <<Len,Val:Length/binary,Rest/binary>> = Bin,
     {ok,{<<Len,Val/binary>>, Rest}};
 get_length_and_value(Bin = <<1:1,0:7,_T/binary>>) ->
     get_indefinite_length_and_value(Bin);
 get_length_and_value(<<1:1,LL:7,T/binary>>) ->
+    check_bin_size(T,LL),
     <<Length:LL/unit:8,Rest/binary>> = T,
+    check_bin_size(Rest,Length),
     <<Value:Length/binary,Rest2/binary>> = Rest,
     {ok,{<<1:1,LL:7,Length:LL/unit:8,Value/binary>>,Rest2}}.
 
@@ -685,6 +699,8 @@
 %%
 %% decode_tag(OctetListBuffer) -> {{Form, (Class bsl 16)+ TagNo}, RestOfBuffer, RemovedBytes}
 %%===============================================================================
+decode_tag_and_length(<<>>) ->
+    throw({error,incomplete});
 
 decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 0:1, Length:7, V:Length/binary, RestBuffer/binary>>) when TagNo < 31 ->
     {Form, (Class bsl 16) + TagNo, V, RestBuffer};
@@ -706,12 +722,21 @@
 decode_tag_and_length(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
     {TagNo, Buffer1} = decode_tag(Buffer, 0),
     {Length, RestBuffer} = decode_length(Buffer1),
+    check_bin_size(RestBuffer,Length),
     << V:Length/binary, RestBuffer2/binary>> = RestBuffer,
-    {Form, (Class bsl 16) + TagNo, V, RestBuffer2}.
+    {Form, (Class bsl 16) + TagNo, V, RestBuffer2};
 
+decode_tag_and_length(<<_>>) ->
+    throw({error,incomplete});
+decode_tag_and_length(<<_,_:1,L:7,Rest/binary>>) when size(Rest) < L ->
+    throw({error,incomplete});
+decode_tag_and_length(<<_,_:1,LL:7,Length:LL/binary,Rest/binary>>) when size(Rest) < Length ->
+    throw({error,incomplete}).
 
-    
-%% last partial tag
+
+%% last partial tag
+decode_tag(<<>>,_) ->
+    throw({error,incomplete});
 decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck) ->
     TagNo = (TagAck bsl 7) bor PartialTag,
     %%<<TagNo>> = <<TagAck:1, PartialTag:7>>,
@@ -919,7 +944,9 @@
     range_check_integer(Int,Range),
     Int.
 
-%% decoding postitive integer values.
+%% decoding postitive integer values.
+decode_integer(<<>>) ->
+    throw({error,incomplete});
 decode_integer(Bin = <<0:1,_:7,_/binary>>) ->
     Len = size(Bin),
 %    <<Int:Len/unit:8,Buffer2/binary>> = Bin,
@@ -1087,6 +1114,10 @@
 %%  decode_real2(Buffer, Form, size(Buffer)).
 
 % decode_real2(Buffer, Form, Len) ->
+%     case Buffer of
+%       <<>> -> throw({error,incomplete});
+%       _ -> ok
+%     end,
 %     <<First, Buffer2/binary>> = Buffer,
 %     if
 % First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
@@ -1110,15 +1141,22 @@
 %    {FirstLen,Exp,Buffer3} =
 % case B1_0 of
 %    0 ->
+%                       case Buffer2 of
+%                         <<>> -> throw({error,incomplete});
+%                         _ -> ok
+%                       end,  
 % <<_:1/unit:8,Buffer21/binary>> = Buffer2,
 % {2, decode_integer2(1, Buffer2),Buffer21};
 %    1 ->
+%                       check_bin_size(Buffer2,2),
 % <<_:2/unit:8,Buffer21/binary>> = Buffer2,
 % {3, decode_integer2(2, Buffer2)};
 %    2 ->
+%                       check_bin_size(Buffer2,3),
 % <<_:3/unit:8,Buffer21/binary>> = Buffer2,
 % {4, decode_integer2(3, Buffer2)};
 %    3 ->
+%                       check_bin_size(Buffer2,2),
 % <<ExpLen1,RestBuffer/binary>> = Buffer2,
 % <<_:ExpLen1/unit:8,RestBuffer2/binary>> = RestBuffer,
 % { ExpLen1 + 2,
@@ -1126,6 +1164,7 @@
 %  RestBuffer2}
 % end,
 %    Length = Len - FirstLen,
+%           check_bin_size(Buffer2,Length),
 %    <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
 %    {Mantissa, Buffer4} =
 % if Sign =:= 0 ->
@@ -1424,6 +1463,8 @@
      NamedNumberList,old).
 
 
+decode_bit_string2(<<>>,_,_) ->
+    throw({error,incomplete});
 decode_bit_string2(<<0>>,_NamedNumberList,BinOrOld) ->
     case BinOrOld of
  bin ->
@@ -1453,7 +1494,9 @@
 decode_bitstring2(Len, Unused,
   <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
     [B7, B6, B5, B4, B3, B2, B1, B0 |
-     decode_bitstring2(Len - 1, Unused, Buffer)].
+     decode_bitstring2(Len - 1, Unused, Buffer)];
+decode_bitstring2(_,_Unused,<<>>) ->
+    throw({error,incomplete}).
 
 %%decode_bitstring2(1, Unused, Buffer) ->
 %%    make_bits_of_int(hd(Buffer), 128, 8-Unused);
@@ -1628,7 +1671,7 @@
 dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al) ->
     dec_subidentifiers(T,(Av bsl 7) + H,Al);
 dec_subidentifiers(<<H,T/binary>>,Av,Al) ->
-    dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al]).
+    dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al]).
 
 %%============================================================================
 %% RELATIVE-OID, ITU_T X.690 Chapter 8.20
@@ -1965,12 +2008,14 @@
 %% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} |  
 %%                             {{Length, RestOctetsL}, NoRemovedBytes}
 %%===========================================================================
-
+decode_length(<<>>) ->
+    throw({error,incomplete});
 decode_length(<<1:1,0:7,T/binary>>) ->    
     {indefinite, T};
 decode_length(<<0:1,Length:7,T/binary>>) ->
     {Length,T};
 decode_length(<<1:1,LL:7,T/binary>>) ->
+    check_bin_size(T,LL),
     <<Length:LL/unit:8,Rest/binary>> = T,
     {Length,Rest}.
 
@@ -1981,12 +2026,15 @@
 %%-------------------------------------------------------------------------
 
 
-%% decoding postitive integer values.
+%% decoding postitive integer values.
+decode_integer2(_,<<>>) ->
+    throw({error,incomplete});
 decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>) ->
     <<Int:Len/unit:8>> = Bin,
     Int;
 %% decoding negative integer values.
 decode_integer2(Len,<<1:1,B2:7,Bs/binary>>)  ->
+    check_bin_size(Bs,Len-1),
     <<N:Len/unit:8>> = <<B2,Bs/binary>>,
     Int = N - (1 bsl (8 * Len - 1)),
     Int.
@@ -2004,6 +2052,7 @@
 
 collect_parts([{_,L}|Rest],Acc) when is_list(L) ->
     collect_parts(Rest,[collect_parts(L)|Acc]);
+
 collect_parts([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],_Acc) ->
     collect_parts_bit(Rest,[Bits],Unused);
 collect_parts([{_T,V}|Rest],Acc) ->
@@ -2014,10 +2063,16 @@
 collect_parts_bit([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],Acc,Uacc) ->    
     collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc);
 collect_parts_bit([],Acc,Uacc) ->
-    list_to_binary([Uacc|lists:reverse(Acc)]).
-
-
-
+    list_to_binary([Uacc|lists:reverse(Acc)]);
+collect_parts_bit([{?N_BIT_STRING,<<>>}|_Rest],_Acc,_Uacc) ->
+    throw({error,incomplete}).
+
+check_bin_size(Binary,ExpectedSize) ->
+    case size(Binary) of
+ Size when Size < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.
 
 
 
diff -u -r old/asn1rt_per_bin.erl new/asn1rt_per_bin.erl
--- old/asn1rt_per_bin.erl 2009-08-13 15:07:50.000000000 +0200
+++ new/asn1rt_per_bin.erl 2009-08-17 19:33:08.000000000 +0200
@@ -241,6 +241,7 @@
     Used = Num rem 8,
     Pad = (8 - Used) rem 8,
 %    Nbytes = Num div 8,
+    check_bit_size(Bin,Num+Pad),
     <<Bits:Num,_:Pad,RestBin/binary>> = Bin,
     {{Pad,<<Bits:Num,0:Pad>>},RestBin};
 getbits_as_binary(Num,Buffer={_Used,_Bin}) -> % Unaligned buffer
@@ -268,23 +269,27 @@
 %% If first byte in buffer is full and at least one byte will be picked,
 %% then pick one byte.
 getbits_as_list(N,{0,Bin},Acc) when N >= 8 ->
+    check_bin_size(Bin,1),
     <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>> = Bin,
     getbits_as_list(N-8,{0,Rest},[B0,B1,B2,B3,B4,B5,B6,B7|Acc]);
 getbits_as_list(N,{Used,Bin},Acc) when N >= 4, Used =< 4 ->
     NewUsed = Used + 4,
     Rem = 8 - NewUsed,
+    check_bit_size(Bin,Used+4+Rem),
     <<_:Used,B3:1,B2:1,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
     NewRest = case Rem of 0 -> Rest; _ -> Bin end,
     getbits_as_list(N-4,{NewUsed rem 8,NewRest},[B0,B1,B2,B3|Acc]);
 getbits_as_list(N,{Used,Bin},Acc) when N >= 2, Used =< 6  ->
     NewUsed = Used + 2,
     Rem = 8 - NewUsed,
+    check_bit_size(Bin,Used+2+Rem),
     <<_:Used,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
     NewRest = case Rem of 0 -> Rest; _ -> Bin end,
     getbits_as_list(N-2,{NewUsed rem 8,NewRest},[B0,B1|Acc]);
 getbits_as_list(N,{Used,Bin},Acc) when Used =< 7 ->
     NewUsed = Used + 1,
     Rem = 8 - NewUsed,
+    check_bit_size(Bin,Used+1+Rem),
     <<_:Used,B0:1,_:Rem, Rest/binary>> = Bin,
     NewRest = case Rem of 0 -> Rest; _ -> Bin end,
     getbits_as_list(N-1,{NewUsed rem 8,NewRest},[B0|Acc]).
@@ -296,6 +301,7 @@
     {B,{1,Buffer}};
 getbit({Used,Buffer}) ->
     Unused = (8 - Used) - 1,
+    check_bit_size(Buffer,Used+1+Unused),
     <<_:Used,B:1,_:Unused,_/binary>> = Buffer,
     {B,{Used+1,Buffer}};
 getbit(Buffer) when is_binary(Buffer) ->
@@ -303,6 +309,7 @@
 
 
 getbits({0,Buffer},Num) when (Num rem 8) == 0 ->
+    check_bit_size(Buffer,Num),
     <<Bits:Num,Rest/binary>> = Buffer,
     {Bits,{0,Rest}};
 getbits({Used,Bin},Num) ->
@@ -311,10 +318,12 @@
     Unused = (8-NewUsed) rem 8,
     case Unused of
  0 ->
+    check_bit_size(Bin,Used+Num),
     <<_:Used,Bits:Num,Rest/binary>> = Bin,
     {Bits,{0,Rest}};
  _ ->
     Bytes = NumPlusUsed div 8,
+    check_bit_size(Bin,Used+Num+Unused),
     <<_:Used,Bits:Num,_UBits:Unused,_/binary>> = Bin,
     <<_:Bytes/binary,Rest/binary>> = Bin,
     {Bits,{NewUsed,Rest}}
@@ -345,10 +354,13 @@
 %% First align buffer, then pick the first Num octets.
 %% Returns octets as an integer with bit significance as in buffer.
 getoctets({0,Buffer},Num) ->
+    check_bin_size(Buffer,Num),
     <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
     {Val,{0,RestBin}};
 getoctets({U,<<_Padding,Rest/binary>>},Num) when U /= 0 ->
     getoctets({0,Rest},Num);
+getoctets({_U,<<>>},_Num) ->
+    throw({error,incomplete});
 getoctets(Buffer,Num) when is_binary(Buffer) ->
     getoctets({0,Buffer},Num).
 % getoctets(Buffer,Num) ->
@@ -373,9 +385,11 @@
 %% First align buffer, then pick the first Num octets.
 %% Returns octets as a binary
 getoctets_as_bin({0,Bin},Num)->
+    check_bin_size(Bin,Num),
     <<Octets:Num/binary,RestBin/binary>> = Bin,
     {Octets,{0,RestBin}};
 getoctets_as_bin({_U,Bin},Num) ->
+    check_bin_size(Bin,1+Num),
     <<_Padding,Octets:Num/binary,RestBin/binary>> = Bin,
     {Octets,{0,RestBin}};
 getoctets_as_bin(Bin,Num) when is_binary(Bin) ->
@@ -440,7 +454,9 @@
 decode_fragmented_bits({0,Buffer},C) ->
     decode_fragmented_bits(Buffer,C,[]);
 decode_fragmented_bits({_N,<<_,Bs/binary>>},C) ->
-    decode_fragmented_bits(Bs,C,[]).
+    decode_fragmented_bits(Bs,C,[]);
+decode_fragmented_bits({_N,<<>>},_C) ->
+    throw({error,incomplete}).
 
 decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
     {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
@@ -456,12 +472,14 @@
 decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
     Result = {BinBits,{Used,_Rest}} =
  case (Len rem 8) of
-    0 ->
+    0 ->
+ check_bit_size(Bin,Len),
  <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
  {list_to_binary(lists:reverse([Value|Acc])),{0,Bin2}};
     Rem ->
  Bytes = Len div 8,
  U = 8 - Rem,
+ check_bit_size(Bin,Bytes*8+Rem+U),
  <<Value:Bytes/binary-unit:8,Bits1:Rem,Bits2:U,Bin2/binary>> = Bin,
  {list_to_binary(lists:reverse([Bits1 bsl U,Value|Acc])),
  {Rem,<<Bits2,Bin2/binary>>}}
@@ -471,7 +489,9 @@
     Result;
  Int when is_integer(Int) ->
     exit({error,{asn1,{illegal_value,C,BinBits}}})
-    end.
+    end;
+decode_fragmented_bits(<<>>,_C,_Acc) ->
+    throw({error,incomplete}).
 
 
 decode_fragmented_octets({0,Bin},C) ->
@@ -489,6 +509,7 @@
     exit({error,{asn1,{illegal_value,C,Octets}}})
     end;
 decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
+    check_bin_size(Bin,Len),
     <<Value:Len/binary-unit:8,Bin2/binary>> = Bin,
     BinOctets = list_to_binary(lists:reverse([Value|Acc])),
     case C of
@@ -496,7 +517,9 @@
     {BinOctets,Bin2};
  Int when is_integer(Int) ->
     exit({error,{asn1,{illegal_value,C,BinOctets}}})
-    end.
+    end;
+decode_fragmented_octets(<<>>,_,_) ->
+    throw({error,incomplete}).
 
 
     
@@ -892,8 +915,12 @@
 decode_length(Buffer,undefined)  -> % un-constrained
     {0,Buffer2} = align(Buffer),
     case Buffer2 of
+ Bin when size(Bin) < 1 ->
+    throw({error,incomplete});
  <<0:1,Oct:7,Rest/binary>> ->
     {Oct,{0,Rest}};
+ <<1:1,Rest/bitstring>> when bit_size(Rest) < 15->
+    throw({error, incomplete});
  <<2:2,Val:14,Rest/binary>> ->
     {Val,{0,Rest}};
  <<3:2,_:14,_Rest/binary>> ->
@@ -932,12 +959,17 @@
 decode_length({Used,Bin},{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
     Unused = (8-Used) rem 8,
     case Bin of
+
  <<_:Used,0:1,Val:7,R:Unused,Rest/binary>> ->
     {Val,{Used,<<R,Rest/binary>>}};
+ Bin when bit_size(Bin) < (8+Used+Unused) ->
+    throw({error,incomplete});
  <<_:Used,_:Unused,2:2,Val:14,Rest/binary>> ->
     {Val, {0,Rest}};
  <<_:Used,_:Unused,3:2,_:14,_Rest/binary>> ->
-    exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
+    exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}});
+ <<_Used,_:Unused,1:1,_:7,Rest/binary>> when bit_size(Rest) < 8 ->
+    throw({error,incomplete})
     end;
 % decode_length(Buffer,{_,_Lb,Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
 %     case getbit(Buffer) of
@@ -2280,8 +2312,18 @@
 % complete_bytes2([{V8,B8},{V7,B7},{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
 %     <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,V7:B7,V8:B8,0:PadBits>>.
 
-    
-    
+check_bin_size(Binary,ExpectedSize) ->
+    case size(Binary) of
+ Size when Size < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.
+check_bit_size(BitString,ExpectedSize) ->
+    case bit_size(BitString) of
+ BitSize when BitSize < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.
     
 
 
diff -u -r old/asn1rt_per_bin_rt2ct.erl new/asn1rt_per_bin_rt2ct.erl
--- old/asn1rt_per_bin_rt2ct.erl 2009-08-13 19:00:44.000000000 +0200
+++ new/asn1rt_per_bin_rt2ct.erl 2009-08-17 19:33:36.000000000 +0200
@@ -210,20 +210,24 @@
 %% Bin = bitstring(),
 %% Rest = bitstring()
 getbits_as_binary(Num,Bytes) when is_bitstring(Bytes) ->
+    check_bit_size(Bytes,Num),
     <<BS:Num/bitstring,Rest/bitstring>> = Bytes,
     {BS,Rest}.
     
 getbits_as_list(Num,Bytes) when is_bitstring(Bytes) ->
+    check_bit_size(Bytes,Num),
     <<BitStr:Num/bitstring,Rest/bitstring>> = Bytes,
     {[ B || <<B:1>> <= BitStr],Rest}.
 
-
+getbit(<<>>) ->
+    throw({error,incomplete});
 getbit(Buffer) ->
     <<B:1,Rest/bitstring>> = Buffer,
     {B,Rest}.
 
 
 getbits(Buffer,Num) when is_bitstring(Buffer) ->
+    check_bit_size(Buffer,Num),
     <<Bs:Num,Rest/bitstring>> = Buffer,
     {Bs,Rest}.
 
@@ -237,11 +241,14 @@
 
 %% First align buffer, then pick the first Num octets.
 %% Returns octets as an integer with bit significance as in buffer.
+
 getoctets(Buffer,Num) when is_binary(Buffer) ->
+    check_bin_size(Buffer,Num),
     <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
     {Val,RestBin};
 getoctets(Buffer,Num) when is_bitstring(Buffer) ->
     AlignBits = bit_size(Buffer) rem 8,
+    check_bit_size(Buffer,Num*8+AlignBits),
     <<_:AlignBits,Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
     {Val,RestBin}.
 
@@ -249,10 +256,12 @@
 %% First align buffer, then pick the first Num octets.
 %% Returns octets as a binary
 getoctets_as_bin(Bin,Num) when is_binary(Bin) ->
+    check_bin_size(Bin,Num),
     <<Octets:Num/binary,RestBin/binary>> = Bin,
     {Octets,RestBin};
 getoctets_as_bin(Bin,Num) when is_bitstring(Bin) ->
     AlignBits = bit_size(Bin) rem 8,
+    check_bit_size(Bin,AlignBits+Num*8),
     <<_:AlignBits,Val:Num/binary,RestBin/binary>> = Bin,
     {Val,RestBin}.
     
@@ -336,6 +345,7 @@
     exit({error,{asn1,{illegal_value,C,BinBits}}})
     end;
 decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
+    check_bit_size(Bin,Len),
     <<Value:Len/bitstring,Rest/bitstring>> = Bin,
     BinBits = erlang:list_to_bitstring([Value|Acc]),
     case C of
@@ -349,6 +359,8 @@
 decode_fragmented_octets(Bin,C) ->
     decode_fragmented_octets(Bin,C,[]).
 
+decode_fragmented_octets(<<>>,_C,_Acc) ->
+    throw({error,incomplete});
 decode_fragmented_octets(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
     {Value,Bin2} = split_binary(Bin,Len * ?'16K'),
     decode_fragmented_octets(Bin2,C,[Value|Acc]);
@@ -744,8 +756,9 @@
 dec_integer(<<_:1,B:7,BitStr/bitstring>>) ->
     Size = bit_size(BitStr),
     <<I:Size>> = BitStr,
-    (-128 + B) bsl bit_size(BitStr) bor I.
-
+    (-128 + B) bsl bit_size(BitStr) bor I;
+dec_integer(Bin) when bit_size(Bin) < 8 ->
+    throw({error,incomplete}).
     
     
 decpint(Bin) ->
@@ -811,13 +824,17 @@
 
 decode_length(Buffer,undefined)  -> % un-constrained
     case align(Buffer) of
+ <<>> ->
+    throw({error,incomplete});
  <<0:1,Oct:7,Rest/binary>> ->
     {Oct,Rest};
  <<2:2,Val:14,Rest/binary>> ->
     {Val,Rest};
  <<3:2,_Val:14,_Rest/binary>> ->
     %% this case should be fixed
-    exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
+    exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
+ <<1:1,_:7>> ->
+    throw({error,incomplete})
     end;
 
 decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
@@ -837,6 +854,7 @@
 % X.691:10.9.3.5
 decode_length(Bin,{_,_Lb,_Ub}) -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
     case Bin of
+ <<>> -> throw({error,incomplete});
  <<0:1,Val:7,Rest/bitstring>> ->
     {Val,Rest};
  _ ->
@@ -844,7 +862,9 @@
  <<2:2,Val:14,Rest/binary>> ->
     {Val,Rest};
  <<3:2,_:14,_Rest/binary>> ->
-    exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
+    exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}});
+ <<1:1,_:7>> ->
+    throw({error,incomplete})
     end
     end;
 decode_length(Buffer,SingleValue) when is_integer(SingleValue) ->
@@ -1873,3 +1893,17 @@
     [30,Unused,Len,Val];
 octets_unused_to_complete(Unused,Len,Val) ->
     [31,Unused,<<Len:16>>,Val].
+
+check_bin_size(Binary,ExpectedSize) ->
+    case size(Binary) of
+ Size when Size < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.
+
+check_bit_size(BitString,ExpectedSize) ->
+    case bit_size(BitString) of
+ BitSize when BitSize < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.
diff -u -r old/asn1rt_uper_bin.erl new/asn1rt_uper_bin.erl
--- old/asn1rt_uper_bin.erl 2009-08-18 09:58:25.000000000 +0200
+++ new/asn1rt_uper_bin.erl 2009-08-17 19:32:53.000000000 +0200
@@ -177,33 +177,40 @@
 %% BinBits = binary(),
 %% RestBytes = tuple()
 getbits_as_binary(Num,Bytes) when is_bitstring(Bytes) ->
+    check_bit_size(Bytes,Num),
     <<BS:Num/bitstring,Rest/bitstring>> = Bytes,
     {BS,Rest}.
 
 getbits_as_list(Num,Bytes) when is_bitstring(Bytes) ->
+    check_bit_size(Bytes,Num),
     <<BitStr:Num/bitstring,Rest/bitstring>> = Bytes,
     {[ B || <<B:1>> <= BitStr],Rest}.
 
+getbit(<<>>) ->
+    throw({error,incomplete});
+
 getbit(Buffer) ->
     <<B:1,Rest/bitstring>> = Buffer,
     {B,Rest}.
 
 
 getbits(Buffer,Num) when is_bitstring(Buffer) ->
+    check_bit_size(Buffer,Num),
     <<Bs:Num,Rest/bitstring>> = Buffer,
     {Bs,Rest}.
 
 
-
 %% Pick the first Num octets.
 %% Returns octets as an integer with bit significance as in buffer.
 getoctets(Buffer,Num) when is_bitstring(Buffer) ->
+    check_bin_size(Buffer,Num),
     <<Val:Num/integer-unit:8,RestBitStr/bitstring>> = Buffer,
     {Val,RestBitStr}.
 
 %% Pick the first Num octets.
 %% Returns octets as a binary
 getoctets_as_bin(Bin,Num) when is_bitstring(Bin) ->
+    check_bin_size(Bin,Num),
     <<Octets:Num/binary,RestBin/bitstring>> = Bin,
     {Octets,RestBin}.
 
@@ -265,9 +272,13 @@
 %% If the buffer is not aligned, this function does that.
 decode_fragmented_bits(Buffer,C) ->
     decode_fragmented_bits(Buffer,C,[]).
+
+decode_fragmented_bits(<<>>,_C,[]) ->
+    throw({error, incomplete});
 decode_fragmented_bits(<<3:2,Len:6,BitStr/bitstring>>,C,Acc) ->
 %%    {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
     FragLen = (Len*?'16K') div 8,
+    check_bin_size(BitStr,FragLen),
     <<Value:FragLen/binary,BitStr2/bitstring>> = BitStr,
     decode_fragmented_bits(BitStr2,C,[Value|Acc]);
 decode_fragmented_bits(<<0:1,0:7,BitStr/bitstring>>,C,Acc) ->
@@ -279,6 +290,7 @@
     exit({error,{asn1,{illegal_value,C,BinBits}}})
     end;
 decode_fragmented_bits(<<0:1,Len:7,BitStr/bitstring>>,C,Acc) ->
+    check_bit_size(BitStr,Len),
     <<Val:Len/bitstring,Rest/bitstring>> = BitStr,
 %%    <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
     ResBitStr = list_to_bitstring(lists:reverse([Val|Acc])),
@@ -293,8 +305,11 @@
 decode_fragmented_octets({0,Bin},C) ->
     decode_fragmented_octets(Bin,C,[]).
 
+decode_fragmented_octets(Bin,_C,[]) when bit_size(Bin) < 8->
+    throw({error, incomplete});
 decode_fragmented_octets(<<3:2,Len:6,BitStr/bitstring>>,C,Acc) ->
     FragLen = Len * ?'16K',
+    check_bin_size(BitStr,FragLen),
     <<Value:FragLen/binary,Rest/bitstring>> = BitStr,
     decode_fragmented_octets(Rest,C,[Value|Acc]);
 decode_fragmented_octets(<<0:1,0:7,Bin/bitstring>>,C,Acc) ->
@@ -306,6 +321,7 @@
     exit({error,{asn1,{illegal_value,C,Octets}}})
     end;
 decode_fragmented_octets(<<0:1,Len:7,BitStr/bitstring>>,C,Acc) ->
+    check_bin_size(BitStr,Len),
     <<Value:Len/binary-unit:8,BitStr2/binary>> = BitStr,
     BinOctets = list_to_binary(lists:reverse([Value|Acc])),
     case C of
@@ -571,13 +587,17 @@
     {Ints,Bytes3} = getoctets_as_bin(Bytes2,Len),
     {dec_integer(Ints),Bytes3}.
 
+dec_integer(Bin) when bit_size(Bin) < 8->
+    throw({error, incomplete});
 dec_integer(Bin = <<0:1,_:7,_/bitstring>>) ->  
     decpint(Bin);
 dec_integer(<<_:1,B:7,BitStr/bitstring>>) ->
     Size = bit_size(BitStr),
     <<I:Size>> = BitStr,
     (-128 + B) bsl bit_size(BitStr) bor I.
-    
+
+decpint(<<>>) ->
+    throw({error, incomplete});
 decpint(Bin) ->
     Size = bit_size(Bin),
     <<Int:Size>> = Bin,
@@ -642,6 +662,10 @@
     {Val,Rest};
 decode_length(<<3:2,_:14,_Rest/bitstring>>,undefined)  ->
     exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
+decode_length(Buffer, undefined) when bit_size(Buffer) < 8 ->
+    throw({error, incomplete});
+decode_length(<<1:1,Rest/bitstring>>,undefined) when bit_size(Rest) < 15 ->
+    throw({error, incomplete});
 
 decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
     decode_constrained_number(Buffer,{Lb,Ub});
@@ -661,12 +685,15 @@
  <<2:2,Val:14,Rest/bitstring>> ->
     {Val,Rest};
  <<3:2,_:14,_Rest/bitstring>> ->
-    exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
+    exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}});
+ <<1:1,Rest/bitstring>> when bit_size(Rest) < 15 ->
+    throw({error, incomplete});
+        Bin when bit_size(Bin) < 8 ->
+    throw({error, incomplete})
     end;
 decode_length(Buffer,SingleValue) when is_integer(SingleValue) ->
     {SingleValue,Buffer}.
 
-
  % X.691:11
 encode_boolean(true) ->
     <<1:1>>;
@@ -1560,6 +1587,7 @@
 %% decode_real({Name,Val}) -> {REALvalue,Rest}
 decode_real(Bytes) ->
     {Len,Bytes2} = decode_length(Bytes,undefined),
+    check_bin_size(Bytes2,Len),
     <<Bytes3:Len/binary,Rest/bitstring>> = Bytes2,
     {RealVal,Rest,Len} = ?RT_COMMON:decode_real(Bytes3,Len),
     {RealVal,Rest}.
@@ -1633,3 +1661,17 @@
     10;
 num_bits(R) ->
     1+num_bits(R bsr 1).
+
+check_bin_size(Binary,ExpectedSize) ->
+    case size(Binary) of
+ Size when Size < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.
+
+check_bit_size(BitString,ExpectedSize) ->
+    case bit_size(BitString) of
+ BitSize when BitSize < ExpectedSize ->
+    throw({error,incomplete});
+ _ -> ok
+    end.



________________________________________________________________
erlang-patches mailing list. See http://www.erlang.org/faq.html
erlang-patches (at) erlang.org