]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - pyderasn.py
BER additional tests
[pyderasn.git] / pyderasn.py
index 50479c60a9d47b3266975178bbfb25ecdff9e841..391ff9ea1b456f68d5f761b5be60089220b9d83b 100755 (executable)
@@ -369,10 +369,6 @@ useful for SEQUENCE/SET OF-s.
 BER encoding
 ------------
 
-.. warning::
-
-   Currently BER support is not extensively tested.
-
 By default PyDERASN accepts only DER encoded data. It always encodes to
 DER. But you can optionally enable BER decoding with setting ``bered``
 :ref:`context <ctx>` argument to True. Indefinite lengths and
@@ -2009,9 +2005,7 @@ class BitString(Obj):
                         len(value) * 4,
                         hexdec(value + ("" if len(value) % 2 == 0 else "0")),
                     )
-                else:
-                    raise InvalidValueType((self.__class__, string_types, binary_type))
-            elif isinstance(value, binary_type):
+            if isinstance(value, binary_type):
                 return (len(value) * 8, value)
             else:
                 raise InvalidValueType((self.__class__, string_types, binary_type))
@@ -2223,7 +2217,7 @@ class BitString(Obj):
                     decode_path=decode_path,
                     offset=offset,
                 )
-            if l > 0 and l > len(v):
+            if l > len(v):
                 raise NotEnoughData(
                     "encoded length is longer than data",
                     klass=self.__class__,
@@ -2251,7 +2245,7 @@ class BitString(Obj):
                         raise DecodeError(
                             "chunk out of bounds",
                             klass=self.__class__,
-                            decode_path=len(chunks) - 1,
+                            decode_path=decode_path + (str(len(chunks) - 1),),
                             offset=chunks[-1].offset,
                         )
                 sub_decode_path = decode_path + (str(len(chunks)),)
@@ -2286,7 +2280,7 @@ class BitString(Obj):
             for chunk_i, chunk in enumerate(chunks[:-1]):
                 if chunk.bit_len % 8 != 0:
                     raise DecodeError(
-                        "BitString chunk is not multiple of 8 bit",
+                        "BitString chunk is not multiple of 8 bits",
                         klass=self.__class__,
                         decode_path=decode_path + (str(chunk_i),),
                         offset=chunk.offset,
@@ -2591,20 +2585,13 @@ class OctetString(Obj):
                     decode_path=decode_path,
                     offset=offset,
                 )
-            if l > 0 and l > len(v):
+            if l > len(v):
                 raise NotEnoughData(
                     "encoded length is longer than data",
                     klass=self.__class__,
                     decode_path=decode_path,
                     offset=offset,
                 )
-            if not lenindef and l == 0:
-                raise NotEnoughData(
-                    "zero length",
-                    klass=self.__class__,
-                    decode_path=decode_path,
-                    offset=offset,
-                )
             chunks = []
             sub_offset = offset + tlen + llen
             vlen = 0
@@ -2619,7 +2606,7 @@ class OctetString(Obj):
                         raise DecodeError(
                             "chunk out of bounds",
                             klass=self.__class__,
-                            decode_path=len(chunks) - 1,
+                            decode_path=decode_path + (str(len(chunks) - 1),),
                             offset=chunks[-1].offset,
                         )
                 sub_decode_path = decode_path + (str(len(chunks)),)
@@ -2642,13 +2629,6 @@ class OctetString(Obj):
                 sub_offset += chunk.tlvlen
                 vlen += chunk.tlvlen
                 v = v_tail
-            if len(chunks) == 0:
-                raise DecodeError(
-                    "no chunks",
-                    klass=self.__class__,
-                    decode_path=decode_path,
-                    offset=offset,
-                )
             try:
                 obj = self.__class__(
                     value=b"".join(bytes(chunk) for chunk in chunks),
@@ -4036,29 +4016,27 @@ class Any(Obj):
             llen, vlen, v = 1, 0, lv[1:]
             sub_offset = offset + tlen + llen
             chunk_i = 0
-            while True:
-                if v[:EOC_LEN].tobytes() == EOC:
-                    tlvlen = tlen + llen + vlen + EOC_LEN
-                    obj = self.__class__(
-                        value=tlv[:tlvlen].tobytes(),
-                        expl=self._expl,
-                        optional=self.optional,
-                        _decoded=(offset, 0, tlvlen),
-                    )
-                    obj.lenindef = True
-                    obj.tag = t
-                    return obj, v[EOC_LEN:]
-                else:
-                    chunk, v = Any().decode(
-                        v,
-                        offset=sub_offset,
-                        decode_path=decode_path + (str(chunk_i),),
-                        leavemm=True,
-                        ctx=ctx,
-                    )
-                    vlen += chunk.tlvlen
-                    sub_offset += chunk.tlvlen
-                    chunk_i += 1
+            while v[:EOC_LEN].tobytes() != EOC:
+                chunk, v = Any().decode(
+                    v,
+                    offset=sub_offset,
+                    decode_path=decode_path + (str(chunk_i),),
+                    leavemm=True,
+                    ctx=ctx,
+                )
+                vlen += chunk.tlvlen
+                sub_offset += chunk.tlvlen
+                chunk_i += 1
+            tlvlen = tlen + llen + vlen + EOC_LEN
+            obj = self.__class__(
+                value=tlv[:tlvlen].tobytes(),
+                expl=self._expl,
+                optional=self.optional,
+                _decoded=(offset, 0, tlvlen),
+            )
+            obj.lenindef = True
+            obj.tag = t
+            return obj, v[EOC_LEN:]
         except DecodeError as err:
             raise err.__class__(
                 msg=err.msg,
@@ -4712,6 +4690,16 @@ class Set(Sequence):
             _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)),
         )
         obj._value = values
+        if lenindef:
+            if v[:EOC_LEN].tobytes() != EOC:
+                raise DecodeError(
+                    "no EOC",
+                    klass=self.__class__,
+                    decode_path=decode_path,
+                    offset=offset,
+                )
+            tail = v[EOC_LEN:]
+            obj.lenindef = True
         if not obj.ready:
             raise DecodeError(
                 "not all values are ready",
@@ -4719,8 +4707,7 @@ class Set(Sequence):
                 decode_path=decode_path,
                 offset=offset,
             )
-        obj.lenindef = lenindef
-        return obj, (v[EOC_LEN:] if lenindef else tail)
+        return obj, tail
 
 
 class SequenceOf(Obj):
@@ -4977,10 +4964,19 @@ class SequenceOf(Obj):
             expl=self._expl,
             default=self.default,
             optional=self.optional,
-            _decoded=(offset, llen, vlen),
+            _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)),
         )
-        obj.lenindef = lenindef
-        return obj, (v[EOC_LEN:] if lenindef else tail)
+        if lenindef:
+            if v[:EOC_LEN].tobytes() != EOC:
+                raise DecodeError(
+                    "no EOC",
+                    klass=self.__class__,
+                    decode_path=decode_path,
+                    offset=offset,
+                )
+            obj.lenindef = True
+            tail = v[EOC_LEN:]
+        return obj, tail
 
     def __repr__(self):
         return "%s[%s]" % (