]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - pyderasn.py
No to double quotes
[pyderasn.git] / pyderasn.py
index 6e772e09b5870c743b5c9228d3027a8d1cef35bf..a048f4d3990c85e899f10a1f96179a89217da7aa 100755 (executable)
@@ -850,6 +850,7 @@ class Obj(object):
         "llen",
         "vlen",
         "bered",
+        "expl_bered",
     )
 
     def __init__(
@@ -872,6 +873,7 @@ class Obj(object):
         self.offset, self.llen, self.vlen = _decoded
         self.default = None
         self.bered = False
+        self.expl_bered = False
 
     @property
     def ready(self):  # pragma: no cover
@@ -982,6 +984,35 @@ class Obj(object):
                 )
             try:
                 l, llen, v = len_decode(lv)
+            except LenIndefiniteForm as err:
+                if not ctx.get("bered", False):
+                    raise err.__class__(
+                        msg=err.msg,
+                        klass=self.__class__,
+                        decode_path=decode_path,
+                        offset=offset,
+                    )
+                llen, v = 1, lv[1:]
+                offset += tlen + llen
+                result = self._decode(
+                    v,
+                    offset=offset,
+                    decode_path=decode_path,
+                    ctx=ctx,
+                    tag_only=tag_only,
+                )
+                if tag_only:
+                    return
+                obj, tail = result
+                eoc_expected, tail = tail[:EOC_LEN], tail[EOC_LEN:]
+                if eoc_expected.tobytes() != EOC:
+                    raise DecodeError(
+                        msg="no EOC",
+                        decode_path=decode_path,
+                        offset=offset,
+                    )
+                obj.vlen += EOC_LEN
+                obj.expl_bered = True
             except DecodeError as err:
                 raise err.__class__(
                     msg=err.msg,
@@ -989,23 +1020,24 @@ class Obj(object):
                     decode_path=decode_path,
                     offset=offset,
                 )
-            if l > len(v):
-                raise NotEnoughData(
-                    "encoded length is longer than data",
-                    klass=self.__class__,
+            else:
+                if l > len(v):
+                    raise NotEnoughData(
+                        "encoded length is longer than data",
+                        klass=self.__class__,
+                        decode_path=decode_path,
+                        offset=offset,
+                    )
+                result = self._decode(
+                    v,
+                    offset=offset + tlen + llen,
                     decode_path=decode_path,
-                    offset=offset,
+                    ctx=ctx,
+                    tag_only=tag_only,
                 )
-            result = self._decode(
-                v,
-                offset=offset + tlen + llen,
-                decode_path=decode_path,
-                ctx=ctx,
-                tag_only=tag_only,
-            )
-            if tag_only:
-                return
-            obj, tail = result
+                if tag_only:
+                    return
+                obj, tail = result
         return obj, (tail if leavemm else tail.tobytes())
 
     @property
@@ -1022,6 +1054,8 @@ class Obj(object):
 
     @property
     def expl_llen(self):
+        if self.expl_bered:
+            return 1
         return len(len_encode(self.tlvlen))
 
     @property
@@ -3852,7 +3886,49 @@ class Any(Obj):
     def _decode(self, tlv, offset, decode_path, ctx, tag_only):
         try:
             t, tlen, lv = tag_strip(tlv)
+        except DecodeError as err:
+            raise err.__class__(
+                msg=err.msg,
+                klass=self.__class__,
+                decode_path=decode_path,
+                offset=offset,
+            )
+        try:
             l, llen, v = len_decode(lv)
+        except LenIndefiniteForm as err:
+            if not ctx.get("bered", False):
+                raise err.__class__(
+                    msg=err.msg,
+                    klass=self.__class__,
+                    decode_path=decode_path,
+                    offset=offset,
+                )
+            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.bered = 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
         except DecodeError as err:
             raise err.__class__(
                 msg=err.msg,
@@ -4199,8 +4275,19 @@ class Sequence(Obj):
             )
         if tag_only:
             return
+        eoc_expected = False
         try:
             l, llen, v = len_decode(lv)
+        except LenIndefiniteForm as err:
+            if not ctx.get("bered", False):
+                raise err.__class__(
+                    msg=err.msg,
+                    klass=self.__class__,
+                    decode_path=decode_path,
+                    offset=offset,
+                )
+            l, llen, v = 0, 1, lv[1:]
+            eoc_expected = True
         except DecodeError as err:
             raise err.__class__(
                 msg=err.msg,
@@ -4215,11 +4302,16 @@ class Sequence(Obj):
                 decode_path=decode_path,
                 offset=offset,
             )
-        v, tail = v[:l], v[l:]
+        if not eoc_expected:
+            v, tail = v[:l], v[l:]
+        vlen = 0
         sub_offset = offset + tlen + llen
         values = {}
         for name, spec in self.specs.items():
-            if len(v) == 0 and spec.optional:
+            if spec.optional and (
+                (eoc_expected and v[:EOC_LEN].tobytes() == EOC) or
+                len(v) == 0
+            ):
                 continue
             sub_decode_path = decode_path + (name,)
             try:
@@ -4282,7 +4374,9 @@ class Sequence(Obj):
                         )
                     value.defined = (defined_by, defined_value)
 
-            sub_offset += (value.expl_tlvlen if value.expled else value.tlvlen)
+            value_len = value.expl_tlvlen if value.expled else value.tlvlen
+            vlen += value_len
+            sub_offset += value_len
             v = v_tail
             if spec.default is not None and value == spec.default:
                 if ctx.get("strict_default_existence", False):
@@ -4309,7 +4403,17 @@ class Sequence(Obj):
                             abs_decode_path(sub_decode_path[:-1], rel_path),
                             (value, defined),
                         ))
-        if len(v) > 0:
+        if eoc_expected:
+            if v[:EOC_LEN].tobytes() != EOC:
+                raise DecodeError(
+                    "no EOC",
+                    klass=self.__class__,
+                    decode_path=decode_path,
+                    offset=offset,
+                )
+            tail = v[EOC_LEN:]
+            vlen += EOC_LEN
+        elif len(v) > 0:
             raise DecodeError(
                 "remaining data",
                 klass=self.__class__,
@@ -4322,9 +4426,11 @@ class Sequence(Obj):
             expl=self._expl,
             default=self.default,
             optional=self.optional,
-            _decoded=(offset, llen, l),
+            _decoded=(offset, llen, vlen),
         )
         obj._value = values
+        if eoc_expected:
+            obj.bered = True
         return obj, tail
 
     def __repr__(self):
@@ -4395,8 +4501,19 @@ class Set(Sequence):
             )
         if tag_only:
             return
+        eoc_expected = False
         try:
             l, llen, v = len_decode(lv)
+        except LenIndefiniteForm as err:
+            if not ctx.get("bered", False):
+                raise err.__class__(
+                    msg=err.msg,
+                    klass=self.__class__,
+                    decode_path=decode_path,
+                    offset=offset,
+                )
+            l, llen, v = 0, 1, lv[1:]
+            eoc_expected = True
         except DecodeError as err:
             raise err.__class__(
                 msg=err.msg,
@@ -4410,11 +4527,15 @@ class Set(Sequence):
                 klass=self.__class__,
                 offset=offset,
             )
-        v, tail = v[:l], v[l:]
+        if not eoc_expected:
+            v, tail = v[:l], v[l:]
+        vlen = 0
         sub_offset = offset + tlen + llen
         values = {}
         specs_items = self.specs.items
         while len(v) > 0:
+            if eoc_expected and v[:EOC_LEN].tobytes() == EOC:
+                break
             for name, spec in specs_items():
                 sub_decode_path = decode_path + (name,)
                 try:
@@ -4442,9 +4563,9 @@ class Set(Sequence):
                 decode_path=sub_decode_path,
                 ctx=ctx,
             )
-            sub_offset += (
-                value.expl_tlvlen if value.expled else value.tlvlen
-            )
+            value_len = value.expl_tlvlen if value.expled else value.tlvlen
+            sub_offset += value_len
+            vlen += value_len
             v = v_tail
             if spec.default is None or value != spec.default:  # pragma: no cover
                 # SeqMixing.test_encoded_default_accepted covers that place
@@ -4455,9 +4576,19 @@ class Set(Sequence):
             expl=self._expl,
             default=self.default,
             optional=self.optional,
-            _decoded=(offset, llen, l),
+            _decoded=(offset, llen, vlen + (EOC_LEN if eoc_expected else 0)),
         )
         obj._value = values
+        if not obj.ready:
+            raise DecodeError(
+                msg="not all values are ready",
+                klass=self.__class__,
+                decode_path=decode_path,
+                offset=offset,
+            )
+        if eoc_expected:
+            obj.bered = True
+            tail = v[EOC_LEN:]
         return obj, tail
 
 
@@ -4659,8 +4790,19 @@ class SequenceOf(Obj):
             )
         if tag_only:
             return
+        eoc_expected = False
         try:
             l, llen, v = len_decode(lv)
+        except LenIndefiniteForm as err:
+            if not ctx.get("bered", False):
+                raise err.__class__(
+                    msg=err.msg,
+                    klass=self.__class__,
+                    decode_path=decode_path,
+                    offset=offset,
+                )
+            l, llen, v = 0, 1, lv[1:]
+            eoc_expected = True
         except DecodeError as err:
             raise err.__class__(
                 msg=err.msg,
@@ -4675,11 +4817,15 @@ class SequenceOf(Obj):
                 decode_path=decode_path,
                 offset=offset,
             )
-        v, tail = v[:l], v[l:]
+        if not eoc_expected:
+            v, tail = v[:l], v[l:]
+        vlen = 0
         sub_offset = offset + tlen + llen
         _value = []
         spec = self.spec
         while len(v) > 0:
+            if eoc_expected and v[:EOC_LEN].tobytes() == EOC:
+                break
             value, v_tail = spec.decode(
                 v,
                 sub_offset,
@@ -4687,7 +4833,9 @@ class SequenceOf(Obj):
                 decode_path=decode_path + (str(len(_value)),),
                 ctx=ctx,
             )
-            sub_offset += (value.expl_tlvlen if value.expled else value.tlvlen)
+            value_len = value.expl_tlvlen if value.expled else value.tlvlen
+            sub_offset += value_len
+            vlen += value_len
             v = v_tail
             _value.append(value)
         obj = self.__class__(
@@ -4698,8 +4846,11 @@ class SequenceOf(Obj):
             expl=self._expl,
             default=self.default,
             optional=self.optional,
-            _decoded=(offset, llen, l),
+            _decoded=(offset, llen, vlen),
         )
+        if eoc_expected:
+            obj.bered = True
+            tail = v[EOC_LEN:]
         return obj, tail
 
     def __repr__(self):
@@ -4843,13 +4994,10 @@ def main():  # pragma: no cover
         pprinter = partial(pprint, big_blobs=True)
     else:
         schema, pprinter = generic_decoder()
-    obj, tail = schema().decode(
-        der,
-        ctx=(
-            None if args.defines_by_path is None else
-            {"defines_by_path": obj_by_path(args.defines_by_path)}
-        ),
-    )
+    ctx = {"bered": True}
+    if args.defines_by_path is not None:
+        ctx["defines_by_path"] = obj_by_path(args.defines_by_path)
+    obj, tail = schema().decode(der, ctx=ctx)
     print(pprinter(
         obj,
         oids=oids,